代码之家  ›  专栏  ›  技术社区  ›  Steve Weet

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

  •  2
  • Steve Weet  · 技术社区  · 14 年前

    我有一个问题,在ActiveRecord验证中的:if子句没有得到遵守。

    我的模型有一个IP端口属性,我正在验证该属性是否存在,是否为数字,是否在某个范围内。我试图确保每个条件只生成一个错误。我不希望出现这样的情况:一个空属性导致向用户显示三条消息,说明它不存在、必需且不是数字。

    这是我的模型

    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-include被调用时,为什么非数字IP端口会出现两个错误。

    这是在OS/X 10.6.3上带有Ruby1.8.7的Rails 2.3.5。

    1 回复  |  直到 14 年前
        1
  •  2
  •   Steve Weet    14 年前

    我一边沉思一边散步,一边解决了自己的问题。

    问题是,为了验证范围内的包含,它将提供的值转换为int,然后检查是否包含。所以对于一个非数字值,我将得到一个:非数字和一个:包含错误。

    答案是修改:if子句,以便在类型转换之前使用该值,以便验证方法的包含性

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

    这会给我三个条件中的每一个都带来一个错误。