Rails 6重写部分继承的控制器方法- DRY



我想要符合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,因为您对该特性不感兴趣。你只需要方法的继承。

你甚至可以消除createShareBuysController,只是把before_create { @transaction=ShareBuysTransaction.new(wallet,transaction_params)和BaseTransactionsController做before_create {@transaction=BaseTransaction.new(wallet, transaction_params)。哦,真干!

最新更新