In Active-Record gibt es ein praktisches dynamisches Attribut namens find_or_create_by:
Model.find_or_create_by_<attribute>(:<attribute> => "")
Aber was ist, wenn ich nach mehr als einem Attribut suchen oder erstellen muss?
Angenommen, ich habe ein Modell für die Behandlung einer M: M-Beziehung zwischen Gruppe und Mitglied namens GroupMember. Ich könnte viele Instanzen haben, in denen member_id = 4 ist, aber ich möchte nie mehr als eine Instanz, in der member_id = 4 und group_id = 7 sind. Ich versuche herauszufinden, ob es möglich ist, so etwas zu tun:
GroupMember.find_or_create(:member_id => 4, :group_id => 7)
Mir ist klar, dass es vielleicht bessere Möglichkeiten gibt, damit umzugehen, aber ich mag die Bequemlichkeit der Idee von find_or_create.
Fügen Sie Ihrem Modell die folgende Methode hinzu, wenn Sie über diesen Thread stolpern, aber ein Objekt mit Attributen suchen oder erstellen müssen, die sich je nach den Umständen ändern können:
Optimierungstipp: Unabhängig davon, für welche Lösung Sie sich entscheiden, sollten Sie Indizes für die Attribute hinzufügen, die Sie am häufigsten abfragen.
quelle
find_or_create_by
ist.Model.where(attributes).instance_eval{|q| q.first || q.create}
.find_or_create
hat auch den Vorteil, eine Transaktion zu verwenden, beiwhere….first || create
der eine Rennbedingung eingeführt wirddef self.find_or_create(attributes) self.where(attributes).first || self.create(attributes) end
damit Sie nicht wiederholen müssenModel
self
innerhalb des Methodenkörpers (da Sie Wörter entfernen möchten !).In Rails 4 können Sie Folgendes tun:
Und die Verwendung
where
ist anders:Dies ruft
create
aufGroupMember.where(member_id: 4, group_id: 7)
:Im Gegenteil, die
find_or_create_by(member_id: 4, group_id: 7)
rufencreate
aufGroupMember
:Bitte beachten Sie dieses relevante Commit auf Schienen.
quelle
Durch Übergeben eines Blocks an
find_or_create
können Sie zusätzliche Parameter übergeben, die dem Objekt hinzugefügt werden, wenn es neu erstellt wird. Dies ist nützlich, wenn Sie das Vorhandensein eines Felds überprüfen, nach dem Sie nicht suchen.Angenommen:
dann
erstellt ein neues GroupMember mit dem Namen "John Doe", wenn es keines mit findet
member_id 4
and group_id 7
quelle
Du kannst tun:
Oder einfach zu initialisieren:
quelle