如何validation此哈希参数?

如何为此哈希参数编写正确的paramsvalidation:

 { "files": { "main.c": { "contents": "#include  ...", "foo": "bar" }, "main.h": { "contents": "#define BLAH ...", "foo": "baz" }, ... more files here ... } } 

files是我要validation的哈希参数。 files每个键都可以是任何东西(字符串); 值是具有特定格式的哈希值,也需要进行validation(需要contentsfoo )。 我正在使用葡萄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)在filesvalidation器中保持不变,仍然适用。

包含以下数据的发布请求无法通过validation:

 { "files": [ { "name": "main.c", "contents": "#include  ...", "foo": "bar" }, { "name": "main.c", "contents": "#define BLAH ...", "foo": "baz" } ] }