Rails“是否可以知道在验证方法中执行的操作(更新,创建)?

时间:2011-03-23 01:58:48

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

平台:Rail 3.0 数据库:mysql 5.1

业务要求:一次只能发布一件产品。退回已发出的项目后,可以发出相同产品的新项目。可以一次发布不同产品的多件商品。

为了实现上述业务要求,我正在检查是否已经在同一日期范围内为同一产品发出了一个项目(通过检查我下面的日期是否重叠)。

     class Item < ActiveRecord::Base
         validate :validate_one_item_for_product
         def validate_one_item_for_product
               items = Item.where( "issue_date < ? and return_date > ? and product_id = ?", return_date, issue_date, product_id)
               errors.add( :base, "item already issued for this product, not returned yet") if items.size > 0
         end
     end

上面定义的验证在创建时工作正常但在更新的情况下我需要实现不同的逻辑。我不想为同一要求定义两种方法。所以我想根据它的更新或创建操作来实现对函数的检查。有什么方法我可以知道触发验证的操作是更新还是删除?

2 个答案:

答案 0 :(得分:2)

简单的解决方案是使用参数定义验证它的方法,然后使用不同的:on =>调用进行两次验证,然后使用参数调用第一个方法。

此外,如果有帮助,您可以使用new_record?来告诉您是否正在创建对象(在保存之前)

答案 1 :(得分:1)

验证可以随时运行,而不仅仅是createsaveupdate_attributes等。所以,即使你知道哪种方法触发了验证(你也可以破解)使用caller)的输出,你不应该使用它,因为它可能是完全有效但完全出乎意料的。

然而,一切都不会丢失。您可以通过调用persisted?来检查记录是否已保留。

 class Item < ActiveRecord::Base
   validate :validate_one_item_for_product, :unless => :persisted?

 private

   def validate_one_item_for_product
     items = Item.where(
       "issue_date < ? and return_date > ? and product_id = ?",
       return_date, issue_date, product_id)
     if items.size > 0
       errors.add(:base,
         "item already issued for this product, not returned yet") 
     end
   end
 end