Rails 3检查属性是否已更改

时间:2011-02-19 13:54:57

标签: ruby-on-rails ruby-on-rails-3

在Rails 3中更新之前,需要检查属性块是否已更改。

street1,street2,city,state,zipcode

我知道我可以使用像

这样的东西
if @user.street1 != params[:user][:street1]
  then do something....
end

但那段代码真的很长。有更清洁的方式吗?

5 个答案:

答案 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.changedattrs都是数组,因此我可以获得交集(请参阅ary & other ary方法)。交集的结果是一个数组。通过调用数组上的any?,如果至少有一个交集,我就会得到。

同样非常有用,changed_attributes方法返回属性的哈希值及其原始值,changes返回属性的哈希值及其原始值和新值(在数组中)。 / p>

您可以查看APIDock支持这些方法的版本。

http://apidock.com/rails/ActiveModel/Dirty

答案 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'] }

参考change in ROR