多种方法中的Ruby救援异常

Phi*_*ell 5 ruby rescue

我已经构建了一个简单的银行应用程序,它能够执行常规操作; 存款,提款等

我的控制器方法执行这些操作并挽救帐户或其他实体引发的异常.

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

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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我在多种方法中拯救了多个错误,通常会处理相同的错误.

虽然这是有效的,但我想知道在调用控制器中的任何方法时是否可以重构和处理这些异常.

例如:

during: 
  open, deposit, withdraw
rescue ItemExistError => message
  boundary.render message
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激.

Max*_*Max 7

您可以通过定义一个包装您想要从中拯救的每个方法的方法来进行元编程.这是你的电话,这是否真的更干净的代码.

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
Run Code Online (Sandbox Code Playgroud)

如果您不打算重用该方法(即,如果您只想为这一组方法和这一个异常类使用统一处理程序),我将删除该rescue_from定义并将元编程代码放在类中.


Pio*_*zek 6

您可以尝试编写这样的方法:

def call_and_rescue
  yield if block_given?
rescue ItemExistError => message
  boundary.render message
end
Run Code Online (Sandbox Code Playgroud)

然后使用它: call_and_rescue { open(type, with) }