Rab*_*ott 5 ruby-on-rails callback nested-class
我有两个模型Ticket和TicketComment,TicketComment 是 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
Run Code Online (Sandbox Code Playgroud)
ticket_comment.rb
class TicketComment < ActiveRecord::Base
belongs_to :ticket
validates_presence_of :comment
end
Run Code Online (Sandbox Code Playgroud)
我想要做的是模仿 Trac 中的功能,如果用户更改票证和/或添加评论,则会向分配给票证的人员发送电子邮件。
我想使用 after_update 或 after_save 回调,以便我知道在发送电子邮件之前信息已全部保存。
如何检测模型的更改 (ticket.changes) 以及是否创建了新评论 (ticket.comments) 并在一封电子邮件中发送此更新(x 更改为 y,用户添加的评论“文本”)回调方法?
您可以使用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
Run Code Online (Sandbox Code Playgroud)
因此,在 before_create 的 before_update 中,您应该执行这些操作(您只能在保存之前进行检查!)。
收集所有这些方法的一个非常好的地方是观察者类TicketObserver,因此您可以将“观察者”代码与实际模型分开。
例如
class TicketObserver < ActiveRecord::Observer
def before_update
.. do some checking here ..
end
end
Run Code Online (Sandbox Code Playgroud)
要启用观察者类,您需要将其添加到您的environment.rb:
config.active_record.observers = :ticket_observer
Run Code Online (Sandbox Code Playgroud)
这应该可以帮助您开始:)
链接的评论涉及什么。如果你这样做:
new_comment = ticket.ticket_comments.build
new_comment.new_record? => true
ticket.comments.changed => true
Run Code Online (Sandbox Code Playgroud)
所以这正是您所需要的。这对你不起作用吗?再次注意:当然,您需要在保存之前检查这一点:)
我想您必须收集在 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
Run Code Online (Sandbox Code Playgroud)