Rails 3 check if attribute changed
在Rails 3中更新之前,需要检查属性块是否已更改。
street1,street2,city,state,zipcode
我知道我可以使用类似的东西
1 2 3 | if @user.street1 != params[:user][:street1] then do something.... end |
但这段代码真的很长。 有更干净的方式吗?
查看ActiveModel :: Dirty(默认情况下适用于所有型号)。文档非常好,但它可以让您执行以下操作:
1 | @user.street1_changed? # => true/false |
这就是我如何解决检查多个属性中的更改的问题。
1 2 3 4 5 | attrs = ["street1","street2","city","state","zipcode"] if (@user.changed & attrs).any? then do something.... end |
同样非常有用的是,
您可以检查APIDock支持这些方法的版本。
http://apidock.com/rails/ActiveModel/Dirty
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 |
如果你试图检测很多属性变化,它可能会变得混乱。可能不应该在控制器中这样做,但是meh。
对于rails 5.1+回调
改进这篇文章并完成其他答案
对于下一个rails版本(5.1之后)的回调,第一个答案将被弃用。
那么检查属性是否已更改的新方法是使用saved_change_to_attribute?
你可以做:
1 | @user.saved_change_to_street1? # => true/false |
您可以在此博客上看到更多示例
以上答案更好,但对于知识我们还有另一个approch,
让一个对象(@design)改变'catagory'列值,
1 | @design.changes.has_key?('catagory') |
.changes将返回一个哈希,其中key作为列的名称,值返回为一个数组,每列有两个值[old_value,new_value]。例如,上面的catagory从@design的'ABC'变为'XYZ',
1 2 3 | @design.changes # => {} @design.catagory = 'XYZ' @design.changes # => { 'catagory' => ['ABC', 'XYZ'] } |
对于ROR中的参考变化