为什么:如果没有被ActiveRecord验证识别?

时间:2010-07-01 09:31:28

标签: ruby-on-rails ruby activerecord

我遇到一个问题,即ActiveRecord验证中的:if子句没有被尊重。

我的模型有一个ip_port属性,我将其验证为存在,数字并且在一定范围内。我试图确保每个条件只生成一个错误。我不希望空属性导致向用户显示三条消息的情况表明它不存在,是必需的而不是数字。

这是我的模型

class Arc < ActiveRecord::Base
  attr_accessible :ip_port

  validates_presence_of :ip_port
  validates_numericality_of :ip_port, :allow_blank => true
  validates_inclusion_of :ip_port, :in => 1025..65535, :allow_blank => true, 
     :if => Proc.new {|arc| arc.ip_port.to_s.match(/^\d+$/) }
end

这是我的模型规范及其结果。

describe Arc do
  it "should be valid with valid attributes" do
    Arc.new(:ip_port => 1200).should be_valid
  end
  it "should be invalid with a non-numberic port" do
    Arc.new(:ip_port => "test").should be_invalid
  end
  it "should be invalid with a missing port" do
    Arc.new(:ip_port => nil).should be_invalid
  end
  it "should have one error with a missing port" do
    a = Arc.new(:ip_port => nil)
    a.should be_invalid
    a.should have(1).errors_on(:ip_port)
  end
  it "should have one error with a non-numeric port" do
    a = Arc.new(:ip_port => "test")
    a.should be_invalid
    a.should have(1).errors_on(:ip_port)
  end
  it "should have one error with a numeric port outside the range" do
    a = Arc.new(:ip_port => 999)
    a.should be_invalid
    a.should have(1).errors_on(:ip_port)
  end
end
Arc
- should be valid with valid attributes
- should be invalid with a non-numberic port
- should be invalid with a missing port
- should have one error with a missing port
- should have one error with a non-numeric port (FAILED - 1)
- should have one error with a numeric port outside the range

1)
'Arc should have one error with a non-numeric port' FAILED
expected 1 errors on :ip_port, got 2
./spec/models/arc_spec.rb:21:

Finished in 0.108245 seconds

我的问题是,当if子句应该阻止调用validates_inclusion时,我为非数字ip_port收到两个错误。

这是在OS / X 10.6.3上使用Ruby 1.8.7的Rails 2.3.5

1 个答案:

答案 0 :(得分:2)

虽然我沉思地漫步,但我已经解决了自己的问题。

问题在于,为了验证范围内的包含,它将提供的值转换为int,然后检查包含。因此,对于非数字值,我将得到:not_a_number和:包含错误。

答案是修改:if子句以在类型转换之前使用该值,因此我的validates_inclusion_of方法变为

validates_inclusion_of :ip_port, :in => 1025..65535, :allow_blank => true, 
  :if => Proc.new {|arc| arc.ip_port_before_type_cast.to_s.match(/^\d+$/) }

然后,这给出了三个条件中的每一个的一个错误。

相关问题