4

我有两个模型

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

is_live 是合同模型中的布尔字段。合约在创建时默认为不存在(is_live => false)。当第一笔交易被记录时,它被标记为实时(is_live => true)。使用上面的解决方案,这意味着每次创建事务都需要调用数据库来检查合约是否处于活动状态。有没有替代方案?

如果合约有数千笔交易,这意味着这将被调用数千次,尽管它只与第一笔交易相关。

在一般意义上,什么是实现回调的优雅方式。这看起来很乱?

4

1 回答 1

5
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

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

但因为它是一个非常短的方法,它可能不值得。

另请注意,ActiveRecord添加了类似xxx?布尔字段的方法。方法末尾的问号更清楚地传达了您想说的内容。

最后,但这是一个品味问题,我不喜欢在布尔属性前加上is_xxx. 我不使用RSpec并且可能是错误的,但我认为它添加了一些谓词匹配器,例如be_xxx属性xxx,并且属性可能会变得很奇怪is_xxx。因为很多人都在使用RSpec,所以它可能会成为一种惯例。

如果合约有数千笔交易,这意味着这将被调用数千次,尽管它只与第一笔交易相关。

如果您像这样创建事务,该Contract实例仍将被加载contract.transactions.create(transaction_params):因此,拨打电话is_live?将免费,您不必担心。

于 2013-11-01T01:16:48.923 回答