使用包含来验证数组元素包含:{in:array}

时间:2012-11-27 07:30:55

标签: ruby-on-rails

我使用acts-as-taggable-on gem来填充用户对此类User模型的兴趣

# User.rb
acts_as_taggable
acts_as_taggable_on :interests

当我填充interest_list数组时,我需要检查给定的值是否与常量数组匹配,以确保它们是可接受的值,如下所示

VALID_INTERESTS = ["music","biking","hike"]
validates :interest_list, :inclusion => { :in => VALID_INTERESTS, :message => "%{value} is not a valid interest" }

上面的代码返回以下错误

@user = User.new
@user.interest_list = ["music","biking"]
@user.save
=> false …. @messages={:interest_list=>["music, biking is not a valid interest"]}

我可以看到包含没有意识到它应该迭代数组元素而不是s考虑作为普通字符串,但我不知道如何实现这一点。有什么想法吗?

3 个答案:

答案 0 :(得分:9)

标准包含验证器不适用于此用例,因为它检查有问题的属性是否是给定数组的成员。你想要的是检查数组的每个元素(属性)是否是给定数组的成员。

要做到这一点,你可以创建一个自定义验证器,如下所示:

VALID_INTERESTS = ["music","biking","hike"]
validate :validate_interests

private

def validate_interests
  if (invalid_interests = (interest_list - VALID_INTERESTS))
    invalid_interests.each do |interest|
      errors.add(:interest_list, interest + " is not a valid interest")
    end
  end
end

我通过获取这两个数组的差异,得到interest_list的元素不在VALID_INTERESTS

我实际上没有尝试过这段代码,所以不能保证它会起作用,但我认为解决方案看起来会像这样。

答案 1 :(得分:0)

这是一个不错的实现,但是我在模型描述中忘了一个。

serialize : interest_list, Array

答案 2 :(得分:0)

您可以实现自己的ArrayInclusionValidator

# app/validators/array_inclusion_validator.rb
class ArrayInclusionValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    # your code here

    record.errors.add(attribute, "#{attribute_name} is not included in the list")
  end
end

在模型中,它看起来像这样:

# app/models/model.rb
class YourModel < ApplicationRecord
  ALLOWED_TYPES = %w[one two three]
  validates :type_of_anything, array_inclusion: { in: ALLOWED_TYPES }
end

示例可在此处找到: