0

I have a pair of models, Preset and Plot

class Preset < ApplicationRecord
    belongs_to :user
    has_many :plots, :dependent => :destroy
    accepts_nested_attributes_for :plots, allow_destroy: true
end

class Plot < ApplicationRecord
    belongs_to :preset
    belongs_to :theme, optional: true
end

And a nested form for editing presets and their respective plots

= form_with(model: @preset, local: true, method: "patch") do |f|
  = label_tag(:name, "Preset name:")
  = text_field_tag(:name, @preset.name)
  %br
  = f.fields_for :plots do |builder|
    %br
    = render 'editplot', f: builder

And an _editplot partial (this is working correctly, but included for completeness)

= f.label(:name, "Change plot:")
= f.select(:name, options_for_select([['Existing Plot 1', 'Existing Plot 1'], ['Existing Plot 2', 'Existing Plot 2']]))
= f.label(:_destroy, "Remove plot")
= f.check_box(:_destroy)

I have permitted the parameters I need in the presets controller as follows:

private
        def preset_params
            params.require(:preset).permit(:name, plots_attributes: [:id, :name, :parameter_path, :theme_id, :_destroy])
        end

I would therefore expect the :name parameter to be included in preset_params.

The update method in the controller is as follows:

def update
        @preset = Preset.find(params[:id])

        puts "name"
        puts params[:name]

        puts "preset params"
        puts preset_params

        if @preset.update(preset_params)
            redirect_to presets_path, notice: 'Preset was successfully updated.'
            return
        else
            render :edit
            return
        end

When I submit the form, checked plots are deleted as expected. However, the name of the preset itself is not updated. The console shows the parameters include the :name parameter, and its value is correct, but it does not show up in the console when I output preset_params. Where has it gone?

Parameters: {"authenticity_token"=>"15RgDM+SCwfScbQXcHmVGfzo2w8qe972QPdkf/OB9AFeyvtUXdxJpaVGKgCMoLaISYljclmOuIowqrfGyy/Dug==", "name"=>"Edited name", "preset"=>{"plots_attributes"=>{"0"=>{"name"=>"Existing Plot 1", "_destroy"=>"0", "id"=>"3"}, "1"=>{"name"=>"Existing Plot 1", "_destroy"=>"0", "id"=>"4"}}}, "commit"=>"Update Preset", "id"=>"1"}

{"plots_attributes"=><ActionController::Parameters {"0"=><ActionController::Parameters {"id"=>"3", "name"=>"Existing Plot 1", "_destroy"=>"0"} permitted: true>, "1"=><ActionController::Parameters {"id"=>"4", "name"=>"Existing Plot 1", "_destroy"=>"0"} permitted: true>} permitted: true>}

1 Answer 1

1

"name" is not inside the "preset" hash in your parameters, see:

Parameters: {
  "name"=>"Edited name", 
  "preset"=>{
    "plots_attributes"=>{
      "0"=>{
        "name"=>"Existing Plot 1", 
        "_destroy"=>"0", 
        "id"=>"3"
      }, 
      "1"=>{
        "name"=>"Existing Plot 1", 
        "_destroy"=>"0", 
        "id"=>"4"
      }
    }
  }, 
  "commit"=>"Update Preset", 
  "id"=>"1"
}

So, preset_params is not going to include "name".

You can try:

= text_field_tag('preset[name]', @preset.name)

...to get the name nested in the preset hash.

Sign up to request clarification or add additional context in comments.

2 Comments

So would it be correct to add name inside the required params? I.e. params.require(:name) before the params.require(:preset) line?
No, not if you want name to be inside preset so that you can do @preset.update(preset_params). Did you try using 'preset[name]' instead of :name?

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.