如何validation此哈希参数?
如何为此哈希参数编写正确的params
validation:
{ "files": { "main.c": { "contents": "#include ...", "foo": "bar" }, "main.h": { "contents": "#define BLAH ...", "foo": "baz" }, ... more files here ... } }
files
是我要validation的哈希参数。 files
每个键都可以是任何东西(字符串); 值是具有特定格式的哈希值,也需要进行validation(需要contents
和foo
)。 我正在使用葡萄0.9.0。
这就是我想要的东西:
params do optional :files, type: Hash do requires , type: Hash do requires :contents, type: String requires :foo, type: String end end end
我已经阅读了文档,但我看不出如何实现这种validation。 它甚至可能吗? 我需要编写自定义validation器吗?
另一种方法是改为:
{ "files": [ { "name": "main.c", "contents": "#include ...", "foo": "bar" }, { "name": "main.h", "contents": "#define BLAH ...", "foo": "baz" } ] }
这可以很容易地validation:
params do optional :files, type: Array do requires :name, type: String requires :contents, type: String requires :foo, type: String end end
但现在我失去了拥有唯一文件名的能力。
基于葡萄文档,我想出了编写自己的自定义validation器的想法,并选择第二种方法。
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
还可以报告呈现唯一性违规的自定义错误。 当然,该原理也可以应用于执行不同于唯一性的validation。
如果在您的应用程序中加载了此validation器,您可以在路径的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值的任何validation(名称,内容,foo)在files
validation器中保持不变,仍然适用。
包含以下数据的发布请求无法通过validation:
{ "files": [ { "name": "main.c", "contents": "#include ...", "foo": "bar" }, { "name": "main.c", "contents": "#define BLAH ...", "foo": "baz" } ] }