web-dev-qa-db-ja.com

has_manyアソシエーションに「first_or_build」メソッドはありますか?

Rails 3.2+では、これを行うことができます:

SomeModel.some_scope.first_or_initialize

つまり、次のこともできます。

OtherModel.some_models.first_or_initialize

これは非常に便利だと思いますが、first_or_buildアソシエーションにhas_manyメソッドを設定したいと思います。これはfirst_or_initializeのように機能しますが、も追加します必要に応じてbuildが行うように、関連付けへの新しいレコード

説明のための更新:はい、first_or_initializefirst_or_createについて知っています。つまり、first_or_initializebuildのように初期化されたレコードをアソシエーションのターゲットに追加せず、first_or_create...まあ...createsレコード。これは意図されたものではありません。

関連付け拡張機能を使用して機能するソリューションがあります:

class OtherModel < ActiveRecord::Base

  has_many :some_models do 
    def first_or_build( attributes = {}, options = {}, &block )
      object = first_or_initialize( attributes, options, &block )
      proxy_association.add_to_target( object ) if object.new_record?
      object
    end
  end

end

私は:かどうか疑問に思います

  • この問題に対する組み込みの解決策はすでに存在しますか?
  • 私の実装には私が見ない欠陥がありますか?
32
m_x

Railsに組み込まれているものが、あなたが望むことを正確に実行するかどうかはわかりませんが、現在使用しているよりも簡潔な拡張子でfirst_or_initializeコードを模倣することができます。必要な処理を実行し、次のような再利用可能な拡張機能にラップします。これは、Rails 3.2拡張形式で記述されています。

module FirstOrBuild
  def first_or_build(attributes = nil, options = {}, &block)
    first || build(attributes, options, &block)
  end
end

class OtherModel < ActiveRecord::Base
  has_many :some_models, :extend => FirstOrBuild
end
21
Bryan Corey