2011-10-19 8 views
2

多くのアソシエーションを含む複雑なモデルに対してフォームを提出しました。私はオブジェクトの2つのコピーを保存する必要があります。 1つは触れられず、最初に提出されたものの参照としてのみ使用され、もう1つはユーザーによって編集されます。Railsのシリアライゼーションアソシエーションを含むActiveRecordオブジェクト

元々、オブジェクトとすべての関連付けのディープクローンを作成し、両方をデータベースに保存し、元のフィールドをマークし、編集可能にしました。しかし、これは複雑すぎるので、私はもっと簡単な解決策を望んでいます。

私は、オブジェクト全体をシリアル化して編集可能オブジェクト内の単一フィールドに格納することをお勧めしました。だから私の質問です:関連付けを含むオブジェクトをシリアル化し、単一のフィールドに格納することは可能ですか?

モデルレベルでこれを行う必要がありますか?フォームから返されたものを1つのフィールドに保存するだけですか? (つまり、application.original_form = params [:application])。

ありがとうございました! ライアン

EDIT ---

私はこのアプローチを試みています:

https://gist.github.com/1298567

私は直列化フィールドに返されたパラメータを保存しています。

これで誰かが没落していますか?それは最も簡単なアプローチのようです。

もう一度おねがいします!

ライアン

答えて

1

私はこのアプローチを行ってきた:

def create 
    @app = App.new(params[:app]) 
    @app.original = params[:app] 
    respond_to do |format| 
     if @app.save 
     format.html { redirect_to(done_path(@app.member.id)) } 
     else 
     format.html { render :action => "new" } 
     end 
    end 
end 

#show the original Application 
def show 
    @app = App.new(App.find(params[:id]).original) 
end 

#Model 

class App < ActiveRecord::Base 
    has_one :applicant 

    serialize :original, Hash 

    accepts_nested_attributes_for :applicant 
end 

私にとって、これは問題に最も簡単な方法のように思えます。

1

私は一つだけレベルの深い団体と、前に似た何かをやりました。例えば。あなたは、関連する他のモデルのあなたの団体はかなり単純であることを確認しなければならない一または-多くのアドレス、連絡先、など。

を持っていたアカウントなので、そこにはループがありませんまたはバックポインタ

にですモデルの現在のバージョンと後で比較するのが簡単な方法で保存することをお勧めします。

モデルの最初の保存時に、モデルのクローンを作成して関連付けを行い、シリアライズされたフィールドに保存しますメインモデルでは「オリジナル」です。

私は例えば、私はActiveRecordののserialize機能を使用したいと思います。:

Class YourMainModel 
    ... 
    serialize :original # will serialize this ; make this TEXT field in DB 
    ... 
end 

あなたは、データベース内のフィールドのデータ型がテキストまたは文字列ではなく、バイナリフィールドであることを確認するには! (それは後にバグを引き起こす!)そして、

をモデルのafter_saveの間に、私はこのような何かを行うにはいくつかのコードを追加します。

# do this in the after_save - so the validations have run: 
main_model_object.original ||= main_model_object.deep_clone # ||= to do this only once 
main_model_object.save(:validate => false) if main_model_object.original_changed? # save if we added the "copy" 

これをフックするために、おそらく他の方法がありますが、after_saveあり検証が実行される利点。

最初に保存した時点までに関連するすべてのレコードが作成されていることを確認する必要があります。おそらく、nested_forms Gemを使用して「モンスターフォーム」を実行することをお勧めします。

参照:

https://github.com/moiristo/deep_cloneable(Railsのためのフォーク3)

https://github.com/openminds/deep_cloning(元のプロジェクト)

チェックアウト他のライアンのRailsCasts:

http://railscasts.com/episodes/196-nested-model-form-part-1

http://railscasts.com/episodes/197-nested-model-form-part-2

これは


EDIT役立ちます

希望:データベース/データベースのサイズを制限するために、第二思想に

があなたのスキーマを簡単にするために、ダンプ、とにオリジナルを安全に保つ、あなたが望むかもしれませんオリジナルを別のドキュメントストアに保存するそのためにMongoDBを使うことができます。

オリジナルに頻繁にアクセスする必要がない場合は、構造化文書としてMongoDBに格納することは本当に有益であり、メインアプリケーションの複雑さを軽減します。

レコードを比較すると、最初に行ったのと同じ方法で修正したモデルをdeep_cloneし、元のレコードの 'id'フィールドでMongoDBレコードを検索してから2つを比較しますクローン)。

このソリューションの利点:SQLデータベースレコードに直接添付されていないため、誤って元のデータを変更するのが難しくなります。例えばあなたは偶然にすることができなかったobject.original = something

0

私はhaventそれをまだ試してみましたが、それは超気味悪いね! あなたは、インスタンスのcolonesを使用して、このようにそれらを参照する必要があります。

belongs_to :original_version, :class_name => 'ModelName', :foreign_key => 'original_version_id' 
has_one :original_version, :class_name => 'ModelName', :foreign_key => 'original_version_id' 
belongs_to :user_version, :class_name => 'ModelName', :foreign_key => 'user_version_id' 
has_one :user_version, :class_name => 'ModelName', :foreign_key => 'user_version_id' 

そして、はい、あなたはすべて同じモデルで、その後、あなたはインスタンスがあり、これらのバージョンのどの確認するためにいくつかのメソッドを書くことを置きます。

+0

なぜすべてのリレーションシップをコピーしたいですか? – Tilo

0

私は同じようなことをしばらくやり直さなければなりませんでした。そして、これらの質問に何度も何度も行きました。私は最終的に編集可能なオブジェクトグラフを直列化して保存したが、XMLとして保存したと思う。私の場合、ユーザは元の「テンプレート」オブジェクトを除いて実際には編集しないので、オブジェクトグラフを再インスタンス化する本当の理由はありませんでした。

しかし、私は他人のソリューションに興味があります。

要点を投稿することはできますか?私は多分より詳細なフィードバックを与えることができます。

関連する問題