update_attributes,然后检查属性之一是否已更改 [英] update_attributes, and then check if one of the attributes has changed
问题描述
我有一个课程模型,用户可以使用表单对其进行编辑和更新.在控制器中,更新方法调用update_attributes(course_params)
,即强参数.这一切都是标准的,并且工作正常.
I have a Course model that users can edit and update using a form. In the controller, the update method calls update_attributes(course_params)
, i.e. strong parameters. This is all standard and is working fine.
现在我试图找出更新期间特定属性是否发生变化.特别是,如果用户正在更改课程对象的 points
属性,我还需要将对象的 points_recently_changed
属性标记为 true.快速而肮脏的实现将是这样的:
Now I'm trying to find out if a specific attribute is changing during the update. In particular, if the course object's points
attribute is being changed by the user, I also need to mark the object's points_recently_changed
attribute to true. The quick-and-dirty implementation would be like this:
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
一种稍微不那么可怕的做法可能是:
A slightly less terrible way of doing it could be:
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 可以选择返回更新期间实际更改的属性数组.但它没有.
However, neither of these satisfy my desire for a clean, efficient, and easy-to-read implementation. Ideally, update_attributes would optionally return an array of attributes that have actually changed during the update. But it doesn't.
我查看了 ActiveModel::Dirty,但问题是它只在保存前有效.由于我使用的是 update_attributes,它更新和保存,诸如 has_changed?
之类的方法在我的场景中不起作用.
I looked at ActiveModel::Dirty, but the problem with that is it only works before save. And since I'm using update_attributes, which updates and saves, methods such as has_changed?
would not work in my scenario.
任何建议将不胜感激.:)
Any suggestions would be appreciated. :)
管理员可以通过以下表单更新课程对象:
Here's the form through which admins can update the course object:
<%= 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 %>
推荐答案
您可以使用 after_validation
回调来更新 points_recently_changed
属性.
You can use after_validation
callback to update points_recently_changed
attribute.
#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不是.
considering points
is a attribute in your Course
model points_changed?
method will return true or false based on whether the points attribute is updated or not .
一个例子
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
Note: You have to use changed?
method before saving the record. Once the record is saved calling changed?
will return false
这篇关于update_attributes,然后检查属性之一是否已更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!