【问题标题】:before_validation fails in railsbefore_validation 在 Rails 中失败
【发布时间】:2013-03-07 06:37:54
【问题描述】:

我正在使用 Rails 3.2.11、Mac OS X Mountain Lion、Ruby 1.9.3

所以我有这段代码:

class Points < ActiveRecord::Base
validates :id, :presence => true

before_create :validate_points

def validate_points
  if self.amount < 0
    Rails.logger.error "Invalid amount of points"
  else
    save!
  end
end

结束

我想限制用户插入负值。但由于某种原因, validate_points 方法不起作用。有什么我做错了吗?谢谢。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3


    【解决方案1】:

    你应该使用Rails提供的validates_numericality_of方法

    validates :amount, numericality: { greater_than_or_equal_to: 0 }
    

    更新:您的代码存在问题

    您的代码有几个问题。

    1. 您正在使用before_create,它在记录保存到数据库之前被调用。以这种方式防止数据库提交的唯一方法是在回调中返回 false,但这不是好的做法。
    2. validate_points 调用 save! 但在 before_create 回调中调用,因此您将记录保存 2x 更新:正如 rxing 所指出的,这将导致无限循环,而不仅仅是 2 次保存到数据库

    如果您不想使用内置验证,请尝试以下操作

    validate :validates_amount_points
    
    def validates_amount_points
      errors.add_to :amount, 'must be greater than or equal to 0' if amount < 0
    end
    

    【讨论】:

      【解决方案2】:

      您需要使用“验证”而不是 before_create 挂钩。 顺便说一句,您的 before_create 也不正确。它会引发 SystemStackError: stack level too deep since "save!"将递归触发 before_create。

      【讨论】:

      • 这是不正确的。 before_create 只会被触发一次。如果是before_save,那我同意你的看法。
      • 当你保存一个new_record时,before_create将被递归调用,因为它没有机会成为一个'现有记录'。这就是为什么它会在 before_create 中处于死循环。
      • 嗯,很有趣。现在我想多了,你是对的。它永远不会超过创造记录的地步。不错的收获!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-19
      • 1970-01-01
      • 2011-03-17
      • 2014-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多