简体   繁体   中英

validates array elements inclusion using inclusion: { in: array }

I use acts-as-taggable-on gem to populate a user interests on a User model like this

# User.rb
acts_as_taggable
acts_as_taggable_on :interests

As I populate the interest_list array, I need to check that the given values matches against a constant array to make sure these are accepted values, something like this

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

The code above returns the following error

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

I can see the inclusion doesn't realize it should iterate over the array elements instead of s considering as a plain string but I'm not sure how to achieve this. Any idea?

The standard inclusion validator will not work for this use case, since it checks that the attribute in question is a member of a given array. What you want is to check that every element of an array (the attribute) is a member of a given array.

To do this you could create a custom validator, something like this:

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

I'm getting the elements of interest_list not in VALID_INTERESTS by taking the difference of these two arrays.

I haven't actually tried this code so can't guarantee it will work, but the solution I think will look something like this.

这是一个很好的实现,但我忘记了模型描述中的一个。

serialize : interest_list, Array

You can implement your own 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

In the model it looks like this:

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

Examples can be found here:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM