sam*_*mol 3 activerecord ruby-on-rails
我有两个模型
class Contract < ActiveRecord::Base
has_many :transactions
end
class Transaction < ActiveRecord::Base
belongs_to :contract
after_create :mark_contract_as_live
def mark_contract_as_live
k = self.contract
if !k.is_live
k.update_attributes(:is_live => true)
end
end
end
Run Code Online (Sandbox Code Playgroud)
is_live 是 Contract 模型中的布尔字段。合约在创建时默认为无效(is_live => false)。当第一笔交易被记录时,它被标记为实时(is_live => true)。有了上面的解决方案,这意味着每个交易创建都需要调用数据库来检查合约是否有效。有没有替代方法?
如果合约有数千笔交易,这意味着这将被调用数千次,尽管它只与第一笔交易有关。
一般来说,什么是实现回调的优雅方式。这看起来很乱?
class Contract < ActiveRecord::Base
has_many :transactions
def mark_as_live
update(is_live: true) unless is_live?
end
end
class Transaction < ActiveRecord::Base
belongs_to :contract
after_create :mark_contract_as_live
private
def mark_contract_as_live
contract.mark_as_live
end
end
Run Code Online (Sandbox Code Playgroud)
Contract关心合约是否应该被标记为有效是班级的责任。这个Transaction类不应该处理这个。所以我mark_as_live在Contract类中创建了一个并在Transaction after_create回调中调用它。
我更喜欢在mark_as_live方法中使用保护子句,如下所示:
def mark_as_live
return if is_live?
update(is_live: true)
end
Run Code Online (Sandbox Code Playgroud)
但是因为它是一个很短的方法,所以它可能不值得。
还要注意ActiveRecord添加了像xxx?布尔字段这样的方法。方法末尾的问号更清楚地传达了您想说的内容。
最后,但这是一个品味问题,我不喜欢在布尔属性前加上is_xxx. 我不使用RSpec,可能是错的,但我认为,它增加了一些谓词的匹配一样be_xxx的xxx属性,它可能会用怪异的is_xxx属性。因为很多人都在使用RSpec,所以它可能会成为一种惯例。
如果合约有数千笔交易,这意味着这将被调用数千次,尽管它只与第一笔交易有关。
本Contract实例将如果你创建了像这样一个事务中仍然加载:contract.transactions.create(transaction_params)。因此is_live?,您可以免费拨打电话,您不必担心。