How can I pass multiple attributes to find_or_create_by in Rails 3?

后端 未结 5 1126
独厮守ぢ
独厮守ぢ 2020-12-12 20:53

I want to use find_or_create_by, but this statement does NOT work. It does not \"find\" or \"create\" with the other attributes.

productproperty = ProductPro         


        
相关标签:
5条回答
  • 2020-12-12 21:09

    You could also use 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
    
    0 讨论(0)
  • 2020-12-12 21:20

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

    With single query parameter:

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

    or extended with multiple parameters:

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

    Would work with:

    conditions = { :product_id => product.id, 
                   :property_id => property.id,
                   :value => d[descname] }
    
    pp = ProductProperty.find(:first, :conditions => conditions) || ProductProperty.create(conditions) 
    
    0 讨论(0)
  • 2020-12-12 21:22

    In Rails 4, you can use find_or_create_by(attr1: 1, attr2: 2) to find or create by multiple attributes.

    You can also do something like:

    User.create_with(
      password: 'secret', 
      password_confirmation: 'secret',
      confirmation_date: DateTime.now
    ).find_or_create_by(
      email: 'admin@domain.com',
      admin: true
    )
    

    If you need to create the user with some attributes, but cannot search by those attributes.

    0 讨论(0)
  • 2020-12-12 21:26

    I've found in Rails 3.1 you do not need to pass the attributes in as a hash. You just pass the values themselves.

    ProductProperty.find_or_create_by_product_id_and_property_id_and_value(
      product.id, property.id, d[descname])
    
    0 讨论(0)
  • 2020-12-12 21:36

    If you want to search by multiple attributes, you can use "and" to append them. For example:

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

    There is one minor catch to be aware of. It will always return the object you've specified, even if that object can't be saved due to validation errors. So make sure you check to see if the returned object has an id (or is_valid?). Don't assume its in the database.

    Alternatively, you can use the 'bang' version of the method to raise an error if the object cannot be saved:

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

    This applies to Rails 3.

    0 讨论(0)
提交回复
热议问题