首页 > 解决方案 > 控制器“params”在测试环境和开发环境中表现不同

问题描述

我正在为我的ShareOptions控制器使用强参数,如下所示:

def share_option_params
  params.require(:share_option).permit(:public_read, :team_read, :team_write)
end

如您所见,:share_option是必需的,因此当我直接在 JSON 正文中使用属性测试 PUT 时{ public_read: true },我的测试正确失败,因为它们没有嵌套在share_option. 使用binding.pry,这是 的输出share_option_params

<ActionController::Parameters {"public_read"=>"true", "format"=>:json, "controller"=>"api/share_options", "action"=>"update", "id"=>"553"} permitted: false>

但是,对于我的 JS 前端来说,相同请求成功的情况并非如此。在那里,我{ public_read: true }直接发送,而不是嵌套。在这种情况下,它似乎share_option是自动添加的,这里的输出是share_options_params

<ActionController::Parameters {"public_read"=>true, "format"=>:json, "controller"=>"api/share_options", "action"=>"update", "id"=>"332", "share_option"=>{"public_read"=>true}} permitted: false>

在这一点上,我怀疑 Rails 正在幕后做某事。但我完全不清楚为什么会这样。

标签: ruby-on-railsruby

解决方案


事实证明,Rails 允许您在发出正确的JSON 请求时省略请求的根元素。就我而言,我的测试没有正确编码为 JSON,因此没有发生这种行为。

更多信息:https ://edgeguides.rubyonrails.org/action_controller_overview.html#json-parameters

[…] 如果您在初始化程序中打开了 config.wrap_parameters 或在控制器中调用了 wrap_parameters,则可以安全地省略 JSON 参数中的根元素。在这种情况下,参数将被克隆并使用基于控制器名称选择的密钥进行包装。所以上面的 JSON 请求可以写成 […]

为了避免这种情况发生,我计划将我的参数包装在我的辅助方法中进行测试:

def json_request(params)
  {
    params: params.to_json,
    headers: { 'CONTENT_TYPE' => 'application/json' }
  }
end

推荐阅读