Ruby-on-rails Rails 3 检查属性是否更改
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5051135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails 3 check if attribute changed
提问by pcasa
Need to check if a block of attributes has changed before update in Rails 3.
在 Rails 3 中更新之前需要检查属性块是否已更改。
street1, street2, city, state, zipcode
街道 1、街道 2、城市、州、邮政编码
I know I could use something like
我知道我可以使用类似的东西
if @user.street1 != params[:user][:street1]
then do something....
end
But that piece of code will be REALLY long. Is there a cleaner way?
但是那段代码真的很长。有更干净的方法吗?
回答by Peter Brown
Check out ActiveModel::Dirty(available on all models by default). The documentation is really good, but it lets you do things such as:
查看ActiveModel::Dirty(默认适用于所有型号)。该文档非常好,但它可以让您执行以下操作:
@user.street1_changed? # => true/false
回答by campeterson
This is how I solved the problem of checking for changes in multiple attributes.
这就是我如何解决检查多个属性变化的问题。
attrs = ["street1", "street2", "city", "state", "zipcode"]
if (@user.changed & attrs).any?
then do something....
end
The changedmethod returns an array of the attributes changed for that object.
该changed方法返回为该对象更改的属性的数组。
Both @user.changedand attrsare arrays so I can get the intersection (see ary & other arymethod). The result of the intersection is an array. By calling any?on the array, I get true if there is at least one intersection.
两个@user.changed和attrs是数组因此可以得到的交叉点(参见ary & other ary方法)。交集的结果是一个数组。通过调用any?数组,如果至少有一个交集,我就会得到 true。
Also very useful, the changed_attributesmethod returns a hash of the attributes with their original values and the changesreturns a hash of the attributes with their original and new values (in an array).
同样非常有用的是,该changed_attributes方法返回属性及其原始值changes的散列,并返回属性及其原始值和新值的散列(在数组中)。
You can check APIDock for which versions supported these methods.
您可以检查 APIDock 以了解哪些版本支持这些方法。
回答by hamstar
ActiveModel::Dirtydidn't work for me because the @model.update_attributes()hid the changes. So this is how I detected changes it in an updatemethod in a controller:
ActiveModel::Dirty对我不起作用,因为@model.update_attributes()隐藏了更改。所以这就是我update在控制器中的方法中检测到更改它的方式:
def update
@model = Model.find(params[:id])
detect_changes
if @model.update_attributes(params[:model])
do_stuff if attr_changed?
end
end
private
def detect_changes
@changed = []
@changed << :attr if @model.attr != params[:model][:attr]
end
def attr_changed?
@changed.include :attr
end
If you're trying to detect a lot of attribute changes it could get messy though. Probably shouldn't do this in a controller, but meh.
如果您试图检测大量属性更改,它可能会变得混乱。可能不应该在控制器中执行此操作,但是嗯。
回答by Lucas Andrade
For rails 5.1+ callbacks
对于 Rails 5.1+ 回调
As of Ruby on Rails 5.1, the attribute_changed?and attribute_wasActiveRecord methods will be deprecated
从 Ruby on Rails 5.1 开始,不推荐使用theattribute_changed?和attribute_wasActiveRecord 方法
Use saved_change_to_attribute?instead of attribute_changed?
使用saved_change_to_attribute?代替attribute_changed?
@user.saved_change_to_street1? # => true/false
More examples here
更多例子在这里
回答by shubham mishra
Above answers are better but yet for knowledge we have another approch as well, Lets 'catagory' column value changed for an object (@design),
上面的答案更好,但对于知识,我们还有另一种方法,让“类别”列值更改为对象(@design),
@design.changes.has_key?('catagory')
The .changes will return a hash with key as column's name and values as a array with two values [old_value, new_value] for each columns. For example catagory for above is changed from 'ABC' to 'XYZ' of @design,
.changes 将返回一个散列,键作为列的名称,值作为一个数组,每个列有两个值 [old_value, new_value]。例如上面的类别从@design的“ABC”更改为“XYZ”,
@design.changes # => {}
@design.catagory = 'XYZ'
@design.changes # => { 'catagory' => ['ABC', 'XYZ'] }
For references change in ROR

