确定Rails after_savecallback中哪些属性发生了变化?
我在模型观察者中设置after_savecallback,只有当模型的发布属性从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
有没有人有任何build议,以最好的方式来处理,最好使用模型观察callback(以免污染我的控制器代码)?
在模型的after_update
filter中,您可以使用_changed?
accessor(至less在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
它只是工作。
对于那些想知道保存后的变化,你应该使用
model.previous_changes
这工作像model.change
但它仍然工作model.save
等。我觉得这个信息很有用,所以也许你也会。
在Rails 5.1+中已经弃用了。 saved_changes
在after_save
callback中使用saved_changes
。
如果你可以在before_save
而不是after_save
上做到这一点,你可以使用这个:
self.changed
它将返回此logging中所有已更改列的数组。
你也可以使用:
self.changes
它返回一个散列的变化,并在结果之前和之后作为数组
对任何人来说,今天(2017年8月)tops谷歌:值得一提的是,这种行为将被改变在Rails 5.2 ,并有Rails 5.1的弃用警告,因为ActiveModel ::脏改变了一点。
我该怎么改变?
如果你使用的是attribute_changed?
方法在after_*
,你会看到一个警告,如:
拒绝警告:
attribute_changed?
的行为attribute_changed?
在Rails的下一个版本中,后面的callback里面将会改变。 新的返回值将反映save
返回后调用方法的行为(例如与现在返回的相反)。 要保持当前行为,请使用saved_change_to_attribute?
代替。 (在/PATH_TO/app/models/user.rb:15从some_callback调用)
正如它提到的,你可以通过用saved_change_to_attribute?
replace函数来修复这个saved_change_to_attribute?
。 那么例如, name_changed?
变成saved_change_to_name?
。
同样,如果您使用attribute_change
来获取之前的值,这也会改变,并引发以下内容:
DEPRECATION警告:在callback之后的
attribute_change
行为在下一个版本的Rails中将会改变。 新的返回值将反映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']
被访问。
“选定”的答案不适合我。 我使用CouchRest :: Model(基于Active Model)的rails 3.1。 _changed?
方法不会在after_update
挂钩中对已更改的属性返回true,而只会在before_update
挂钩中返回true。 我能够得到它使用(新?) 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
我正在使用这个来提取一个新的属性值的哈希值,这对我来说更新其他模型是有用的
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”。
我想有一个更简单的方法,我是新来的铁轨
你可以添加一个条件到after_update
像这样:
class SomeModel < ActiveRecord::Base after_update :send_notification, if: :published_changed? ... end
send_notification
方法本身不需要添加条件。
您只需添加一个定义您所做更改的访问者
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