打开Rails POST参数散列并映射到带有/strong参数的模型属性



我正在构建一个rails4 api,在其中发布一个嵌套的属性哈希。然而,该模型实际上并没有嵌套的属性或关联。试图通过将一些属性组合成一个组来制作一个更干净的post-params哈希,但要让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

关于"嵌套"参数的传递,文档非常明确;按照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

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

使用上面的应该使您能够使用嵌套的params哈希;唯一的缺点是必须坚持使用group: [:a, :b]作为params的结构。

与大多数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

最新更新