2014-06-16 47 views
0

我有一个课程模型,用户可以使用表单进行编辑和更新。在控制器中,更新方法调用update_attributes(course_params),即强参数。这是所有标准,工作正常。update_attributes,然后检查其中一个属性是否已更改

现在我试图找出在更新过程中特定属性是否正在更改。特别是,如果用户正在更改课程对象的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

所以......我的直接问题是 - 这是什么变化点内的课程?你能告诉我们那个代码吗? –

+0

这是一个非常标准的形式。我会更新这个问题 - 一秒钟... –

+0

我想知道更多,如果有一种方法after_X钩或类似的方法,改变了课程上的点...并不保存它们..,。也许可以更新该方法以实际保存它们。 –

回答

0

更快,而不是(太)丑陋的方法可能会被改写update_attributes方法。这样,您就可以在控制器为您在您的课程控制器

if @courses.changes 

解决方法:可以使用after_validation回调

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

更新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?方法将返回为真或者基于点属性是否虚假更新或不是一个属性。

一个例子

[email protected]:~/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?将返回错误

+0

为什么写'只要做'obj.points_changed?'''p_changed?'? –

+0

感谢@AndrewMarshall的反馈我已经更新了答案。 – Monideep

+0

'points_changed?'从哪里来? –

相关问题