开发者

Why is :if not being recognised by ActiveRecord validations?

I have a problem where an :if clause within an ActiveRecord validation is not being honoured.

My model has an ip_port attribute which I am validating as being present, numeric and within a certain range. I am trying to ensure that each condition only generates one error. I do not want the situation where an empty attribute results in three messages displayed to the user stating that it is not present, required and not numeric.

This is my model as it stands

class Arc < ActiveRecord::Base
  attr_accessible :ip_port

  validates_presence_of :ip_port
  validates_numericality_of :ip_port, :a开发者_JAVA技巧llow_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

And this is my model spec and its results.

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

My question is why I am getting two errors for a non-numeric ip_port when the :if clause should prevent the validates_inclusion of from being called.

This is Rails 2.3.5 with Ruby 1.8.7 on OS/X 10.6.3


Whilst having a contemplative stroll I have solved my own problem.

The issue is that in order to validate the inclusion within the range it converts the provided value to an int and then checks for inclusion. So for a non-numeric value I will get both a :not_a_number and an :inclusion error.

The answer is to modify the :if clause to use the value before it was typecast so my validates_inclusion_of method becomes

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+$/) }

This then gives me one error for each of three conditions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜