如何验证接受一个布尔值或另一个布尔值

时间:2015-07-30 23:39:16

标签: ruby-on-rails validation mongoid

我需要验证表单中是否接受了一个布尔值或另一个布尔值。

我试过

validates_acceptance_of :seller_accepted || :buyer_accepted

但这不起作用

1 个答案:

答案 0 :(得分:2)

Rails验证器是元编程宏。在评估类时读入。他们添加一个列表,在调用valid?类时运行验证规则(回调)。

这就是为什么你必须使用ifunless选项与lambda,proc或在验证实例时实际调用的符号。

这是您的代码无法运行的原因之一。使用ifunless条件也不起作用 - 在评估seller_accepted之前,Rails会向if: :buyer_accepted添加和错误。

在这种情况下,最简单的解决方法可能是创建自定义验证方法:

validate :one_of_two_accepted

def one_of_two_accepted
  unless acceptable?(seller_accepted) || acceptable?(buyer_accepted)
    errors.add(:seller_accepted, "Must accept buyer or seller.")
  end
end

def acceptable?(val)
  ['1', true, 'yes'].include?(val)
end 

acceptable?方法模拟validates_acceptance_of完成的类型转换。

修改。

这是完整的,最小的,经验证的例子:

class Thing < ActiveRecord::Base

  attr_accessor :seller_accepted
  attr_accessor :buyer_accepted

  validate :one_of_two_accepted

  def acceptable?(val)
    ['1', true].include?(val)
  end

  def one_of_two_accepted
    unless acceptable?(seller_accepted) || acceptable?(buyer_accepted)
      errors.add(:seller_accepted, "Must accept buyer or seller.")
    end
  end
end
require 'rails_helper'

RSpec.describe Thing, type: :model do

  let(:thing) { Thing.new }

  describe 'acceptable?' do
    it "accepts '1'" do
      expect(thing.acceptable?('1')).to be_truthy
    end

    it "accepts 'true' " do
      expect(thing.acceptable?(true)).to be_truthy
    end

    it "rejects others" do
      expect(thing.acceptable?('gobbeligook')).to be_falsy
      expect(thing.acceptable?('no')).to be_falsy
      expect(thing.acceptable?(nil)).to be_falsy
      expect(thing.acceptable?(0)).to be_falsy
    end
  end

  describe 'custom validation' do
    it 'is invalid if neither seller or buyer is accepted' do
        expect(thing.valid?).to be_falsy
        expect(thing.errors[:seller_accepted]).to include "Must accept buyer or seller."
    end

    it 'is valid if seller_accepted' do
      thing.seller_accepted = true
      thing.valid?
      expect(thing.errors).to_not have_key :seller_accepted
    end

    it 'is valid if buyer_accepted' do
      thing.buyer_accepted = true
      thing.valid?
      expect(thing.errors).to_not have_key :seller_accepted
    end
  end
end