使用Rails内置验证器通过动态选项验证哈希

时间:2017-06-27 16:49:27

标签: ruby-on-rails metaprogramming ruby-on-rails-5

我有两个模型CharacterSheetSheet,两个模型都有properties列。 Sheet的{​​{1}}列用于存储属性名称及其验证的键值对(这些对象是正确的Ruby properties语法)。

validates

Sheet.create!(name: 'A Test Sheet', properties: { prop1: { numericality: { only_integer: true }, length: { maximum: 3 } }, prop2: { numericality: { only_integer: true }, length: { minimum: 1 } }, prop3: { numericality: { only_integer: true } } }) 存储属性名称及其实际值的键值对,并通过相应的CharacterSheet键值对进行验证。

Sheet

理想情况下,我想使用CharacterSheet.create(sheet_id: 1, name: 'A Test CharacterSheet', properties: { prop1: 123, prop2: 234, prop3: 345 }) 中存储的验证要求来使用Rails'内置的验证方法,所以我不必自己重写所有的验证。但是,我找不到合适的方法来挂钩。 Sheet.properties似乎无法满足我的目的,因为它似乎(据我所知)它需要一个有效的列名,然后用它来提取值,而不是允许传递一个值在直接。

1 个答案:

答案 0 :(得分:0)

所以我看到的第一个问题是你还需要转换它的意思,数字以及如何获取该属性,以及only_integer以及这意味着什么。 我建议你使用像

这样的东西
prop_name: { type_of_validation: 'regexp', validator: 'Regex-representation' }
prop_name2: { type_of_validation: 'type', validator: 'Hash' }

正则表达式表示需要双重转义。

因为那样你可以做到

 loaded_sheet = Sheet.find(csheet.sheet_id).properties.as_json.with_indifferent_access
    csheet.properties.as_json.with_indifferent_access.each do |k,v|
      if loaded_sheet[k.to_sym][:type_of_validation] == 'regexp'
        regex = Regexp.new loaded_sheet[k.to_sym][:validator]
        return false unless v =~ regex
      elsif loaded_sheet[k.to_sym[:type_of_validation] == 'type'
        return false unless v.is_a?(loaded_sheet[k.to_sym][:validator].constantize)
      end
    end