pca*_*asa 149 ruby-on-rails ruby-on-rails-3
在Rails 3中更新之前,需要检查属性块是否已更改.
street1,street2,city,state,zipcode
我知道我可以使用类似的东西
if @user.street1 != params[:user][:street1]
then do something....
end
Run Code Online (Sandbox Code Playgroud)
但这段代码真的很长.有更干净的方式吗?
Pet*_*own 275
查看ActiveModel :: Dirty(默认情况下适用于所有型号).文档非常好,但它可以让您执行以下操作:
@user.street1_changed? # => true/false
Run Code Online (Sandbox Code Playgroud)
cam*_*son 54
这就是我如何解决检查多个属性中的更改的问题.
attrs = ["street1", "street2", "city", "state", "zipcode"]
if (@user.changed & attrs).any?
then do something....
end
Run Code Online (Sandbox Code Playgroud)
该changed方法返回为该对象更改的属性数组.
两个@user.changed和attrs是数组因此可以得到的交叉点(参见ary & other ary方法).交集的结果是一个数组.通过调用any?数组,如果至少有一个交集,我就会得到.
同样非常有用的changed_attributes方法是,该方法返回属性的散列及其原始值,并changes返回属性的散列及其原始值和新值(在数组中).
您可以检查APIDock支持这些方法的版本.
http://apidock.com/rails/ActiveModel/Dirty
ham*_*tar 14
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
Run Code Online (Sandbox Code Playgroud)
如果你试图检测很多属性变化,它可能会变得混乱.可能不应该在控制器中这样做,但是meh.
对于Rails 5.1+回调
为了改善这篇文章并完成其他答案
对于下一个Rails版本(5.1之后)的回调,不建议使用第一个答案。
因此,检查属性是否已更改的新方法是使用save_change_to_attribute?
你可以做:
@user.saved_change_to_street1? # => true/false
Run Code Online (Sandbox Code Playgroud)
您可以在此博文中查看更多示例