2010-05-11 11 views
4

J'ai 2 modèles Ticket et TicketComment, le TicketComment est un enfant de Ticket.Rails accepte_nested_attributes_for callbacks

ticket.rb

class Ticket < ActiveRecord::Base 
    has_many :ticket_comments, :dependent => :destroy, :order => 'created_at DESC' 

    # allow the ticket comments to be created from within a ticket form 
    accepts_nested_attributes_for :ticket_comments, :reject_if => proc { |attributes| attributes['comment'].blank? } 
end 

ticket_comment.rb

class TicketComment < ActiveRecord::Base 
    belongs_to :ticket 

    validates_presence_of :comment 
end 

Ce que je veux faire est d'imiter la fonctionnalité dans Trac, où si une l'utilisateur apporte une modification au ticket, et/ou ajoute un commentaire, un email est envoyé aux personnes affectées au ticket.

Je souhaite utiliser un rappel after_update ou after_save, afin que je sache que toutes les informations ont été enregistrées avant d'envoyer des e-mails. Comment puis-je détecter des changements dans le modèle (ticket.changes) et savoir si un nouveau commentaire a été créé ou non (ticket.comments) et envoyer cette mise à jour (x change pour y, l'utilisateur ajoute un commentaire 'texte') dans un email dans une méthode de rappel?

+0

Aha, je suppose que je mal interprété votre question. Excuses. Je vais essayer de trouver une solution réelle. –

Répondre

4

Vous pouvez utiliser le module ActiveRecord::Dirty, qui vous permet de suivre les modifications non enregistrées.

E.g.

t1 = Ticket.first 
t1.some_attribute = some_new_value 
t1.changed? => true 
t1.some_attribute_changed? => true 
t1.some_attribute_was => old_value 

donc dans un before_update de before_create vous devriez ceux (vous ne pouvez vérifier avant la sauvegarde!).

Un très bon endroit pour rassembler toutes ces méthodes est dans un TicketObserver Observer-class, ainsi vous pouvez séparer votre "observateur" -code de votre modèle actuel.

E.g.

class TicketObserver < ActiveRecord::Observer 
    def before_update 
    .. do some checking here .. 
    end 
end 

pour permettre à la classe d'observateur, vous devez ajouter dans votre environment.rb:

config.active_record.observers = :ticket_observer 

Cela devrait vous aider à démarrer :)

ce qui concerne les commentaires liés. Si vous faites ceci:

new_comment = ticket.ticket_comments.build 
new_comment.new_record? => true 
ticket.comments.changed => true 

Donc ce serait exactement ce dont vous auriez besoin. Cela ne fonctionne-t-il pas pour vous? Note encore: vous devez vérifier cela avant d'enregistrer, bien sûr :)

J'imagine que vous devez collecter les données qui ont changé dans un before_create ou before_update, et dans un after_update/create envoyer réellement le courrier (parce que alors vous êtes sûr qu'il a réussi).

Apparemment, ce n'est toujours pas clair. Je vais le rendre un peu plus explicite. Je recommanderais d'utiliser la classe TicketObserver.Mais si vous voulez utiliser la fonction de rappel, ce serait comme ceci:

class Ticked 

    before_save :check_state 
    after_save :send_mail_if_needed 

    def check_state 
    @logmsg="" 
    if ticket_comments.changed 
     # find the comment 
     ticket_comments.each do |c| 
     @logmsg << "comment changed" if c.changed? 
     @logmsg << "comment added" if c.new_record? 
     end 
    end 
    end 

end 
def send_mail_if_needed 
    if @logmsg.size > 0 
    ..send mail.. 
    end 
end 
+0

J'ai déjà le code sale qui fonctionne, je comprends cette partie. La partie difficile ici est de déterminer si un TicketComment a été créé, qui est un objet enfant. Si un était inclus, j'ai besoin d'ajouter son contenu .. Malheureusement, les enfants comme ça n'apparaissent pas dans le tableau 'changes', car ce n'est pas un changement (pas sale) – Rabbott

+0

Salut, j'ai étendu ma réponse en conséquence. Cela a-t-il plus de sens maintenant? – nathanvda

+0

Oui, je comprends tout cela .. Je comprends sale. Dirty ne m'aide pas cependant. Quand un formulaire est soumis, dans le contrôleur j'ai un hash (params [: ticket]), un nouveau ticket_comment a été créé, et est fourni dans ce hash. L'objet ticket est enregistré. le ticket_comment est enregistré. Maintenant, dans le rappel, j'ai SELF, comment puis-je savoir qu'un commentaire a été ajouté, et comment puis-je obtenir ce commentaire? – Rabbott