Rails - 既存のレコードを保存し、コピーに更新を適用する方法は?
概要
40 以上の列に保存された多くの変数を含む予算を追跡する Web ページがあります。時間の経過とともに、これらの予算は調整されますが、時間の経過と年ごとの変化を追跡できる必要があります。 :before_update コールバックによってトリガーされる既存のレコードの複製を作成するプライベート メソッドをモデルに追加してみました。しかし、うまくいきません。更新により既存のレコードが変更され、元のレコードはまったく保持されません。
モデル:
class Budget < ActiveRecord::Base
before_update :copy_budget
private
def copy_budget
@budget = Budget.find(params[:id])
@budget.dup
@budget.save
end
end
私はまだ Rails を学習中ですが (これは Rails 4 です)、これが最善の方法だったと思います。そうでない場合、レコードがすでに存在する場合に更新するようにルーティングするのではなく、常に新しいレコードを投稿するようにフォームを設定するより良い方法はありますか?
現在、form_for 行は次のようになります。
<%= form_for(@budget) は |f| を実行します%>
重複が発生しないことを除いて、すべてが正常に動作します。私には何が欠けているのでしょうか? .dup 関数が :id も複製している可能性はありますか?これは、私が使用している MySQL データベースの自動インクリメントによって割り当てられているため、.dup がすべてをコピーしている場合、:id を除くすべてのデータを新しいレコードにコピーする方法はありますか?
ご提案をいただきありがとうございます。
解決策
dup メソッドは ID なしで新しいオブジェクトを返し、その場で更新しません。 copy_budget メソッドはすでに Budget のインスタンス メソッドであるため、ID で予算を検索する必要はなく (モデル内でパラメータにアクセスできないため、検索することさえできません)、代わりに現在のインスタンス (自分自身)。したがって、次の変更により copy_budget メソッドが修正されますが、データベースに保存される直前に、すでに変更されたオブジェクトがまだコピーされています。
def copy_budget
copy_of_budget = self.dup
copy_of_budget.save
end
それはあなたが期待しているように機能するでしょう。ただし、コピーを現在のバージョンの予算にリンクしているわけではありません (予算 ID = 1 が予算 ID = 2 の古いバージョンであるかどうかを判断する方法はありません)。 PaperTrail などの gem を検討することをお勧めします (ニーズに合わない場合は、他にもたくさんあると思います)。これは、履歴を保存する際の多くの問題と機能をすでに検討しています。記録が変わった。