多个方法期间Ruby救援异常

gzjq41n4  于 2023-08-04  发布在  Ruby
关注(0)|答案(4)|浏览(148)

我已经建立了一个简单的银行应用程序,它能够执行通常的操作;存款、取款等
我的控制器方法执行这些操作,并拯救由帐户或其他实体引发的异常。

下面是控制器代码中使用的一些方法:

def open(type, with:)
    account = create type, (holders.find with)
    add account
    init_yearly_interest_for account
    boundary.render AccountSuccessMessage.new(account)
  rescue ItemExistError => message
    boundary.render message
  end

  def deposit(amount, into:)
    account = find into
    account.deposit amount
    boundary.render DepositSuccessMessage.new(amount)
  rescue ItemExistError => message
    boundary.render message
  end

  def withdraw(amount, from:)
    account = find from
    init_limit_reset_for account unless account.breached?
    account.withdraw amount
    boundary.render WithdrawSuccessMessage.new(amount)
  rescue ItemExistError, OverLimit, InsufficientFunds => message
    boundary.render message
  end

  def get_balance_of(id)
    account = find id
    boundary.render BalanceMessage.new(account)
  rescue ItemExistError => message
    boundary.render message
  end

  def transfer(amount, from:, to:)
    donar = find from
    recipitent = find to
    init_limit_reset_for donar unless donar.breached?
    donar.withdraw amount
    recipitent.deposit amount
    boundary.render TransferSuccessMessage.new(amount)
  rescue ItemExistError, OverLimit, InsufficientFunds => message
    boundary.render message
  end

  def add_holder(id, to:)
    holder = holders.find id
    account = find to
    account.add_holder holder
    boundary.render AddHolderSuccessMessage.new(holder, account)
  rescue ItemExistError, HolderOnAccount => message
    boundary.render message
  end

  def get_transactions_of(id)
    transactions = (find id).transactions
    boundary.render TransactionsMessage.new(transactions)
  rescue ItemExistError => message
    boundary.render message
  end

  def get_accounts_of(id)
    holder = holders.find id
    accounts = store.select { |_, a| a.holder? holder }.values
    boundary.render DisplayAccountsMessage.new(accounts)
  rescue ItemExistError => message
    boundary.render message
  end

字符串
正如你所看到的,我在多个方法中拯救了多个错误,通常处理相同的错误。
虽然这是工作,我想知道是否有可能重构和处理这些异常时,任何控制器中的方法被调用。
例如:

during: 
  open, deposit, withdraw
rescue ItemExistError => message
  boundary.render message


如有任何帮助,我们将不胜感激。

lzfw57am

lzfw57am1#

通过元编程,您可以定义一个方法来 Package 您希望从中拯救的每个方法。这是不是真正更干净的代码由您决定。

class MyController
  # define a unified exception handler for some methods
  def self.rescue_from *meths, exception, &handler
    meths.each do |meth|
      # store the previous implementation
      old = instance_method(meth)
      # wrap it
      define_method(meth) do |*args|
        begin
          old.bind(self).call(*args)
        rescue exception => e
          handler.call(e)
        end
      end
    end
  end

  rescue_from :open, :deposit, :withdraw, ItemExistError do |message|
    boundary.render message
  end
end

字符串
如果你不打算重用这个方法(即如果你只想为这一组方法和这一个异常类提供一个统一的处理程序),我会删除rescue_from定义,并将元编程代码放在该类中。

zsbz8rwp

zsbz8rwp2#

你可以试着写一个这样的方法:

def call_and_rescue
  yield if block_given?
rescue ItemExistError => message
  boundary.render message
end

字符串
然后使用它:第一个月

alen0pnh

alen0pnh3#

Rails的ActiveSupport gem提供了rescue_from helper:
https://edgeapi.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html#method-i-rescue_from

class MyController < ApplicationController
  rescue_from ItemExistError, with: :item_exist_error

  def get_transactions_of(id)
    transactions = (find id).transactions
    boundary.render TransactionsMessage.new(transactions)
  end

  def get_accounts_of(id)
    holder = holders.find id
    accounts = store.select { |_, a| a.holder? holder }.values
    boundary.render DisplayAccountsMessage.new(accounts)
  end

  private

  def item_exist_error(_exception)
    boundary.render message
  end
end

字符串

l7mqbcuq

l7mqbcuq4#

前后风格回调会有帮助吗?

存储回调动作列表的变量

@before_actions = Hash.new {|hash,key| hash[key] = Array.new}
@after_actions = Hash.new {|hash,key| hash[key] = Array.new}

字符串

定义before_action方法action是要执行的回调,methods是一个action数组,这些action都有回调分配给它们

def before_action(action, methods)  
  methods.each do |m|
    @before_actions[m] << action
  end
end

def after_action(action, methods)  
  methods.each do |m|
    @after_actions[m] << action
  end
end

在我们的方法中使用的块,允许我们使用这些回调

def execute_callbacks  
  @before_actions.each {|k,v| v.each {|v| send(v)}}
  yield
  @after_actions.each {|k,v| v.each {|v| send(v)}}
end

声明我们希望发生的before和after操作(可能会将#first_do_this和#lastly_do_this等回调函数作为私有方法?)

before_action :first_do_this, [:do_something]  
after_action :lastly_do_this, [:do_something]

private
def first_do_this  
  puts "this occurs first"
end

def lastly_do_this  
  puts "this occurs last"
end

我们想要解决的方法。(我知道它不是那么优雅,它可以改进)

def do_something  
  execute_callbacks do
    puts "hello world"
  end
end

调用do_something时

do_something # =>
  this occurs first
  hello world
  this occurs last

相关问题