使用 button_to 进行更新操作时无法满足的强参数
Unsatisfiable strong params when using button_to for an update action
我无法理解在使用 button_to
执行 update
操作时如何满足强参数。我正在尝试将一个名为 active
的属性设置为 true
的值,用于一个名为 Plan
的 class 的现有实例。
(请注意,我在这里使用 HAML 来处理我的视图。)
这个有效:
= form_for(plan, remote: true) do |f|
= f.hidden_field :active, value: true
= f.submit 'set active'
但事实并非如此:
= button_to "set active", plan_path(plan, active: true), method: :put, remote: true
错误
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'
路线
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
控制器
# 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
这似乎是个愚蠢的问题,但我想不通,而且 the API documentation 似乎没有提供任何线索说明它为什么不起作用。
这些只是我尝试过的一些变体(每个变体后都有其随附的错误消息):
= 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'
根据http://apidock.com/rails/ActionView/Helpers/UrlHelper/button_to,params
应该是一个单独的散列
= button_to "set active", plan, method: :put, remote: true, params: { :active => true }
如果您查看提交的参数,不同之处在于您的表单导致 params
成为
{ "id" => 123, "plan" => {"active" => true}, "controller" => "...", "action" => "..."}
而第二个结果是
{ "id" => 123, "active" => true, "controller" => "...", "action" => "..."}
在那种情况下 params[:plan]
为零,这会导致您看到错误。
有多种方法可以解决这个问题。您可以更改提交的参数以匹配控制器当前期望的参数,例如
button_to set_active, plan, method: :put, remote: true, params: {"plan[active]" => 1}
(您也可以让参数成为表单 URL 的一部分,就像您尝试的那样,但对我来说,作为表单字段感觉稍微更正确)。
或者,如果此更新操作未被任何其他表单使用,则更改它以匹配提交的数据。我通常不会这样做 - 这会很容易,但如果事情以可预测的方式运行,你的应用程序会更容易考虑。
根据this thread中的信息,我终于解决了这个问题。
我没有将参数作为 button_to
的另一个参数放在它们自己的散列中,而是将它们包含在对 plan_path
方法的调用中。第一个参数需要是模型的 ID,第二个参数需要是模型的名称作为键,所需属性的散列作为其值。 (以下示例):
= button_to "set active", plan_path(plan.id, plan: { active: true }), method: :put, remote: true
我无法理解在使用 button_to
执行 update
操作时如何满足强参数。我正在尝试将一个名为 active
的属性设置为 true
的值,用于一个名为 Plan
的 class 的现有实例。
(请注意,我在这里使用 HAML 来处理我的视图。)
这个有效:
= form_for(plan, remote: true) do |f|
= f.hidden_field :active, value: true
= f.submit 'set active'
但事实并非如此:
= button_to "set active", plan_path(plan, active: true), method: :put, remote: true
错误
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'
路线
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
控制器
# 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
这似乎是个愚蠢的问题,但我想不通,而且 the API documentation 似乎没有提供任何线索说明它为什么不起作用。
这些只是我尝试过的一些变体(每个变体后都有其随附的错误消息):
= 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'
根据http://apidock.com/rails/ActionView/Helpers/UrlHelper/button_to,params
应该是一个单独的散列
= button_to "set active", plan, method: :put, remote: true, params: { :active => true }
如果您查看提交的参数,不同之处在于您的表单导致 params
成为
{ "id" => 123, "plan" => {"active" => true}, "controller" => "...", "action" => "..."}
而第二个结果是
{ "id" => 123, "active" => true, "controller" => "...", "action" => "..."}
在那种情况下 params[:plan]
为零,这会导致您看到错误。
有多种方法可以解决这个问题。您可以更改提交的参数以匹配控制器当前期望的参数,例如
button_to set_active, plan, method: :put, remote: true, params: {"plan[active]" => 1}
(您也可以让参数成为表单 URL 的一部分,就像您尝试的那样,但对我来说,作为表单字段感觉稍微更正确)。
或者,如果此更新操作未被任何其他表单使用,则更改它以匹配提交的数据。我通常不会这样做 - 这会很容易,但如果事情以可预测的方式运行,你的应用程序会更容易考虑。
根据this thread中的信息,我终于解决了这个问题。
我没有将参数作为 button_to
的另一个参数放在它们自己的散列中,而是将它们包含在对 plan_path
方法的调用中。第一个参数需要是模型的 ID,第二个参数需要是模型的名称作为键,所需属性的散列作为其值。 (以下示例):
= button_to "set active", plan_path(plan.id, plan: { active: true }), method: :put, remote: true