验证模型属性大于另一个

时间:2009-12-22 13:03:36

标签: ruby-on-rails activerecord

首先,让我说我是非常 Rails的新手(玩了一两次,但强迫自己现在用它写一个完整的项目,昨天就开始了。)

我现在正在尝试验证模型属性(术语?)是否大于另一个。这似乎是具有validates_numericality_of选项的greater_than的完美实例,但是唉,这会引发错误告诉我greater_than expects a number, not a symbol。如果我尝试对该符号.to_f进行类型转换,则会出现undefined method错误。

这是我最终做的事情,我很好奇是否有更好的方法。它只是一个控制项目发布的简单系统,我们只有主要/次要版本(一点),所以浮动感觉就像这里的正确决定。

class Project < ActiveRecord::Base
    validates_numericality_of :current_release
    validates_numericality_of :next_release
    validate :next_release_is_greater

    def next_release_is_greater
        errors.add_to_base("Next release must be greater than current release") unless next_release.to_f > current_release.to_f
    end
end

这是有效的 - 它通过了相关的单元测试(下面是为了您的观看乐趣),我只是好奇是否有一种更简单的方法 - 我本来可以尝试的其他方式。

相关单元测试:

# Fixture data:
#   PALS:
#     name: PALS
#     description: This is the PALS project
#     current_release: 1.0
#     next_release: 2.0
#     project_category: 1
#     user: 1
def test_release_is_future
    project = Project.first(:conditions => {:name => 'PALS'})
    project.current_release = 10.0
    assert !project.save

    project.current_release = 1.0
    assert project.save
end

4 个答案:

答案 0 :(得分:24)

正如您所注意到的,唯一的方法是使用自定义验证器。 :greater_than选项应该是一个整数。以下代码将不起作用,因为当前版本和下一版本仅在实例级别可用。

class Project < ActiveRecord::Base
  validates_numericality_of :current_release
  validates_numericality_of :next_release, :greater_than => :current_release
end

greater_than选项的目的是根据静态常量或其他类方法验证值。

所以,不要介意并继续使用自定义验证器。 :)

答案 1 :(得分:9)

validates_numericality_of接受a large list of options,其中一些可以提供proc或符号(这意味着您基本上可以传递属性或整个方法)。

验证属性的数值高于另一个值:

class Project < ActiveRecord::Base
  validates_numericality_of :current_release, less_than: ->(project) { project.next_release }

  validates_numericality_of :next_release, 
    greater_than: Proc.new { project.current_release }
end

为了澄清,这些选项中的任何一个都可以接受过程或符号:

  • :greater_than
  • :greater_than_or_equal_to
  • :equal_to :less_than
  • :less_than_or_equal_to

validates_numericality docs: http://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_numericality_of

使用带有验证的过滤器 http://guides.rubyonrails.org/active_record_validations.html#using-a-proc-with-if-and-unless

答案 2 :(得分:6)

使用Rails 3.2,您可以通过传入proc来验证两个字段。

validates_numericality_of :next_release, :greater_than => Proc.new {|project| project.current_release }

答案 3 :(得分:-2)

这是执行自定义验证的最佳方式,但是,您可能希望查看像factory_girl这样的东西作为灯具的替代品(它看起来像您正在使用):

http://github.com/thoughtbot/factory_girl

您的单元测试将如下所示:

def test_...
    Factory.create(:project, :current_release => 10.0)
    assert !Factory.build(:project, :current_release => 1.0).valid?
end