繁体   English   中英

确定在 Rails after_save 回调中更改了哪些属性?

[英]Determine what attributes were changed in Rails after_save callback?

我正在我的模型观察器中设置 after_save 回调,以便仅当模型的已发布属性从 false 更改为 true 时才发送通知。 等方法改了? 仅在保存模型之前有用,我目前(但未成功)尝试这样做的方式如下:

def before_save(blog)
  @og_published = blog.published?
end

def after_save(blog)
  if @og_published == false and blog.published? == true
    Notification.send(...)
  end
end

有没有人对处理这个问题的最佳方法有任何建议,最好使用模型观察者回调(以免污染我的控制器代码)?

导轨 5.1+

使用saved_change_to_published?

class SomeModel < ActiveRecord::Base
  after_update :send_notification_after_change

  def send_notification_after_change
    Notification.send(…) if (saved_change_to_published? && self.published == true)
  end

end

或者,如果您愿意,也可以使用saved_change_to_attribute?(:published)

导轨 3–5.1

警告

此方法适用于 Rails 5.1(但在 5.1 中已弃用,并在 5.2 中进行了重大更改)。 您可以阅读此拉取请求中的更改。

在模型上的after_update过滤器中,您可以使用_changed? 存取器。 例如:

class SomeModel < ActiveRecord::Base
  after_update :send_notification_after_change

  def send_notification_after_change
    Notification.send(...) if (self.published_changed? && self.published == true)
  end

end

它只是有效。

对于那些想知道刚刚在after_save回调中所做的更改的人:

Rails 5.1 及更高版本

model.saved_changes

导轨 < 5.1

model.previous_changes

另请参阅: http : //api.rubyonrails.org/classes/ActiveModel/Dirty.html#method-i-previous_changes

对于稍后看到这一点的任何人,因为它目前(2017 年 8 月)在 google 上名列前茅:值得一提的是,这种行为将在Rails 5.2 中改变,并且从 Rails 5.1 开始有弃用警告,因为ActiveModel::Dirty发生了一些变化.

我要改变什么?

如果您使用的是attribute_changed? after_*方法,您将看到如下警告:

弃用警告: attribute_changed?的行为attribute_changed? 在下一个版本的 Rails 中,after 回调的内部将发生变化。 新的返回值将反映save返回后调用方法的行为(例如,与现在返回的相反)。 要保持当前行为,请使用saved_change_to_attribute? 相反。 (从 /PATH_TO/app/models/user.rb:15 处的 some_callback 调用)

正如它所提到的,你可以通过用saved_change_to_attribute?替换函数来轻松解决这个saved_change_to_attribute? . 例如, name_changed? 变成saved_change_to_name? .

同样,如果您使用attribute_change来获取前后值,这也会发生变化并抛出以下内容:

弃用警告:在下一个版本的 Rails 中,after 回调中的attribute_change行为将发生变化。 新的返回值将反映save返回后调用方法的行为(例如,与现在返回的相反)。 要保持当前行为,请改用saved_change_to_attribute (从 /PATH_TO/app/models/user.rb:20 处的 some_callback 调用)

同样,正如它所提到的,该方法将名称更改为saved_change_to_attribute ,它返回["old", "new"] 或使用saved_changes ,它返回所有更改,这些可以作为saved_changes['attribute']

如果您可以在before_save而不是after_save上执行此操作,您将能够使用它:

self.changed

它返回此记录中所有更改列的数组。

您还可以使用:

self.changes

它以数组形式返回更改前后的列的哈希值

“选定”的答案对我不起作用。 我将 rails 3.1 与 CouchRest::Model (基于 Active Model)一起使用。 _ _changed? 方法不会为after_update挂钩中更改的属性返回 true,仅在before_update挂钩中。 我能够使用(新的?) around_update钩子让它工作:

class SomeModel < ActiveRecord::Base
  around_update :send_notification_after_change

  def send_notification_after_change
    should_send_it = self.published_changed? && self.published == true

    yield

    Notification.send(...) if should_send_it
  end

end

您可以像这样向after_update添加条件:

class SomeModel < ActiveRecord::Base
  after_update :send_notification, if: :published_changed?

  ...
end

无需在send_notification方法本身中添加条件。

我正在使用它来提取具有新属性值的哈希,这对我更新其他模型很有用

attributes_changed = self.changes.inject(Hash.new){|hash,attr| ((hash[attr[0].to_sym] = attr[1].last) || attr[1].last == false) && hash}

attr[1].last == false

当new值为false时需要使用,其中赋值返回false且不返回“哈希”。

我想有一种更简单的方法,我是Rails的新手

您只需添加一个访问者来定义您更改的内容

class Post < AR::Base
  attr_reader :what_changed

  before_filter :what_changed?

  def what_changed?
    @what_changed = changes || []
  end

  after_filter :action_on_changes

  def action_on_changes
    @what_changed.each do |change|
      p change
    end
  end
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM