Rails accept_nested_attributes_for回调 [英] Rails accepts_nested_attributes_for callbacks
问题描述
我有两个模型 Ticket 和 TicketComment ,TicketComment是Ticket的子代。
ticket.rb
; ActiveRecord :: Base
has_many:ticket_comments,:dependent => :destroy,:order => 'created_at DESC'
#允许从票单内创建票证注释
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
b $ b
我想要做的是模仿Trac中的功能,其中如果用户更改票证和/或添加评论,电子邮件将发送给分配给票证的人员。 p>
我想使用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
..在这里做一些检查..
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 =
如果ticket_comments.changed
#查找注释
ticket_comments。每个| c |
@logmsg<< comment changedif c.changed?
@logmsg<< comment addedif c.new_record?
end
end
end
end
def send_mail_if_needed
if @ logmsg.size> 0
..发送邮件..
end
end
I have two models Ticket and TicketComment, the TicketComment is a child of Ticket.
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
What I want to do is mimic the functionality in Trac, where if a user makes a change to the ticket, and/or adds a comment, an email is sent to the people assigned to the ticket.
I want to use an after_update or after_save callback, so that I know the information was all saved before I send out emails.
How can I detect changes to the model (ticket.changes) as well as whether a new comment was created or not (ticket.comments) and send this update (x changes to y, user added comment 'text') in ONE email in a callback method?
you could use the ActiveRecord::Dirty module, which allows you to track unsaved changes.
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
So inside a before_update of before_create you should those (you can only check before the save!).
A very nice place to gather all these methods is in a Observer-class TicketObserver, so you can seperate your "observer"-code from your actual model.
E.g.
class TicketObserver < ActiveRecord::Observer
def before_update
.. do some checking here ..
end
end
to enable the observer-class, you need to add this in your environment.rb
:
config.active_record.observers = :ticket_observer
This should get you started :)
What concerns the linked comments. If you do this:
new_comment = ticket.ticket_comments.build
new_comment.new_record? => true
ticket.comments.changed => true
So that would be exactly what you would need. Does that not work for you? Note again: you need to check this before saving, of course :)
I imagine that you have to collect the data that has changed in a before_create or before_update, and in an after_update/create actually send the mail (because then you are sure it succeeded).
Apparently it still is not clear. I will make it a bit more explicit. I would recommend using the TicketObserver class. But if you want to use the callback, it would be like this:
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
这篇关于Rails accept_nested_attributes_for回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!