ruby-on-railsruby-on-rails-5strong-parametersactioncontroller

How can I remove objects from ActionController::Parameters?


I am trying to remove an element from my ActionController::Parameters object, but it doesn't work as I was expecting. My report_params object is as follows,

<ActionController::Parameters {"id"=>"51956915", "author_id"=>"1", "workout_attributes"=><ActionController::Parameters {"player_id"=>"14155", "date"=>"2017-10-09", "report_id"=>"51956915"} permitted: true> permitted: true>

I want to execute the following to remove workout_attributes from the object.

report_params.extract!(:workout_attributes)

And this returns the information below, but it still exists when I rerun report_params

<ActionController::Parameters {"player_id"=>"14155", "date"=>"2017-10-09", "report_id"=>"51956915"} permitted: true>

When I rerun report_params in console...

<ActionController::Parameters {"id"=>"51956915", "author_id"=>"1", "workout_attributes"=><ActionController::Parameters {"player_id"=>"14155", "date"=>"2017-10-09", "report_id"=>"51956915"} permitted: true> permitted: true>

Update Here's the report_params method from the controller:

def report_params
  params.require(:report).permit(:id, :author_id, 
        workout_attributes: [:player_id, :report_id, :date]
        )
end

So am I not allowed to edit the report_params object and i need to make a copy of it and then pass that copy to my update function in the action? Or is there something here I'm not doing correctly? Thanks!

Update with a "Working" Solution

I've found if I do the following, essentially making a copy of the params and then editing and passing on - it works. But this seems like ugly code if it can be done with the actual original params object.

  modified_report_params = report_params
  modified_report_params.extract!(:workout_attributes)

  respond_to do |format|
    format.js do
      if @report.update(modified_report_params)
      # ...
  end

Solution

  • Permitting params creates a new object:

    params = ActionController::Parameters.new(a: 1, b: 2)
    params.object_id
    #=> 70277626506220
    params.permit(:a, :b).object_id #new object created
    #=> 70277626332020
    

    As you can see, each time, when you call report_params you create a new object from params. To fix your issue, you can mutate params itself:

    params.extract!(:workout_attributes)
    

    Or, by using memoization:

    def report_params
      @report_params ||= params
        .require(:report)
        .permit(:id, :author_id, workout_attributes: [:player_id, :report_id, :date])
    end
    report_params.extract!(:workout_attributes)
    #=><ActionController::Parameters {"player_id"=>"14155", "date"=>"2017-10-09", "report_id"=>"51956915"} permitted: true>