2014-06-16 48 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?'從哪裏來? –

相關問題