4

私は2つのモデルを持っています

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_liveContractクラスで を作成し、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_xxxxxxis_xxxRSpec

コントラクトに数千のトランザクションがある場合、最初のトランザクションにのみ関連しますが、これは何千回も呼び出されることを意味します。

次のContractようなトランザクションを作成すると、インスタンスは引き続きロードされますcontract.transactions.create(transaction_params)。への電話is_live?は無料ですので、心配する必要はありません。

于 2013-11-01T01:16:48.923 に答える