2017-07-05 40 views
0

我有一個網頁跟蹤包含大量變量的預算,存儲在40列以上。隨着時間的推移,對這些預算進行了調整,但我需要能夠跟蹤隨着時間和年復一年的變化。我嘗試在我的模型中添加一個私有方法,該方法應該創建觸發的現有記錄的副本:before_update回調。但是,它不起作用。該更新更改了現有記錄,並且根本不保留原始記錄。Rails - 如何保存現有記錄並將更新應用於副本?

型號:

class Budget < ActiveRecord::Base 

    before_update :copy_budget 

    private 

    def copy_budget 
    @budget = Budget.find(params[:id]) 
    @budget.dup 
    @budget.save 
    end 
end 

我還在學習軌道,(這是Rails中4),我認爲這將是做到這一點的最好辦法。如果不是,如果記錄已經存在,是否有更好的方式將表單設置爲始終發佈新記錄,而不是路由更新?

目前的form_for線看起來是這樣的:

<%= form_for(@budget) do |f| %>

一切正常,因爲它應該具有的複製沒有發生異常。我錯過了什麼?是否有可能.dup函數也複製:id?這是通過在MySQL數據庫中使用自動增量分配的,所以如果.dup正在複製一切,有沒有辦法將除id之外的所有數據複製到新記錄中?

在此先感謝您的任何建議。

+0

最好的辦法是使用一個爲審計更改而設計的庫,如['audited'](https://github.com/collectiveidea/audited)或['paper_trail'](https://github.com/ airblade/paper_trail),例如 – engineersmnky

回答

1

dup方法返回沒有id的新對象,它不會更新它。由於您的copy_budget方法已經是Budget上的一個實例方法,因此您也不需要(因爲params在模型中不可訪問,所以您甚至無法使用)通過id查找預算,而只需使用當前實例(自我)。所以下面的改變將修復copy_budget方法你,但你仍然複製已修改的對象,就在它被保存到數據庫

def copy_budget 
    copy_of_budget = self.dup 
    copy_of_budget.save 
end 

它的工作你希望它的工作方式。但是,您並未將副本鏈接到當前版本的Budget(無法告訴Budget ID = 1是Budget ID = 2的舊版本)。我建議看看一個像PaperTrail這樣的寶石(我敢肯定還有很多其他的,如果那個不適合你的需要的話),它已經考慮了很多問題和功能,保留了歷史記錄已更改。

+0

也可能觸及OP在'Budget'模型中定義'#copy_budget'的事實。 「params」無法訪問,「@ budget」可能只是「自我」。另外,'duping'當前對象並不表示'#changes',所以dup不會有'id'或時間戳,但會反映改變的對象(我相信)。 – engineersmnky

+0

簡單的石灰,我試着改變copy_budget方法來匹配你的建議,在我的模型中仍然沒有重複。現有記錄應用了更改,但未創建副本。 –

+0

你在什麼版本的導軌,你如何檢查它是否工作?剛剛在rails 5.1.2中創建了一個測試應用程序,無論我如何更新記錄,它都會爲我創建一個新的預算。雖然正如我的回答中所提到的,但除了id之外,兩條記錄都是相同的,因爲您正在複製一條記錄並對其進行了更改,所以您需要更新代碼以複製舊版本([更改]( HTTP:// API。rubyonrails.org/classes/ActiveModel/Dirty.html#method-i-changes)可能會幫助你。我仍然建議查看一些已經完成此操作的寶石 –

相關問題