2012-01-30 15 views
7

İki modelim var: İndirim birçok Businsses'e ait ve aittir.Before_save ilişkilendirme geri bildirimleri içinde bir doğrulama hatası nasıl ekleyebilirim

Bir İndirim'in her zaman başka bir koşulla birlikte en az bir işletmeye sahip olduğunu doğrulamak istiyorum (örneğin 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 

Ancak bu (hiçbir doğrulama hataları kaldırdı) çalışmıyor ve bunu sadece bir geri çağırma değil, bir doğrulama olduğundan bu muhtemelen fark: Aşağıdaki çalıştı. Nasıl kodlayabilirim, ben errors'u özel doğrulama gibi yapabilirim?

(ajax) Ben kontrolör eylemi:

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 

cevap

8

Before_remove geri aramada veya doğrulama yönteminin kendisinde neler olup bittiği sözdiziminiz olabilir. Ayrıca, içeride yapılıp yapılamayacağını görmek için geri arama yönteminde bazı hata ayıklama kodlarını da eklemek isteyebilirsiniz.

* İşlemin yalnızca geri arama yönteminde bir istisna kaldırılmışsa durdurulacağını unutmayın.

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 

kontrolör özü:

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

Not Association Callback Documentation.

+0

Teşekkürler, kontrol ettim ve yöntemden geçti. Eğer 'hatayı' yükseltirsem, hatayı beklendiği gibi yükseltirdi. – lulalala

+0

Cevabı daha fazla bilgi ile güncelledim. İşlemi durdurmak için geri aramada bir istisna oluşturmak isteyeceksiniz. Bunu yaparken, eylemi yeniden oluşturmak için kontrolörde bazı istisna işlemleri yapmak isteyeceksiniz. – miked

+2

Yürütmeyi durdurmak için false de döndürebilirsiniz. "Geridönüşüm zincirinin tamamı bir işleme sarılır. Geri arama yönteminden herhangi biri tam olarak yanlış olanı döndürürse veya bir istisnayı artırırsa, yürütme zinciri durdurulur ve geri dönüşler yalnızca bir istisna oluşturarak başarılabildiğinde bir ROLLBACK verilir." http://guides.rubyonrails.org/active_record_validations_callbacks.html#halting-execution – amree

2

Bunun için :presence => true ile validates yöntemi kullanabilirsiniz. Esas bu en az bir üye var sağlayacak bir ilişki doğrulama ile ilgili :presence => true kullanılması

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

.

+0

sayesinde bu durum olduğundan, muhtemelen eylemi yeniden işlemek için denetleyicinizdeki istisna mantığını işlemek isteyeceksiniz ancak bu doğrulamada bir ek alan daha kontrol etmeliyim (yyy? kısmı). Bu yüzden özel bir doğrulama yazmalıyım. – lulalala

+1

Sorunuzu düzenleyebilir ve tam olarak aradığınızı daha iyi tanımlayabilir misiniz? Yyy ya da açıklamanızda olması gereken şey hakkında hiçbir şey söylemiyorsunuz ve yyy ile yapmaya çalıştığınız koddan gerçekten net değil. –

+0

kötüyüm, yyy'yi mi söyledim? aktif mi Ancak, boolean'ı değerlendiren herhangi bir keyfi ifade olabilir. – lulalala

İlgili konular