Ruby复杂验证

时间:2010-05-07 18:44:25

标签: ruby-on-rails ruby

拥有属于某个类别的产品。想要在短时间内创建促销活动(比方说一两周),但在此期间每个类别只能促销一次。

如何为此创建自定义验证?

product class
  belongs_to :categories

  name:string
  desc:text  
  reg_price:decimal  
  category_id:integer  
  promo_active:boolean  
  promo_price:decimal  
  promo_start:datetime  
  promo_end:datetime
end

category class
  has_many :products

  name:string
end

更新可能的解决方案???

    class Product < ActiveRecord::Base
  attr_accessible :name, :desc, :reg_price, :category_id, :promo_active, :promo_price, :promo_start, :promo_end

  belongs_to  :category

  #validate :check_unique_promo
  #Tweaked original to be more exact and 
  #Give clue if its the start or end date with the error.
  validate :check_unique_promo_start
  validate :check_unique_promo_end

def check_unique_promo
  errors.add_to_base("Only 1 promo allowed") unless Product.count(:conditions => ["promo_active = ? AND promo_end < ?", true, self.promo_start]) == 0
end  

def check_unique_promo_start
  errors.add_to_base("Start date overlaps with another promotion.") unless self.promo_active == false || Product.count(:conditions => ['promo_end BETWEEN ? AND ? AND category_id = ? AND promo_active = ? AND id != ?',self.promo_start, self.promo_end, self.category_id, true, self.id]) == 0
end

def check_unique_promo_end
   errors.add_to_base("End date overlaps with another promotion.") unless self.promo_active == false || Product.count(:conditions => ['promo_start BETWEEN ? AND ? AND category_id = ? AND promo_active = ? AND id != ?',self.promo_start, self.promo_end, self.category_id, true, self.id]) == 0
end
end

如果promo_active为性能,我会跳过自我。

1 个答案:

答案 0 :(得分:1)

我会使用validates_uniqueness_of验证:

class Product < ActiveRecord::Base
  belongs_to :categories
  validates_uniqueness_of :promo_active, :scope => :category_id, :allow_nil => true

  before_save :update_promos

  private
  def update_promos
    # custom code to set :promo_active to nil if the promo is 
    # not active and to something else if it is active
  end
end

拿2:

validate :check_unique_promo

def check_unique_promo
  errors.add_to_base("Only 1 promo allowed") unless Product.count(:conditions => ["active_promo = 1 AND promo_end < ?", self.promo_start]) == 0
end