【问题标题】:Using Strong Parameters with a nested raw JSON parameter使用带有嵌套原始 JSON 参数的强参数
【发布时间】:2020-01-24 11:54:10
【问题描述】:

我的 Web 应用程序中有一个更新表单,但在允许我从该表单接收的参数时遇到了问题。这是参数到达控制器的方式:

<ActionController::Parameters {"company"=>{"description"=>"description", 
"email_address"=>"contact@gmail.com", 
"hours"=>"{\"fri\":[],\"mon\":[[\"09:00\",\"16:00\"]],\"sat\":[],
\"sun\":[[\"09:00\",\"16:00\"]],
\"thu\":[[\"09:00\",\"12:00\"], [\"13:00\",\"16:00\"]],
\"tue\":[[\"08:45\",\"16:00\"]],\"wed\":[[\"09:00\",\"16:00\"]]}"}, 
"controller"=>"my_controller", "action"=>"update"} permitted: false>

它们都以字符串的形式到达控制器,但小时被解析为 json(使用JSON.parse),结果如下:

{"fri"=>[], "mon"=>[["09:00", "16:00"]], "sat"=>[], "sun"=>[["09:00", "16:00"]], 
"thu"=>[["09:00", "12:00"], ["13:00", "16:00"]], "tue"=>[["08:45", "16:00"]], 
"wed"=>[["09:00", "16:00"]]}

Hours 表示例如商店的营业时间。它以星期几分开。并且每一天都可以没有一天的价值,只有一个或两个价值。解析小时后是数组的哈希,这些数组可以是空的,也可以有一个或两个数组。

我的问题是在使用params.require(:company).permit() 时允许这个小时参数。我尝试了许多不同的方法,例如:

  • params.require(:company).permit(:description, : email_address, :hours)
  • params.require(:company).permit(:description, : email_address, hours: {})
  • params.require(:company).permit(:description, : email_address, hours: [])
  • params.require(:company).permit(:description, : email_address, hours: { [sun: [], mon: [], tue: [], wed: [], thu: [], fri: [], sat: [] })
  • params.require(:company).permit(:description, : email_address, hours: [ [sun: [], mon: [], tue: [], wed: [], thu: [], fri: [], sat: [] ])
  • 及其他

但它失败或只是允许它没有任何内容,就像这样:

<ActionController::Parameters {"description"=>"description", 
"email_address"=>"contact@gmail.com",
"hours"=><ActionController::Parameters {"sun"=>[], "mon"=>[], "tue"=>[], 
"wed"=>[], "thu"=>[], "fri"=>[], "sat"=>[]} permitted: true>} permitted: true>

谢谢!

【问题讨论】:

  • A) 目前尚不清楚您是如何提供或接收的。 B) 为什么选择 Rails 4 和 5?
  • 我删除了 RoR 4 和 5 标签。该项目使用 Rails 5.1.6.2。我编辑了我的问题的开头。我希望现在可以,但请随时询问。谢谢!
  • 标签现在更好了。问题是这些数据是如何进来的?就像数据丢失一样,它是如何被接收和解码的?它在链中的哪个点丢失?
  • 最后一个例子,你有一个额外的[以小时为单位的属性,你能修复它并试一试吗? params.require(:company).permit(:description, :email_address, hours: [ sun: [], mon: [], tue: [], wed: [], thu: [], fri: [], sat : [] ]) 而不是 params.require(:company).permit(:description, : email_address, hours: [ [sun: [], mon: [], tue: [], wed: [], thu: [ ],周五:[],周六:[]])
  • 记住 hours 在你解码之前不会有那个结构。我建议 A) 以 JSON 形式提供 all 参数或 B) 像其他参数一样使用 URI 编码参数提供。

标签: ruby-on-rails


【解决方案1】:

Rails 实际上没有用于将嵌套数组as far as I know 列入白名单的语法。

这会:

params.require(:company)
      .permit(:description, :email_address, hours: { mon: [] })

允许company[:hours][:mon] 中的任何标量值。但是数组不是the permitted scalar types 之一:

[ String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile ]

这解释了为什么这些值被“丢弃”。我认为 rails 根本不知道如何处理 permit(hours: { mon: [[]] })

但如果您只是修复传入的 JSON 或在 Ruby 中转换它,这很容易避免。

json = if params[:company][:hours].present?
  # @todo handle JSON parsing errors
  # use each_with_object instead if your Ruby is older than 2.4
  JSON.parse(params[:company][:hours])
    &.transform_values { |v| v.empty? ? v : v.first } 
end
params.merge(
  hours: json
).permit(
   :description, :email_address, 
   hours: { sun: [], mon: [], tue: [], wed: [], thu: [], fri: [], sat: [] }
)

这是可行的,因为它将"mon"=&gt;[["09:00", "16:00"]] 转换为"mon"=&gt;["09:00", "16:00"],并且“09:00”、“16:00”是字符串,因此是允许的标量值。

【讨论】:

  • @tadman 是正确的,因为您应该首先找到更好的解决方案。这简直是​​天方夜谭。
猜你喜欢
  • 2018-07-12
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多