update_attributes,然后检查其中一个属性是否已更改

我有一个课程模型,用户可以使用表单进行编辑和更新。 在控制器中,update方法调用update_attributes(course_params) ,即强参数。 这都是标准的,工作正常。

现在我试图找出更新期间特定属性是否正在发生变化。 特别是,如果用户正在更改课程对象的points属性,我还需要将对象的points_recently_changed属性标记为true。 快速而肮脏的实现将是这样的:

 def update @course = Course.find(params[:id]) @old_points = @course.points @course.update_attributes(course_params) @new_points = @course.points if @old_points != @new_points @course.points_recently_changed = true @course.save end end 

一种稍微不那么糟糕的做法可能是:

 def update @course = Course.find(params[:id]) @course.points_recently_changed = true if @course.points != params[:course][:points] @course.update_attributes(course_params) end 

然而,这些都不能满足我对干净,高效和易于阅读的实现的渴望。 理想情况下,update_attributes可以选择返回在更新期间实际更改的属性数组。 但事实并非如此。

我查看了ActiveModel :: Dirty ,但问题是它只能在保存之前运行。 因为我正在使用更新保存的update_attributes,所以像has_changed?这样的方法has_changed? 在我的方案中不起作用。

任何建议,将不胜感激。 🙂

编辑:

这是管理员可以通过其更新课程对象的表单:

    

您可以使用after_validation回调来更新points_recently_changed属性。

 #course.rb after_validation :points_changed, if: ->(obj){ obj.points.present? and obj.points_changed? } def points_changed self.points_recently_changed = true end 

说明:

考虑points是你的Course模型中的一个属性points_changed? 方法将根据points属性是否更新返回true或false。

一个例子

 deep@IdeaPad:~/test/test_app$ rails c 2.1.1 :001 > course = Course.find(1) => # 2.1.1 :002 > course.changed? # will return true of false based on whether the course object has been updated or not => false 2.1.1 :003 > course.points = "11" => "11" 2.1.1 :004 > course.points_changed? => true 2.1.1 :005 > course.points_change => [2, 11] 

参考 – http://apidock.com/rails/ActiveRecord/Dirty

注意:您必须使用changed? 保存记录之前的方法。 一旦保存记录,呼叫changed? 将返回false

更快,而不是(太)丑陋的方法可能会重写update_attributes。 这样你就可以检查控制器了

 if @courses.changes 

课程控制器中的解决方案:

  def update_attributes(attributes) self.attributes = attributes changes = self.changes save self.changes = changes end