如何在before_save关联回调中添加验证错误

时间:2012-01-30 09:12:17

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

我有两种模式:折扣已经并且属于许多Businsses。

我想验证折扣总是至少有一个商家和另一个商品(例如active?)。我尝试了以下方法:

class Discount < ActiveRecord::Base
  has_and_belongs_to_many :businesses,
    before_remove: :validate_publish_status

  def validate_publish_status(*arg)
    if active? && businesses.count == 0
      errors[:active] << 'discount with no business'
    end
  end
end

然而,这不起作用(没有引发验证错误),我意识到这可能是因为它只是一个回调,而不是验证。我如何对其进行编码以便我可以使用errors,就像我自定义验证一样?

我有的控制器动作(对于ajax):

  def remove
    @business = Business.find(params[:business_id])
    if @business.in? @discount.businesses
      @discount.businesses.delete(@business)
    end
    render json: @business.as_json(only: [:id, :type, :name, :address],
                                   methods: [:city_name, :country_name]).
      merge(paths: paths_for(@discount, @business))
  rescue ActiveRecord::RecordInvalid # even tried the generic Exception
    respond_to do |f|
      f.json { render json: {error: $!.message}, status: 403 }
    end
  end

2 个答案:

答案 0 :(得分:9)

可能是您在before_remove回调中的语法或验证方法本身发生了什么。您还可能希望在回调方法中添加一些调试代码,以查看它是否在那里进行。

*请注意,只有在回调方法中引发异常时才会停止事务。既然如此,您可能希望在控制器中处理异常逻辑以重新呈现操作:

class Discount < ActiveRecord::Base
  has_and_belongs_to_many :businesses, :before_remove => :validate_publish_status

  def validate_publish_status(*args)
   if yyy? && businesses.count == 0
    errors.add(:yyy,'discount with no business')
    raise "Unable to remove business."
   end
  end

end

控制器要点:

  def update
    @company.find(params[:id])
    if @company.update_attributes(params[:company])
      ...
    else
      render :action => 'edit'
    end
  rescue
    render :action=>'edit'
  end

请注意Association Callback Documentation.

答案 1 :(得分:2)

您可以将validates方法与:presence => true一起使用。

class Discount < ActiveRecord::Base
  has_and_belongs_to_many :businesses
  validates :businesses, :presence => true
end

在关联验证程序上使用:presence => true将确保至少有一个关联成员存在。