2010-10-22 82 views
42

我想使用find_or_create_by,但是这个语句不起作用。它不会与其他属性“查找”或“创建”。如何在Rails 3中将多个属性传递给find_or_create_by?

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

似乎有很少或没有对使用Rails中3动态查找器“和”信息一起-ing这些给了我一个未知的方法错误。

UPDATE:

本来我不能让下面的工作。请假设我不是白痴,“产品”是产品AR模型的一个实例。

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

错误方法是:

no such keys: property_id, value 

我不明白这一点。只有今天早上,我发现参考传递这样的值,而不是:

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

而且瞧,它工作正常。我本来会希望哈希能在相同的情况下工作,但我想不是。

所以我想你会得到一个投票,如果你错过了互联网上的东西?

+3

通过“安定”他们你的意思是喜欢这里描述的:?由多个属性的Rails find_or_create(http://stackoverflow.com/questions/3046607/rails-find-or-create-by-more-高于一个属性)? – Matt 2010-10-22 13:15:44

+0

我试过这个,它工作正常。什么不工作?你有错误吗? 'productproperty'的价值是什么?这里的文档在这里:http://api.rubyonrails.org/classes/ActiveRecord/Base.html(基于动态属性的发现者) – Mischa 2010-10-22 13:19:35

回答

52

如果要通过多个属性进行搜索,可以使用“和”来追加它们。例如:

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

有一个小问题需要注意。它将始终返回所指定的对象,即使由于验证错误而无法保存该对象。所以请确保你检查返回的对象是否有一个id(或is_valid?)。不要假设它在数据库中。

或者,您可以使用该方法的“砰”的版本,以提高一个错误,如果该对象不能保存:

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

这适用到Rails 3

+2

是的这改变了Rails 4.现在你只需要'find_or_create_by'和你想要的任何参数。见http://stackoverflow.com/questions/22520274/rails-4-find-or-create-by-method-doesnt-work – 2016-03-04 00:12:54

23

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

随着单查询参数:

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

或多个参数扩展:

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

会一起工作:

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

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

对不起,犯了一个错误,现在纠正它。 – Lichtamberg 2010-10-22 13:18:12

+0

但是这只能通过'product_id'进行搜索,当找到/创建时会设置'property_id'和'value'。我想@AKWF想要通过所有3个值进行搜索。 – Matt 2010-10-22 13:34:21

+0

这也适用于多个参数...更新我的文章 – Lichtamberg 2010-10-22 13:50:30

9

我已经在Rails 3.1中找到,你不需要将属性作为散列来传递。你只需传递这些值。

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

你也可以使用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

在Rails 4中,您可以使用find_or_create_by(attr1: 1, attr2: 2)来查找或创建多个属性。

你也可以这样做:

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

如果你需要创建一些属性的用户,但不能被这些属性进行搜索。