Rails 允许嵌套哈希属性

uks*_*son 3 attributes json nested ruby-on-rails strong-parameters

控制器接收 JSON 对象

{
  user: {
    name: "string",
    details: {
      info1: "string",
      info2: []
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在权限控制器知道可以允许某些定义的字段(如名称)和具有所有嵌套属性的散列字段详细信息(也可以使用数组)。对于这种情况,正确的解决方案是什么?

糟糕的解决方案

  1. permit无法使用,因为我必须选择用户允许的字段

  2. tap do |whitelisted|无法使用,因为它不会使该字段“允许”

  3. 下面的情况不能是用户,因为使用数组不起作用

    details_keys = params[:user][:details].keys

    params.require(:user).permit(:name, details: details_keys)

Was*_*ain 5

如果您想允许某个键具有允许的标量值数组,则只需将该键映射到一个空数组即可:

params.permit(key: [])
Run Code Online (Sandbox Code Playgroud)

允许的标量类型是String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile, and Rack::Test::UploadedFile

因此,当数组包含一些非标量值(例如哈希)时,您必须进一步允许数组中存在嵌套键。

假设您有以下结构:

{
  key: [
    {
      attr1: 'string',
      attr2: 10
    },
    {
      attr1: 'another string',
      attr2: 100
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

那么权限是这样的:

params.permit(key: [:attr1, :attr2])
Run Code Online (Sandbox Code Playgroud)

现在让我们假设您的案例如下:

{
  user: {
    name: "sting",
    details: {
      info1: "string",
      info2: [1, true, :sym] // assume it contains only permitted scalar values
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

该许可将是:

params.require(:user).permit(:name, details: [:info1, info2: []])
Run Code Online (Sandbox Code Playgroud)

为了自动执行此操作,我们假设details有 5 个具有允许的标量值的属性和另外 3 个也仅具有标量值的数组属性。

首先取出 的 5 个非数组键details

non_array_keys = params[:user][:details].reject { |_, v| v.class == Array }.keys
Run Code Online (Sandbox Code Playgroud)

接下来是里面的 3 个数组键details

array_keys = params[:user][:details].select { |_, v| v.class == Array }.keys.map { |k| { k => [] } }
Run Code Online (Sandbox Code Playgroud)

现在details_keys准备就绪:

details_keys = non_array_keys << array_keys
details_keys.flatten!
Run Code Online (Sandbox Code Playgroud)

最终许可将如下所示:

params.require(:user).permit(:name, details: details_keys)
Run Code Online (Sandbox Code Playgroud)

如果嵌套数组包含非标量值,那么我想此时您已经对如何适应更改有了足够的了解!

免责声明:这种自动化不受欢迎,因为不需要执行所有这些操作,简单的调用params.require(:user).permit!就足够了。但这将:user参数哈希及其任何子哈希标记为允许的,并且不检查允许的标量,任何内容都被接受。使用 时应格外小心permit!,因为它将允许对所有当前和未来的模型属性进行批量分配。

有关详细信息,我强烈建议您查看Rails 官方指南,详细介绍了强参数。