展开 Rails POST 参数散列并映射到具有强参数的模型属性

Unwrap Rails POST params hash and map to model attributes w/ strong parameters

我正在构建一个 rails4 api 我正在 post 嵌套的属性散列。然而,该模型实际上并没有嵌套属性或关联。尝试通过将一些属性组合成一个组来制作更清晰的 post 参数散列,但让 api 处理解包和强参数验证。

## Example POST params
params[:item][:group] = {
  a: true,
  b: false
}

但模型实际上并没有group列,属性ab是直接在模型上的属性。

在没有 group 包装器的情况下处理这个问题只是

params.require(:item).permit(:a, :b)

但我想让它通过 strong_parametersgroup 包装器一起提交。我怎样才能做到这一点,但具有如上所述的 POST 参数?

您可以在调用操作之前删除所有中间级别:

class YourController < ApplicationController
  before_action :flatten_item_params

  private

  def flatten_item_params
    params[:item] = params.require(:item).each_with_object({}) do |(key, value), result|
      result.merge!(value)
    end
  end

  def item_params
    params[:item].permit(:a, :b)
  end
end

关于"nested"参数的传递,docs are pretty explicit;按照 Hoang Phan 的建议,您可以将 嵌套 哈希传递给您的控制器:

params: {
   object: {
      title: "Test",
      group: {
         a: "test", 
         b: "test"
      }
   }
}

这可以接受:

def params
   params.require(:object).permit(:title, group: [:a, :b])
end

--

问题 我相信模型中必须存在所有键。要解决此问题,您可以使用 virtual attribute:

#app/models/your_model.rb
class YourModel < ActiveRecord::Base
   attr_accessor :group, :a, :b
end

不保存虚拟属性,但是 实例 方法附加到 class,允许您用不需要放入的数据填充它数据库。

使用上面的应该让你能够使用嵌套的参数散列;唯一的缺点是您必须坚持使用 group: [:a, :b] 作为参数的结构。

像大多数 ruby/rails 情况一样,可能有更好的方法。从我最终采用这种看似骇人听闻的方法的回应中获取信息。重要的是它能满足我的要求,但感觉很恶心,所以如果有人有更优雅的方法,请分享!

class YourController < ApplicationController

private

  ## POST { item: { group: { a: true, b: false } } }
  def item_params
    group = params[:item][:group].presence

    if group
      ## Unwrap nesting and place at root of params[:item]
      ## Probably should explicitly handle this instead of iterating
      group.each {|k,v| params[:item][k] = v }
      params[:item].delete :group
    end

    params[:item].permit(:a, :b)
  end
end