2009-09-25 3 views
4

J'essaie d'implémenter before_destroy sur un modèle. Pendant que je suis ce before_destroy example je reçois soit une erreur NameError ou finis avec quelque chose qui ne fait pas le before_destroy. Quel est le problème avec ma syntaxe?Ruby on Rails before_destroy provoquant NameError

class Person < ActiveRecord::Base 

    has_many :book_loans, :order => 'return_date desc' 
    has_many :books, :through => :book_loans 

    before_destroy 
    errors.add_to_base "Cannot delete borrower with loans" unless 
                  book_loans.count == 0 
end 

Est-ce que ne compilera pas

before_destroy 
    errors.add_to_base "Cannot delete borrower with loans" unless 
                  book_loans.count == 0 

ne fonctionne pas

def before_destroy 
    errors.add_to_base "Cannot delete borrower with loans" unless 
                 book_loans.count == 0 
end 

Répondre

6

Vous ne pouvez pas ajouter des erreurs before_destroy, car ils ne seront pas un impact sur la validation. Vous devez ajouter les erreurs avant la validation, par ex. before_validation. Il existe des rappels supplémentaires, before_validation_on_create et before_validation_on_update. Il n'y a pas de version on_destroy, cependant, parce que save et valid? n'est jamais appelée, donc ajouter des erreurs de validation lorsque vous essayez de détruire quelque chose serait inutile. En d'autres termes: votre before_destroy s'exécute, mais cela n'affecte rien, car rien ne vérifie les erreurs de validation lorsque vous détruisez des enregistrements.

Voici une prise en compte de la mise en œuvre de quelque chose qui empêche la sauvegarde d'enregistrements en fonction de certaines conditions.

before_destroy :require_no_book_loans 

private 

def require_no_book_loans 
    raise ActiveRecord::RecordInvalid unless book_loans.count == 0 
end 

Vous pouvez également créer votre propre classe d'erreur et l'augmenter.

FYI: Vous êtes censé passer un bloc à before_destroy dans votre exemple d'erreur de syntaxe.

before_destroy {|r| 
    r.errors.add_to_base "Foo" # ... 
} 
+0

Alors comment éviter la destruction d'une personne qui a des prêts? – ahsteele

+0

Je vais mettre à jour la réponse, sec :) –

+0

Sweet donc cela va générer une erreur. Considérant que des exceptions ne devraient se produire que dans des circonstances exceptionnelles, serais-je mieux d'empêcher que le lien de destruction n'apparaisse même lorsque l'utilisateur a des prêts? – ahsteele