我正在使用Rails 5来创建JSON Api。
我的控制器使用强参数和一个 require 属性,如下所示:
params.require(:require_attribute).permit(:permit_attribute1,:permit_attribute2)
通常我必须像这样发送我的JSON:
{
"require_attribute":{
"permit_attribute1": "data",
"permit_attribute2": "data"
}
}
如果缺少必需的属性,我必须收到此消息:
"ActionController::ParameterMissing: param is missing or the value is empty: require_attribute"
我的问题是,如果我从JSON中删除了必需的属性,并且我有一个permit
属性与强params相同,那么它确实有效。
我发送的JSON:
{
"permit_attribute1": "data",
}
当我在log
中获得 params 时,我有:
{“permit1”=>数据,“controller”=>“mycontroller”,“action”=>“创建”,“require_attribute”=> {“permit1”=> 1} }
似乎Rails使用必需的密钥创建哈希,而不是引发错误。 但是我想在收到JSON时强制使用必需的属性。
有人有想法吗?
答案 0 :(得分:3)
强参数API是使用最常见的用例设计的 心里。它并不意味着处理你的所有 白名单问题。
http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
require(key)
确保存在参数。如果它存在,则返回 给定键的参数,否则引发一个
ActionController::ParameterMissing
错误。
http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-require
从上面的设置中可以看出,“扁平”散列上的必需参数实际上并不是构建强参数API的原因。相反,它是围绕导轨约定构建的,其中params嵌套在单个键下。
您可以使用'.require'一次拉一个键,但这会非常笨拙。
相反,你可以通过引发异常来模拟它的作用,除非密钥存在:
def something_params
req = [:required_attribute1, :required_attribute2]
req.each do |k|
raise ActionController::ParameterMissing.new(k) unless params[k].present?
end
whitelisted = params.permit(:permit_attribute1, :permit_attribute2)
end
然而,一个更好的方法可能是使用模型级验证 - ActionController::ParameterMissing
应该表明请求的一般格式是关闭的 - 而不是缺少必需的属性。例如,对于JSONAPI.org格式化的请求,您可以执行以下操作:
params.require(:data).require(:attributes).permit(:email, :username)
确保请求遵循标准。但是,强制要求在没有电子邮件的情况下无法创建用户是模型级别的问题。
答案 1 :(得分:1)
是的,默认情况下,API模式下的Rails将JSON请求参数包装到一个哈希中,以从控制器类中猜测其名称。您可以阅读详细信息here。
如果您的应用中不需要此功能,只需从:json
中的:format
数组中删除config\initializers\wrap_parameters.rb
。或者,您可以如上所述在控制器级别使用细粒度控制。
这样,当所需的密钥不存在时,您将获得异常。