假设我有一个Account类和一个AccountReport类。在帐户#show中,我想显示一个帐户的报告。 Account和AccountReport都有许多公共方法。以下哪种技术更好?
1)实例化帐户和AccountReport,使用帐户数据初始化AccountReport。
class AccountsController < ActionController::Base
def show
@account = current_user.account
@account_report = AccountReport.new(@account.orders)
respond_with(@account)
end
# ...
end
2)允许Account实例实例化AccountReport并委托方法调用
class Account < ActiveRecord::Base
attr_reader :account_report
delegate :method_a, :method_b, :method_c, :method_d, :to => :account_report
after_initialize :setup_account_report
def setup_account_report
@account_report = AccountReport.new(orders)
end
# ...
end
选项2对我来说似乎是一种更清洁的方法,但是用很多方法加载帐户会使它感觉像上帝一样。
答案 0 :(得分:2)
好吧,我认为你必须混合两种选择。
如果你只使用show上的报告,第一个是好的。 如果您为帐户使用所有时间报告,则第二个是好的。
使用第二个,您的报告将一直实例化,这可能会降低性能。
你应该尝试这样的事情:
class Account < ActiveRecord::Base
# ...
@report = nil
def report
if @report.nil?
@report = AccountReport.new(self.orders)
end
end
# ...
end
此解决方案的好处是报表仅在需要时加载,但不会每次都加载。 这个解决方案的坏处是,如果你添加一些订单,你的报告就不会是最新的。
<强>更新强> 要改善这一点,您可以用这个替换条件
if @report.nil || self.created_at_changed?
答案 1 :(得分:0)
我喜欢第一个选项,因为它保持低耦合。第二个选项以可能不必要的方式将Account和AccountReport绑定在一起。每当您收到其他类型的报告时会发生什么?您可能需要更改Account中的一堆内容,这很难过,因为它们看似无关。
您可以通过在服务对象中组合这两个内容并将其交给您的视图来控制控制器中的逻辑/详细程度。 AccountReporting
服务可以处理将这两个类组合在一起的逻辑,例如:
class AccountReporting
def initialize(account)
@account = account
end
def report
AccountReport.new(account.orders)
end
end
然后,在控制器中使用它:
AccountReporting.new(current_user.account)
这有意义吗?