2012-01-30 42 views
7

我有兩種模式:折扣具有並屬於多個總線。如何在before_save關聯回調中添加驗證錯誤

我想驗證一個折扣總是有至少一個業務以及另一個條件(例如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

控制器動作我有(阿賈克斯):

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 

回答

8

可能是您的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.

+0

謝謝,我沒有檢查,它通過該方法。如果我'提出'錯誤',它會按預期提高錯誤率。 – lulalala 2012-01-31 01:33:26

+0

我用更多的信息更新了答案。您需要在回調中引發異常來停止交易。爲此,您可能需要在控制器中執行一些異常處理以重新呈現操作。 – miked 2012-01-31 01:56:38

+2

您也可以返回false來暫停執行。 「整個回調鏈都被包裝在一個事務中,如果在回調方法返回完全爲false或引發異常之後,執行鏈會暫停併發出ROLLBACK;回調只能通過引發異常來完成。 http://guides.rubyonrails.org/active_record_validations_callbacks.html#halting-execution – amree 2012-01-31 01:59:18

2

您可以使用validates:presence => true這一點。

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

在關聯驗證器上使用:presence => true將確保至少有一個關聯成員存在。

+0

謝謝但我需要檢查該驗證中的另一個字段(yyy?部分)。所以我必須寫一個自定義驗證。 – lulalala 2012-01-30 09:50:55

+1

你可以編輯你的問題,並提供一個更好的描述你到底在找什麼嗎?你不會說yyy或你的描述中應該包含什麼內容,而且你的代碼真的不清楚你想用yyy做什麼。 – 2012-01-30 09:53:12

+0

我的不好,我已經改寫了yyy?積極?但它可以是任何評估爲布爾值的任意表達式。 – lulalala 2012-01-31 01:34:16

相關問題