简体   繁体   中英

How to validate inclusion of array content in rails

Hi I have an array column in my model:

t.text :sphare, array: true, default: []

And I want to validate that it includes only the elements from the list ("Good", "Bad", "Neutral")

My first try was:

 validates_inclusion_of :sphare, in: [ ["Good"], ["Bad"], ["Neutral"] ]

But when I wanted to create objects with more then one value in sphare ex(["Good", "Bad"] the validator cut it to just ["Good"].

My question is:

How to write a validation that will check only the values of the passed array, without comparing it to fix examples?

Edit added part of my FactoryGirl and test that failds:

Part of my FactoryGirl:

sphare ["Good", "Bad"]

and my rspec test:

  it "is not valid with wrong sphare" do
    expect(build(:skill, sphare: ["Alibaba"])).to_not be_valid
  end
 it "is valid with proper sphare" do
    proper_sphare = ["Good", "Bad", "Neutral"]
    expect(build(:skill, sphare: [proper_sphare.sample])).to be_valid
  end  

Do it this way:

validates :sphare, inclusion: { in: ["Good", "Bad", "Neutral"] }

or, you can be fancy by using the short form of creating the array of strings: %w(Good Bad Neutral) :

validates :sphare, inclusion: { in: %w(Good Bad Neutral) }

See the Rails Documentation for more usage and example of inclusion .

Update

As the Rails built-in validator does not fit your requirement, you can add a custom validator in your model like following:

validate :correct_sphare_types

private

def correct_sphare_types
  if self.sphare.blank?
    errors.add(:sphare, "sphare is blank/invalid")
  elsif self.sphare.detect { |s| !(%w(Good Bad Neutral).include? s) }
    errors.add(:sphare, "sphare is invalid")
  end
end

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