Rails接受_ented_attributes_for回调
我有两个模型Ticket和TicketComment ,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