我正在我的模型观察器中设置一个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
有没有人对处理这个问题的最佳方法有任何建议,最好使用模型观察者回调(以免污染我的控制器代码)?
在模型的after_update
过滤器中,您可以使用_changed?
访问器(至少在Rails 3中,对Rails 2不确定)。例如:
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
如果您可以在before_save
而不是after_save
上执行此操作,您将能够使用此:
self.changed
它返回此记录中所有已更改列的数组。
你也可以用:
self.changes
它返回一个已更改的列的散列,以及作为数组的结果之前和之后
对于后来看到这个的人,因为它目前(2017年8月)是谷歌的顶级:值得一提的是,这种行为将在Rails 5.2中改变,并且在Rails 5.1中有弃用警告,因为ActiveModel::Dirty有所改变。
我该怎么改变?
如果你在attribute_changed?
-callbacks中使用after_*
方法,你会看到如下警告:
弃用警告:回调之后
attribute_changed?
的行为将在下一版本的Rails中发生变化。新的返回值将反映在save
返回后调用方法的行为(例如,它现在返回的相反)。要保持当前行为,请改用saved_change_to_attribute?
。 (在/PATH_TO/app/models/user.rb:15从some_callback调用)
正如它提到的那样,你可以通过用saved_change_to_attribute?
替换函数来轻松解决这个问题。因此,例如,name_changed?
成为saved_change_to_name?
。
同样,如果您使用attribute_change
获取之前的值,这也会发生变化并抛出以下内容:
弃用警告:回调之后
attribute_change
的行为将在下一版本的Rails中发生变化。新的返回值将反映在save
返回后调用方法的行为(例如,它现在返回的相反)。要保持当前行为,请改用saved_change_to_attribute
。 (来自some_callback at /PATH_TO/app/models/user.rb:20)
同样,正如它所提到的,该方法将名称更改为saved_change_to_attribute
,它返回["old", "new"]
。或使用saved_changes
,它返回所有更改,这些可以作为saved_changes['attribute']
访问。
“选定的”答案对我不起作用。我正在使用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
当新值为false
时需要,其中赋值返回false并且不返回“hash”。
我想有一种更简单的方法,我是铁杆新手
您只需添加一个定义您更改内容的访问者
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