我有一个课程模型,用户可以使用表单进行编辑和更新。在控制器中,更新方法调用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?
等方法在我的方案中不起作用。
任何建议将不胜感激。 :)
修改
这是管理员可以通过其更新课程对象的表单:
<%= form_for(@course) do |f| %>
<%= f.label :title %>
<%= f.text_field :title, required: true %>
<%= f.label :course_logo %><br />
<%= f.file_field :course_logo %>
<%= f.label :description %>
<%= f.text_field :description, required: true %>
<%= f.label :worth, "Points" %>
<%= f.number_field :worth %>
<%= f.label :tag_ids, "Tags" %>
<%= f.text_field :tag_ids, data: { load: @course.tags } %>
<%= f.label :content %>
<%= f.cktext_area(:content, rows: 10) %>
<%= f.submit "Save changes", class: "btn btn-large btn-primary" %>
<% end %>
答案 0 :(得分:1)
您可以使用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?
方法中的属性,将根据点属性是否更新返回true或false。
一个例子
deep@IdeaPad:~/test/test_app$ rails c
2.1.1 :001 > course = Course.find(1)
=> #<Course id: 1, name: "Ruby on Rails", points: 2, points_recently_changed: true, created_at: "2014-06-16 01:51:48", updated_at: "2014-06-16 01:58:07">
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
答案 1 :(得分:0)
更快,而不是(太)丑陋的方法可能会重写update_attributes。这样您就可以在控制器中检查
if @courses.changes
课程控制器中的解决方案:
def update_attributes(attributes)
self.attributes = attributes
changes = self.changes
save
self.changes = changes
end