206

find_or_create_byと呼ばれるアクティブレコードには便利な動的属性があります。

Model.find_or_create_by_<attribute>(:<attribute> => "")

しかし、複数の属性でfind_or_createする必要がある場合はどうなりますか?

GroupMemberと呼ばれるGroupとMember間のM:M関係を処理するモデルがあるとします。member_id = 4のインスタンスが多数ある可能性がありますが、member_id=4およびgroup_id=7のインスタンスが2回以上必要になることはありません。次のようなことが可能かどうかを調べています。

GroupMember.find_or_create(:member_id => 4, :group_id => 7)

これを処理するためのより良い方法があるかもしれないことを私は理解していますが、find_or_createのアイデアの便利さが好きです。

4

5 に答える 5

476

and複数の属性を:で接続できます。

GroupMember.find_or_create_by_member_id_and_group_id(4, 7)

find_or_initialize_byレコードをすぐに保存したくない場合に使用します)

編集:上記のメソッドはRails4で非推奨になりました。これを行う新しい方法は次のようになります。

GroupMember.where(:member_id => 4, :group_id => 7).first_or_create

GroupMember.where(:member_id => 4, :group_id => 7).first_or_initialize

編集2:これらのすべてがレールから除外されたわけではなく、属性固有のものだけです。

https://github.com/rails/rails/blob/4-2-stable/guides/source/active_record_querying.md

GroupMember.find_or_create_by_member_id_and_group_id(4, 7)

なりました

GroupMember.find_or_create_by(member_id: 4, group_id: 7)
于 2010-06-15T15:31:13.410 に答える
34

このスレッドに出くわしたが、状況に応じて変更される可能性のある属性を持つオブジェクトを検索または作成する必要がある他の人のために、モデルに次のメソッドを追加します。

# Return the first object which matches the attributes hash
# - or -
# Create new object with the given attributes
#
def self.find_or_create(attributes)
  Model.where(attributes).first || Model.create(attributes)
end

最適化のヒント:選択するソリューションに関係なく、最も頻繁にクエリを実行する属性にインデックスを追加することを検討してください。

于 2012-05-26T21:00:42.927 に答える
34

Rails 4では、次のことができます。

GroupMember.find_or_create_by(member_id: 4, group_id: 7)

そして使用法whereは異なります:

GroupMember.where(member_id: 4, group_id: 7).first_or_create

これは次のことを要求createGroupMember.where(member_id: 4, group_id: 7)ます:

GroupMember.where(member_id: 4, group_id: 7).create

それどころか、は次のfind_or_create_by(member_id: 4, group_id: 7)ように呼びかけcreateますGroupMember

GroupMember.create(member_id: 4, group_id: 7)

レール/レールに関するこの関連するコミットを参照してください。

于 2014-01-04T02:37:51.953 に答える
18

ブロックをに渡すことによりfind_or_create、オブジェクトが新しく作成された場合にオブジェクトに追加される追加のパラメーターを渡すことができます。これは、検索していないフィールドの存在を検証する場合に役立ちます。

仮定:

class GroupMember < ActiveRecord::Base
    validates_presence_of :name
end

それから

GroupMember.where(:member_id => 4, :group_id => 7).first_or_create { |gm| gm.name = "John Doe" }

「JohnDoe」という名前の新しいGroupMemberが見つからない場合は、member_id 4 and group_id 7

于 2013-06-19T14:01:27.277 に答える
5

できるよ:

User.find_or_create_by(first_name: 'Penélope', last_name: 'Lopez')
User.where(first_name: 'Penélope', last_name: 'Lopez').first_or_create

または単に初期化するには:

User.find_or_initialize_by(first_name: 'Penélope', last_name: 'Lopez')
User.where(first_name: 'Penélope', last_name: 'Lopez').first_or_initialize
于 2014-08-11T19:54:15.383 に答える