在Rails 3中更新之前,需要检查属性块是否已更改。
street1,street2,city,state,zipcode
我知道我可以使用像
这样的东西if @user.street1 != params[:user][:street1]
then do something....
end
但那段代码真的很长。有更清洁的方式吗?
答案 0 :(得分:271)
查看ActiveModel::Dirty(默认情况下适用于所有型号)。文档非常好,但它允许您执行以下操作:
@user.street1_changed? # => true/false
答案 1 :(得分:53)
这就是我解决检查多个属性更改的问题。
attrs = ["street1", "street2", "city", "state", "zipcode"]
if (@user.changed & attrs).any?
then do something....
end
changed
方法返回为该对象更改的属性数组。
@user.changed
和attrs
都是数组,因此我可以获得交集(请参阅ary & other ary
方法)。交集的结果是一个数组。通过调用数组上的any?
,如果至少有一个交集,我就会得到。
同样非常有用,changed_attributes
方法返回属性的哈希值及其原始值,changes
返回属性的哈希值及其原始值和新值(在数组中)。 / p>
您可以查看APIDock支持这些方法的版本。
答案 2 :(得分: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
如果您尝试检测很多属性更改,它可能会变得混乱。可能不应该在控制器中这样做,但是meh。
答案 3 :(得分:4)
用于Rails 5.1+回调
要改善此信息并完成其他答案
对于下一个Rails版本(5.1之后)的回调,不建议使用第一个答案。
因此,检查属性是否已更改的新方法是使用saved_change_to_attribute?
您可以这样做:
@user.saved_change_to_street1? # => true/false
您可以看到更多示例here at this post blog
答案 4 :(得分:2)
以上答案更好但是对于知识我们还有另一个方法, Lets&#39; catagory&#39;对象(@design),
的列值已更改@design.changes.has_key?('catagory')
.changes将返回一个带有键的哈希作为列的名称和值作为一个数组,每列有两个值[old_value,new_value]。例如,上面的类别更改为&#39; ABC&#39;到&#39; XYZ&#39; of @design,
@design.changes # => {}
@design.catagory = 'XYZ'
@design.changes # => { 'catagory' => ['ABC', 'XYZ'] }