首页 > 解决方案 > 使用带有嵌套原始 JSON 参数的强参数

问题描述

我的 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>

它们都以字符串的形式到达控制器,但 hours 被解析为 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"]]}

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

我的问题是在使用params.require(:company).permit(). 我尝试了许多不同的方法,例如:

但它失败或只是允许它没有任何内容,例如:

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

谢谢!

标签: ruby-on-rails

解决方案


据我所知, Rails 实际上没有将嵌套数组列入白名单的语法。

这个会:

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

允许 中的任何标量值company[:hours][:mon]。但是数组不是允许的标量类型之一:

[ 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"=>[["09:00", "16:00"]]"mon"=>["09:00", "16:00"]“09:00”、“16:00”是字符串,因此是允许的标量值。


推荐阅读