如何为此哈希参数编写正确的params
验证:
{
"files": {
"main.c": {
"contents": "#include <stdio.h> ...",
"foo": "bar"
},
"main.h": {
"contents": "#define BLAH ...",
"foo": "baz"
},
... more files here ...
}
}
files
是我要验证的哈希参数。 files
的每个键都可以是任何键(字符串);值是具有特定格式的哈希值,也需要进行验证(需要contents
和foo
)。我使用的是葡萄0.9.0。
这就是我想要的东西:
params do
optional :files, type: Hash do
requires <any key>, type: Hash do
requires :contents, type: String
requires :foo, type: String
end
end
end
我已阅读documentation,但我无法看到如何实现此类验证。它甚至可能吗?我是否需要编写自定义验证器?
另一种方法是改为:
{
"files":
[
{
"name": "main.c",
"contents": "#include <stdio.h> ...",
"foo": "bar"
},
{
"name": "main.h",
"contents": "#define BLAH ...",
"foo": "baz"
}
]
}
可以像这样轻松验证:
params do
optional :files, type: Array do
requires :name, type: String
requires :contents, type: String
requires :foo, type: String
end
end
但现在我失去了拥有唯一文件名的能力。
答案 0 :(得分:0)
基于grape documentation,我想出了编写自己的自定义验证器的想法,并选择第二种方法。
class UniqueHashAttributes < Grape::Validations::Base
def validate_param!(attr_name, params)
# assuming @option is an array
@option.each do |attribute|
# detects if the value of the attribute is found more than once
if params[attr_name].group_by { |h| h[attribute] }.values.collect(&:size).max > 1
fail Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)],
message: "must have only unique values for properties: '#{@option.join(', ')}'"
end
end
end
end
还可以报告显示唯一性违规的自定义错误。当然,这个原则也可以应用于执行不同于唯一性的验证。
如果您的应用程序中加载了此验证程序,您可以在params
路径定义中使用它,如下所示:
params do
optional :files, unique_hash_attributes: [:name], type: Array do
requires :name, type: String
requires :contents, type: String
requires :foo, type: String
end
end
post '/validation' do
'passed'
end
通过此实现,您还可以通过将:foo
字段(或任何其他字段)添加到唯一哈希属性的数组中来指定它是唯一的。
Hash值的任何验证(名称,内容,foo)在files
验证器中保持不变,仍然适用。
包含以下数据的发布请求无法通过验证:
{ "files":
[
{
"name": "main.c",
"contents": "#include <stdio.h> ...",
"foo": "bar"
},
{
"name": "main.c",
"contents": "#define BLAH ...",
"foo": "baz"
}
]
}