Il existe un attribut dynamique pratique dans l'enregistrement actif appelé find_or_create_by:
Model.find_or_create_by_<attribute>(:<attribute> => "")
Mais que faire si j'ai besoin de trouver_ou_créer par plus d'un attribut?
Disons que j'ai un modèle pour gérer une relation M: M entre le groupe et le membre appelé GroupMember. Je pourrais avoir de nombreuses instances où member_id = 4, mais je ne veux jamais plus d'une fois où member_id = 4 et group_id = 7. J'essaie de comprendre s'il est possible de faire quelque chose comme ceci:
GroupMember.find_or_create(:member_id => 4, :group_id => 7)
Je me rends compte qu'il peut y avoir de meilleures façons de gérer cela, mais j'aime la commodité de l'idée de find_or_create.
Pour toute autre personne qui tombe sur ce fil mais doit trouver ou créer un objet avec des attributs qui peuvent changer selon les circonstances, ajoutez la méthode suivante à votre modèle:
Conseil d'optimisation: quelle que soit la solution que vous choisissez, pensez à ajouter des index pour les attributs que vous interrogez le plus fréquemment.
la source
find_or_create_by
sera.Model.where(attributes).instance_eval{|q| q.first || q.create}
.find_or_create
a également l'avantage d'utiliser une transaction, oùwhere….first || create
introduit une condition dedef self.find_or_create(attributes) self.where(attributes).first || self.create(attributes) end
pour que vous n'ayez pas besoin de répéterModel
self
intérieur du corps de la méthode (puisque vous cherchez à supprimer des mots!).Dans Rails 4, vous pouvez faire:
Et l'utilisation
where
est différente:Cela fera appel
create
àGroupMember.where(member_id: 4, group_id: 7)
:Au contraire, la
find_or_create_by(member_id: 4, group_id: 7)
volonté fera appelcreate
àGroupMember
:Veuillez consulter ce commit pertinent sur rails / rails.
la source
En passant un bloc à
find_or_create
, vous pouvez passer des paramètres supplémentaires qui seront ajoutés à l'objet s'il est créé nouveau. Ceci est utile si vous validez la présence d'un champ que vous ne recherchez pas.En supposant:
puis
va créer un nouveau GroupMember avec le nom "John Doe" s'il n'en trouve pas un avec
member_id 4
and group_id 7
la source
Tu peux faire:
Ou pour simplement initialiser:
la source