ruby-on-railsactioncontrollerruby-on-rails-5

Rails 5 - Manually add attribute to parameters in controller when updating


I am trying to manually add an additional attribute to parameters in the controller after completing a form. The params seem to be wrapped in , which seems to be preventing me to from changing the params.

Controller:

class ActualsController < SignedInController
...
 def update
   respond_to do |format|
   facesheet = actual_params[:facesheet]

   #trying to manually add attribute
   actual_params.merge(:file_name => 'ted.png')
   new_params = actual_params.except(:facesheet)

      if @actual.update(new_params)
        format.html { redirect_to action: 'show', id:@actual.id, notice: 'Actual was successfully updated.' }
        format.json { render :show, status: :ok, location: @actual }
      else
        format.html { render :edit }
        format.json { render json: @actual.errors, status: :unprocessable_entity }
      end

   end
 end
...
end

"new_params" from console

<ActionController::Parameters {"encounter_type_id"=>"1", "physician_id"=>"669", "insurance_id"=>"1182", "time_start"=>"05:00", "time_end"=>"07:00", "date_start"=>"2017-08-02", "date_end"=>"2017-08-02", "facility_id"=>"1", "med_rec_num"=>"1244", "patient_name_first"=>"Bob", "patient_name_last"=>"Smith", "patient_name_middle_initial"=>"H", "patient_dob"=>"2000-02-05", "note"=>"", "is_complete"=>"0", "procedure_ids"=>["", "300"]} permitted: true>  -Thanks for your help on this.

"@actual" from console

#<Actual id: 18, encounter_id: 4, provider_id: 7, encounter_type_id: 1, physician_id: 669, facility_id: 1, insurance_id: 1182, group_id: nil, datetime_start_utc: "2017-08-02 10:00:00", datetime_end_utc: "2017-08-02 12:00:00", payer: nil, med_rec_num: "1244", patient_name_first: "Bob", patient_name_last: "Smith", patient_name_middle_initial: "H", patient_dob: "2000-02-05", finclass: nil, is_valid: nil, is_complete: false, image_location: nil, note: "", created_at: "2017-08-18 13:30:58", updated_at: "2017-08-18 16:01:28">

Solution

  • In general its a good practice to view the incoming parameters as unmutable. It makes debugging and reasoning about your controller code much simpler.

    There are a few tricks you can to do to avoid monkeying with the params.

    Use a block:

    # this works for .new and .create as well
    updated = @actual.update(actual_params) do |a|
      a.foo = current_user.foo
      a.b = params.fetch(:foo, "some default")
    end
    

    Use composition to create safe parameters methods.

    def common_params
       [:name, :title]
    end
    
    def create_params
      params.require(:model_name)
            .permit(*common_params, :foo)
    end
    
    def update_params
      params.require(:model_name)
            .permit(*common_params, :bar)
    end
    

    Using .except can be risky since its better to whitelist than blacklist as you may forget to add future attributes to the blacklist.