我想要符合DRY原则,这就是为什么我试图重构我的控制器。我有BaseController
作为父母和ShareBuysController
作为孩子,如下所示:
# base_controller.rb
class BaseController < ApplicationController
def create
@transaction = wallet.transactions.new(transaction_params) do |t|
t.transaction_type = transaction_type
end
if @transaction.save
success_response
else
failure_response
end
end
end
# share_buys_controller.rb
class ShareBuysController < BaseController
def create
@transaction = wallet.transactions.new(transaction_params) do |t|
t.transaction_type = transaction_type
# new lines of code
t.amount = calculate_shares_amount(params[:transaction][:shares_number])
t.to_wallet = portfolio.wallet
end
if @transaction.save
# new lines of code
recalculate_balance!
recalculate_portfolio_balance!(@transaction)
success_response
else
failure_response
end
end
end
是否有一种方法来添加这些行代码,我已经标记了# new lines of code
和其他一切可以保持不变?或者我必须像我那样重写整个create
方法?
我会将大部分代码重构为模型。沿着旧范式的路线"胖模型瘦控制器"。我不太了解你的应用,但这种重构可能是合适的:
# base_controller.rb
class BaseController < ApplicationController
def create
@transaction = BaseTransaction.new(wallet, transaction_params)
if @transaction.save
success_response
else
failure_response
end
end
end
# share_buys_controller.rb
class ShareBuysController < BaseController
def create
@transaction = ShareBuysTransaction.new(wallet, transaction_params)
if @transaction.save
success_response
else
failure_response
end
end
end
# models/base_transaction.rb
class BaseTransaction < Transaction
def initialize(wallet, params)
self.wallet_id = wallet.id
self.transaction_type = transaction_type
super
end
end
# models/share_buys_transaction.rb
class ShareBuysTransaction < Transaction
after_save :recalc
def initialize(wallet, params)
self.wallet_id = wallet.id
self.transaction_type = transaction_type
self.amount = calculate_shares_amount(params[:transaction][:shares_number])
self.to_wallet = portfolio.wallet
super
end
def recalc
recalculate_balance! # where is this defined? class method?
self.recalculate_portfolio_balance!
end
end
我假设你有一个Transaction
模型继承自ActiveRecord::Base
。
我敢肯定有一些错误在这个代码b/c有很多关于你的应用程序我不知道,但希望你能看到的图片,使其工作。您甚至可以从BaseTransaction
继承ShareBuysTransaction
,并在其初始化方法中使用super
,以节省几行。
您必须禁用事务模型的STI,因为您对该特性不感兴趣。你只需要方法的继承。
你甚至可以消除create
从ShareBuysController
,只是把before_create { @transaction=ShareBuysTransaction.new(wallet,transaction_params)
和BaseTransactionsController做before_create {@transaction=BaseTransaction.new(wallet, transaction_params)
。哦,真干!