使用 validates_each 进行自定义验证

Custom validation with validates_each

我正在尝试使用 validates_each 方法实现自定义验证。我有 rules.json 文件,我在其中保存验证规则。在这种情况下,我想验证 gender 值包含在 ["Male", "Female"] 数组中,title 包含在 ["Mr", "Mrs"] 数组中。

使用 self.parse_rules 方法解析 json 文件并使用 self.all_funders(attribute) 访问性别和标题值 ["Male", "Female"], ["Mr", "Mrs"].

当我 运行 :gender, :titlevalidates_each 方法时,我只能验证 ["Male", "Female"] 数组上的两个属性,因此 :title 将始终给出错误信息"错误信息".

出于某些原因,我不明白 ["Mr", "Mrs"] 数组在验证处理时未从 json 文件中获取。谁能告诉我如何解决这个问题?

class Rule
 include ActiveModel::Validations

 attr_accessor :gender, :title

 def self.parse_rules
  JSON.parse(File.read("rules.json"))
 end

 def self.all_funders(attribute)
  @all_rules ||= parse_rules[attribute.to_sym][:options]
 end

 validates_each :gender, :title do |record, attr, value|
  record.errors.add(attr, "Error message") if !all_funders(attr).include?(value)
 end
end

因为您正在记忆 all_funders 中的特定属性,而不是整个 json。如果您将 validates_each :gender, :title 替换为 validates_each :title, :gender:title 将始终有效,而 :gender 将始终出错。要解决此问题,您可能需要将 all_funders 更改为更像:

def self.all_funders(attribute)
  @all_rules ||= parse_rules

  @all_rules[attribute.to_sym][:options]
end

所以在这里,我们正在记住 loading/parsing 文件的结果(因此 @all_rules 成为整个文件的已解析哈希),然后查看要求的特定属性。

另一种选择是在 parse_rules 方法中记忆:

def self.parse_rules
  @all_rules ||= JSON.parse(File.read("rules.json"))
end

def self.all_funders(attribute)
  parse_rules[attribute.to_sym][:options]
end

为了更清楚 (IMO) 发生了什么。

第一次调用 all_funders 记住结果。无论方法参数如何,此结果都将在所有后续调用中返回。要修复此错误,请改为记忆 parse_rules

这是一个 shows how your bug is occurring when all_funders is called multiple times 的回购协议。该存储库包括一个演示程序以及静态图像和一个关于错误发生方式的交互式描述。