我已经构建了一个简单的银行应用程序,它可以执行常规操作;存款,取款等。
我的控制器方法执行这些操作并挽救帐户或其他实体引发的异常。
以下是控制器代码中使用的一些方法:
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
非常感谢任何帮助。
答案 0 :(得分:6)
您可以尝试编写这样的方法:
def call_and_rescue
yield if block_given?
rescue ItemExistError => message
boundary.render message
end
然后使用它:call_and_rescue { open(type, with) }
答案 1 :(得分:6)
您可以通过定义一个包装您要从中拯救的每个方法的方法,通过元编程来完成此操作。这是你的电话,不管这是否真的更干净。
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
定义并放置元编程代码在课堂上。
答案 2 :(得分:0)
前后样式回调会有帮助吗?
@before_actions = Hash.new {|hash,key| hash[key] = Array.new}
@after_actions = Hash.new {|hash,key| hash[key] = Array.new}
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_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 # =>
this occurs first
hello world
this occurs last