[英]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
有没有人对处理这个问题的最佳方法有任何建议,最好使用模型观察者回调(以免污染我的控制器代码)?
使用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)
。
警告
此方法适用于 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
回调中所做的更改的人:
model.saved_changes
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.