Search code examples
ruby-on-rails-4strong-parameters

Unsatisfiable strong params when using button_to for an update action


I'm having trouble understanding how to satisfy strong params when using button_to to do an update action. I'm trying to set an attribute called active to the value of true for an existing instance of a class called Plan.

(Note that I'm using HAML for my views here.)

This works:

= form_for(plan, remote: true) do |f|
  = f.hidden_field :active, value: true
  = f.submit 'set active'

But this doesn't:

= button_to "set active", plan_path(plan, active: true), method: :put, remote: true

Error

Completed 400 Bad Request in 7ms (ActiveRecord: 1.1ms)

ActionController::ParameterMissing - param is missing or the value is empty: plan:
actionpack (4.2.1) lib/action_controller/metal/strong_parameters.rb:249:in 'require'
() Users/Rob/Sites/drexel_msis_planner/app/controllers/plans_controller.rb:77:in 'plan_params'
() Users/Rob/Sites/drexel_msis_planner/app/controllers/plans_controller.rb:45:in 'block in update'
actionpack (4.2.1) lib/action_controller/metal/mime_responds.rb:210:in 'respond_to'
() Users/Rob/Sites/drexel_msis_planner/app/controllers/plans_controller.rb:44:in 'update'

Routes

          user_plans GET    /users/:user_id/plans(.:format)               plans#index
                     POST   /users/:user_id/plans(.:format)               plans#create
       new_user_plan GET    /users/:user_id/plans/new(.:format)           plans#new
           edit_plan GET    /plans/:id/edit(.:format)                     plans#edit
                plan PATCH  /plans/:id(.:format)                          plans#update
                     PUT    /plans/:id(.:format)                          plans#update
                     DELETE /plans/:id(.:format)                          plans#destroy

Controller

# PATCH/PUT /plans/1
def update
  respond_to do |format|
    if @plan.update(plan_params)
      format.js { flash.now[:notice] = "Plan was successfully updated." }
    end
  end
end

private 

def plan_params
  params.require(:plan).permit(:user_id, :name, :active)
end

It seems like such a silly issue but I can't figure it out and the API documentation doesn't seem to give any clues as to why it wouldn't be working.

These are but a few of the variations that I've tried (each is followed by its accompanying error message):

= button_to "set active", plan_path(plan: plan, active: true), method: :put, remote: true

ActionController::UrlGenerationError - No route matches {:action=>"update", :active=>true, :controller=>"plans", :plan=>#, :user_id=>"104"} missing required keys: [:id]:

= button_to "set active", plan_path(id: plan.id, active: true), method: :put, remote: true

Completed 400 Bad Request in 17ms (ActiveRecord: 2.1ms)

ActionController::ParameterMissing - param is missing or the value is empty: plan: actionpack (4.2.1) lib/action_controller/metal/strong_parameters.rb:249:in `require'

= button_to "set active", plan, active: true, method: :put, remote: true

ActionController::ParameterMissing - param is missing or the value is empty: plan: actionpack (4.2.1) lib/action_controller/metal/strong_parameters.rb:249:in 'require'
() Users/Rob/Sites/drexel_msis_planner/app/controllers/plans_controller.rb:77:in 'plan_params' () Users/Rob/Sites/drexel_msis_planner/app/controllers/plans_controller.rb:45:in 'block in update'


Solution

  • I was able to finally resolve this based on the information in this thread.

    Instead of placing the parameters in their own hash as another argument to button_to, I included them inside of the call to the plan_path method. The first argument needs to be the model's ID, and the second argument needs to be the model's name as a key with a hash of the desired attributes as its value. (Example below):

    = button_to "set active", plan_path(plan.id, plan: { active: true }), method: :put, remote: true