展开 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
列,属性a
和b
是直接在模型上的属性。
在没有 group
包装器的情况下处理这个问题只是
params.require(:item).permit(:a, :b)
但我想让它通过 strong_parameters
与 group
包装器一起提交。我怎样才能做到这一点,但具有如上所述的 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
我正在构建一个 rails4 api 我正在 post 嵌套的属性散列。然而,该模型实际上并没有嵌套属性或关联。尝试通过将一些属性组合成一个组来制作更清晰的 post 参数散列,但让 api 处理解包和强参数验证。
## Example POST params
params[:item][:group] = {
a: true,
b: false
}
但模型实际上并没有group
列,属性a
和b
是直接在模型上的属性。
在没有 group
包装器的情况下处理这个问题只是
params.require(:item).permit(:a, :b)
但我想让它通过 strong_parameters
与 group
包装器一起提交。我怎样才能做到这一点,但具有如上所述的 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