【问题标题】:Rails accepts_nested_attributes_for callbacksRails 接受_nested_attributes_for 回调
【发布时间】:2010-05-11 22:29:19
【问题描述】:

我有两个模型 TicketTicketComment,TicketComment 是 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

我想做的是模仿 Trac 中的功能,如果用户对工单进行更改和/或添加评论,则会向分配给工单的人员发送一封电子邮件。

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

如何检测模型的更改 (ticket.changes) 以及是否创建了新评论 (ticket.cmets) 并在回调方法中的一封电子邮件?

【问题讨论】:

  • 啊哈,我想我误解了你的问题。道歉。我会尝试提出一个实际的解决方案。

标签: ruby-on-rails callback nested-class


【解决方案1】:

您可以使用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

这应该让你开始:)

与链接的 cmets 有关的问题。如果你这样做:

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

【讨论】:

  • 我已经让脏代码工作了,我理解那部分。这里的困难部分是确定是否创建了 TicketComment,它是一个子对象。如果包含一个,我需要添加它的内容。不幸的是,像这样的孩子不会出现在“更改”数组中,因为它不是更改(不脏)
  • 嗨,我相应地扩展了我的答案。现在更有意义了吗?
  • 是的,我明白这一切.. 我明白肮脏。脏虽然对我没有帮助。提交表单时,在控制器中我有一个哈希(params [:ticket]),创建了一个新的ticket_comment,并在该哈希中提供。工单对象已保存。 ticket_comment 已保存。现在,在回调中,我有 SELF,我如何知道添加了评论,以及如何获取该评论?
  • 嗯,你有自我。如果集合中的某些内容发生了变化,self.ticket_cmets.changed 将为真;如果您在保存前检查。成功更新后,您可以发送电子邮件。我更新了答案以显示这一点。
猜你喜欢
  • 2011-03-04
  • 1970-01-01
  • 2013-12-24
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2012-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多