2010-10-22 10 views
42

Quiero usar find_or_create_by, pero esta declaración NO funciona. No "encuentra" o "crea" con los otros atributos.¿Cómo puedo pasar múltiples atributos a find_or_create_by en Rails 3?

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

Parece haber muy poca, o ninguna, información sobre el uso de buscadores dinámicos en Rails 3. "y" -ing estos juntos me da un error método desconocido.

ACTUALIZACIÓN:

originalmente no podía conseguir lo siguiente para trabajar. Supongamos que no soy un idiota y que el "producto" es una instancia del modelo AR del producto.

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

Los métodos de error fue:

no such keys: property_id, value 

no podía darse cuenta de eso. Sólo esta mañana encontré la referencia para pasar los valores como este en su lugar:

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

Y voilá, funciona bien. Hubiera esperado que un hash funcionara en la misma situación, pero supongo que no.

Así que supongo que obtendrás un voto negativo si pierdes algo en Internet?

+3

Al "guiarlos" te refieres a algo como lo que se describe aquí: [Rails find_or_create por más de un atributo?] (Http://stackoverflow.com/questions/3046607/rails-find-or-create-by-more- que-un-atributo)? – Matt

+0

Intenté esto y funciona bien. ¿Qué exactamente no funciona? ¿Le da un error? ¿Cuál es el valor de 'productproperty'? La documentación para esto está aquí: http://api.rubyonrails.org/classes/ActiveRecord/Base.html (bajo los buscadores dinámicos basados ​​en atributos) – Mischa

Respuesta

52

Si desea buscar por atributos múltiples, puede usar "y" para anexarlos. Por ejemplo:

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

Hay un pequeño inconveniente que hay que tener en cuenta. Siempre devolverá el objeto que ha especificado, incluso si ese objeto no se puede guardar debido a errores de validación. Por lo tanto, asegúrese de verificar si el objeto devuelto tiene una identificación (¿o is_valid?). No asuma que está en la base de datos.

Como alternativa, puede utilizar la versión 'explosión' del método para elevar un error si el objeto no puede ser salvado:

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

Esto se aplica a Rails 3.

+2

Sí esto cambió en Rails 4. Ahora solo necesita 'find_or_create_by' y cualquier parámetro que desees. Ver http://stackoverflow.com/questions/22520274/rails-4-find-or-create-by-method-doesnt-work –

23

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

Con parámetro de consulta individual:

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

o extendida con múltiples parámetros:

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] }) 

trabajaría con:

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

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

Lo sentimos, lo corrigió y lo corrigió. – Lichtamberg

+0

Pero esto solo buscará por 'product_id' y cuando se encuentre/creado establecerá' property_id' y 'value'. Supongo que @AKWF quiere buscar por los 3 valores. – Matt

+0

Esto también funciona con múltiples parámetros ... Actualicé mi publicación – Lichtamberg

9

tengo encontrado en Rails 3.1 no es necesario pasar los atributos en un hash. Usted acaba de pasar los valores ellos mismos.

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

También es posible usar where(...).first_or_create-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 
5

En los carriles 4, puede utilizar find_or_create_by(attr1: 1, attr2: 2) encontrar o crear mediante varios atributos.

También puede hacer algo como:

User.create_with(
    password: 'secret', 
    password_confirmation: 'secret', 
    confirmation_date: DateTime.now 
).find_or_create_by(
    email: '[email protected]', 
    admin: true 
) 

Si tiene que crear el usuario con algunos atributos, pero no puede buscar por esos atributos.

Cuestiones relacionadas