通过ActiveRecord定义自定义验证器

时间:2015-11-01 11:02:31

标签: ruby-on-rails

如何定义允许名字或姓氏为空但不是两者的自定义验证器

我的个人资料类:

class Profile < ActiveRecord::Base
     belongs_to :user

     validates :first_name, allow_nil: true
     validates :last_name, allow_nil: true

     validate :first_xor_last


    def first_xor_last
     if (first_name.nil? and last_name.nil?)
        errors[:base] << ("Specify a first or a last.")
      end
    end

我尝试通过self first_xor_last函数创建但不起作用。

我接受了这个rspec测试:

context "rq11" do
       context "Validators:" do
         it "does not allow a User without a username" do
           expect(User.new(:username=> "")).to_not be_valid
         end
         it "does not allow a Profile with a null first and last name" do
           profile = Profile.new(:first_name=>nil, :last_name=>nil, :gender=>"male")
           expect(Profile.new(:first_name=>nil, :last_name=>nil, :gender=>"male")).to_not be_valid
         end
         it "does not allow a Profile with a gender other than male or female " do
           expect(Profile.new(:first_name=>"first", :last_name=>"last", :gender=>"neutral")).to_not be_valid
         end
         it "does not allow a boy named Sue" do
           expect(Profile.new(:first_name=>"Sue", :last_name=>"last", :gender=>"male")).to_not be_valid
         end
       end
     end

我应该通过它。

谢谢,迈克尔。

3 个答案:

答案 0 :(得分:1)

首先,allow_nill不是有效的验证器。您应该使用presenceabsence

除非您确实需要同时为这两个字段添加自定义消息,否则无需使用自定义验证程序,只需执行以下操作:

class Profile < ActiveRecord::Base
  belongs_to :user

  validates :first_name, :last_name, presence: true

end

如果您想允许其中任何一个,可以使用conditional validation

class Profile < ActiveRecord::Base
  belongs_to :user

  validates :first_name, presence: true, unless: "last_name.present?"
  validates :last_name, presence: true, unless: "first_name.present?"

end   

答案 1 :(得分:0)

而不是:

errors[:base] << ("Specify a first or a last.")

DO

errors.add(:base, "Specify a first or a last.")

编辑:

您获得的错误消息不是由您的自定义验证引起的,而是由另外两个似乎不需要的验证引起的,只是摆脱了这两行:

 validates :first_name, allow_nil: true
 validates :last_name, allow_nil: true

答案 2 :(得分:0)

class Profile < ActiveRecord::Base
  belongs_to :user
  validate :presence_of_first_or_last_name

  def presence_of_first_or_last_name
    if (first_name.blank? and last_name.blank?)
      errors[:base] << ("Specify a first or a last.")
    end
  end
end

您可以丢失两个validates :first_name, allow_nil: true验证,因为它们绝对没有任何效果。

您可能希望使用ActiveSupport方法.nil?而不是.blank?,它不仅检查nil,还检查值是空字符串""还是只包含空格。< / p>

同样正如David Newton所指出的,XOR是eXclusive OR,它是first_name或last_name但不是两者。我尝试根据ActiveModel::Validations的一般方案命名验证器 - 这是一个描述性名称,用于说明执行何种验证。