6

I have two questions:


In Rails 3 you can update multiple records using

Product.update(params[:products].keys, params[:products].values)

How do you do the same thing in Rails 4 using Strong Parameters? How about creating multiple records at the same time? Can you please elaborate your solution with an example in a format like the following:

params = ActionController::Parameters.new(...)
Product.create!(params.require(...)permit(...)

Also, my products model has a column called number which is equal to the order that they are updated. Is there a way to pass a counter value to the number while updating?

Thanks.

user2725109
  • 2,286
  • 4
  • 27
  • 46
  • 2
    I think you're getting confused with what [`strong params`](http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html) are designed for - they are basically just for "white-listing" different parameters, so that you can call them within the controller. It's the equivalent of `attr_accessible` in Rails 3 – Richard Peck Nov 11 '13 at 09:20

2 Answers2

1

Solution w/o accepts_nested_attributes_for

This is my 2nd ever answer on SO, but I came across this problem multiple times, couldn't as of this writing find a reasonable solution and finally figured it out myself after doing a little nested_attributes hypothesizing and wanted to share my best understanding of it. I believe the strong params line you're after is this:

product_params = params.require(:products).permit(product_fields: [:value1, :value2, etc...])

I don't know exactly what your form looks like, but you will need to have a fields_for to nest the params in the product_fields(or any_name):

form_for :products do |f|
  f.fields_for product_fields[] do |pf|
    pf.select :value1
    pf.select :value2
    ...
  end
end

This will allow the permit() to accept a single explicit hash

product_fields => {0 => {value1: 'value', value2: 'value'}}

instead of the key/value pairs

0 => {value1: 'value', value2: 'value'}, 1 => {value1: 'value', value2: 'value'}, etc...

which you'd otherwise have to name individually:

.permit(0 => [value1: 'value', value2: 'value'], 1 => [...], 2 => [...], ad infinitum)

This allows you to update multiple products without having to use a parent model accepting nested attributes. I just tested this on my own project in Rails 4.2 and it worked like a charm. As for creating multiple: How would I save multiple records at once in Rails?.

As for a counter, you may need to iterate over each model individually:

product_params[:product_fields].keys.each_index do |index|
  Product.create!(product_params.merge(counter: index))
end

Thought it's been so long you probably resolved that on your own. :-)

Community
  • 1
  • 1
Kowser
  • 11
  • 3
0

Maybe you're thinking about using nested_attributes? That would look something like this:

params.require(:parent_model).permit(
  :id,
  child_models_attributes: [
    :id,
    :parent_model_id,
    :child_model_attribute_1,
    :child_model_attribute_2
  ]
)

with

params = {
  id: parent_model.id,
  child_models_attributes: {
    '0' => {
      id: child_model_1.id,
      parent_model_id: parent_model.id,
      child_model_attribute_1: 'value 1',
      child_model_attribute_2: 12312
    }
  }
}

You would need to allow nested_attributes for the parent model like this though:

class ChildModel < Activerecord::Base
  belongs_to :parent_model
end

class ParentModel < Activerecord::Base
  has_many :child_models
  accepts_nested_attributes_for :child_models
end
A5308Y
  • 409
  • 6
  • 13