Techioz Blog

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 を検討することをお勧めします (ニーズに合わない場合は、他にもたくさんあると思います)。これは、履歴を保存する際の多くの問題と機能をすでに検討しています。記録が変わった。