Rails接受_ented_attributes_for回调

我有两个模型TicketTicketComment ,TicketComment是Ticket的孩子。

ticket.rb

class Ticket  :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 

我想要做的是模仿Trac中的function,如果用户对故障单进行更改和/或添加注释,则会向分配给故障单的人员发送电子邮件。

我想使用after_update或after_save回调,以便在发送电子邮件之前我知道所有信息都已保存。

如何检测模型的更改(ticket.changes)以及是否创建了新评论(ticket.comments)并在一封电子邮件中发送此更新(x更改为y,用户添加评论’text’)一个回调方法?

您可以使用ActiveRecord :: Dirty模块,它允许您跟踪未保存的更改。

例如

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

所以在before_create的before_update中你应该那些(你只能在保存之前检查!)。

收集所有这些方法的一个非常好的地方是Observer-class TicketObserver,因此您可以从实际模型中分离出“观察者”代码。

例如

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

要启用观察者类,您需要在environment.rb添加它:

 config.active_record.observers = :ticket_observer 

这应该让你开始:)

关联的评论有什么关系。 如果你这样做:

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

所以这正是你需要的。 这不适合你吗? 再次注意:你需要在保存之前检查一下,当然:)

我想你必须收集在before_create或before_update中更改的数据,并在after_update / create中实际发送邮件(因为那时你确定它成功了)。

显然它仍然不清楚。 我会更明确一点。 我建议使用TicketObserver类。 但是如果你想使用回调,它将是这样的:

 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