1

I have

class Deal < ApplicationRecord
  belongs_to :company, dependent: :destroy
  accepts_nested_attributes_for :company

class DealsController < ApplicationController
  def update
    respond_to do |format|
      if @deal.update(deal_params)
        format.html { redirect_to dashboard_path, notice: 'Deal was successfully updated.' }
      ...

  def deal_params
    params.require(:deal).permit :name, ...
      company_attributes: [:name, ...]

When it submits the form, I see

  Parameters: {"utf8"=>"√", "deal"=>{"name"=>"Office building", ...
  "company_attributes"=>{"name"=>"...", "id"=>"25"}}, "commit"=>"Update Deal", "id"=>"1"}
Unpermitted parameter: id

But it always creates a new Company model instead of updating the existing associated model. I don't know why it's creating a new model. I don't include :id in company_attributes array because I'm afraid someone could use it to update something that doesn't belong to them.

Why is Rails always creating a new Company model instead of updating the existing Company model?

This question is similar but doesn't answer my question.

Rails 5.0.2


HTML requested:

<div class="form-group">
  <label for="deal_company_attributes_name">Name</label>
  <input class="form-control" type="text" value="West Side Offices LLC" name="deal[company_attributes][name]" id="deal_company_attributes_name">
</div>
...
<input type="hidden" value="26" name="deal[company_attributes][id]" id="deal_company_attributes_id">
<div class="actions">
  <input type="submit" name="commit" value="Update Deal" class="btn btn-primary" data-disable-with="Update Deal">
</div>
4
  • You need to permit :id of nested attribute Commented May 11, 2017 at 6:24
  • @DeepakMahakale Couldn't a hacker modify the form and update any random id they wanted to? Why does Rails need the id of the nested attribute when it already knows from @deal.company.id? Commented May 11, 2017 at 6:44
  • 1
    how are you going to identify which record you have to update? Commented May 11, 2017 at 6:50
  • There is only one. @deal.company is the only record. Commented May 11, 2017 at 7:04

1 Answer 1

3

But it always creates a new Company model instead of updating the existing associated model. I don't know why it's creating a new model.

For Update to work,you should include :id as well in the company_attributes. That is how StrongParameters deals with accepts_nested_attributes_for

In order to use accepts_nested_attributes_for with Strong Parameters, you will need to specify which nested attributes should be whitelisted. You might want to allow :id and :_destroy, see ActiveRecord::NestedAttributes for more information.

def deal_params
  params.require(:deal).permit :name, ...
      company_attributes: [:id, :name, ...]
end
Sign up to request clarification or add additional context in comments.

7 Comments

But can't a hacker modify the HTML form and change id to any random value to update a record that doesn't belong to them? Why does Rails need the id field anyways when it already knows the associated record from @deal.company.id?
@Chloe Can you post the HTML of your form generated in the console?
How is the HTML relevant? I showed the params submitted. Updated question.
@Chloe It is relevant and it is not safe to put a foreign_key value as a hidden field in the form. There are better ways like adding it in the controller instead(see this)
Are you kidding me? That is how it's detailed in the documentation! And #fields_for.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.