42 votes

Comment puis-je passer plusieurs attributs à find_or_create_by dans Rails 3 ?

Je veux utiliser find_or_create_by, mais cette instruction ne fonctionne PAS. Elle ne permet pas de "trouver" ou de "créer" avec les autres attributs.

productproperty = ProductProperty.find_or_create_by_product_id(:product_id => product.id, :property_id => property.id, :value => d[descname])

Il semble qu'il y ait très peu, voire aucune, information sur l'utilisation des chercheurs dynamiques dans Rails 3. "L'association de ces deux éléments me donne une erreur de méthode inconnue.

UPDATE :

À l'origine, je n'arrivais pas à faire fonctionner ce qui suit. Veuillez supposer que je ne suis pas un idiot et que "product" est une instance du modèle AR Product.

product.product_properties.find_or_create_by_property_id_and_value(:property_id => 1, :value => "X")

Les méthodes d'erreur étaient :

no such keys: property_id, value

Je n'ai pas réussi à comprendre. Ce n'est que ce matin que j'ai trouvé la référence pour passer les valeurs comme ceci :

product.product_properties.find_or_create_by_property_id_and_value(1, "X")

Et voilà, ça marche bien. Je me serais attendu à ce qu'un hachage fonctionne dans la même situation, mais je suppose que non.

Donc je suppose que tu as un vote négatif si tu rates quelque chose sur internet ?

52voto

Lelon Points 725

Si vous souhaitez effectuer une recherche sur plusieurs attributs, vous pouvez utiliser "et" pour les ajouter. Par exemple :

productproperty = ProductProperty.find_or_create_by_product_id_and_property_id_and_value(:product_id => product.id, :property_id => property.id, :value => d[descname])

Il y a un petit problème dont il faut être conscient. Elle renverra toujours l'objet que vous avez spécifié, même si cet objet ne peut pas être enregistré en raison d'erreurs de validation. Assurez-vous donc de vérifier si l'objet retourné a un id (ou is_valid ?). Ne supposez pas qu'il se trouve dans la base de données.

Vous pouvez également utiliser la version "bang" de la méthode pour déclencher une erreur si l'objet ne peut être sauvegardé :

http://guides.rubyonrails.org/active_record_querying.html#find-or-create-by-bang

Ceci s'applique à Rails 3.

23voto

Lichtamberg Points 6221

Voir http://api.rubyonrails.org/classes/ActiveRecord/Base.html :

Avec un seul paramètre de requête :

productproperty = ProductProperty.find_or_create_by_product_id(product.id) { |u| u.property_id => property_id, u.value => d[descname] } )

ou étendu avec plusieurs paramètres :

productproperty = ProductProperty.find_or_create_by_product_id(:product_id => product.id, :property_id => property_id, :value => d[descname]) { |u| u.property_id => property_id, u.value => d[descname] } )

Travaillerait avec :

conditions = { :product_id => product.id, 
               :property_id => property.id,
               :value => d[descname] }

pp = ProductProperty.find(:first, :conditions => conditions) || ProductProperty.create(conditions)

10voto

Pablo Cantero Points 2746

Vous pouvez également utiliser when(...).first_or_create de ActiveRecord::Relation#first_or_create .

product_property_attrs  = { product_id: product.id, 
                            property_id: property.id, 
                            value: d[descname] }
product_property = ProductProperty.where(product_property_attrs).first_or_create

9voto

David Points 388

J'ai découvert que dans Rails 3.1, il n'est pas nécessaire de passer les attributs sous forme de hachage. Il suffit de passer les valeurs elles-mêmes.

productproperty = ProductProperty.find_or_create_by_product_id_and_property_id_and_value(product.id, property.id, d[descname])

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X