2011-10-19 67 views
2

我有一個表單被提交給包含許多關聯的複雜模型。我需要保存2個對象的副本。一個不會被觸及,僅用於參考最初提交的內容,另一個將由我的用戶編輯。序列化包括關聯的Rails ActiveRecord對象

我最初預先形成了對象和所有關聯的深層克隆,然後將它們都保存到數據庫中,標記了原始字段以及可以編輯的字段。然而,這太複雜了,我想要一個更簡單的解決方案

我在想我最好的選擇是序列化整個對象並將其存儲在可編輯對象的單個字段中。所以我的問題是:是否有可能序列化一個對象,包括關聯,並將其存儲在單個字段中?

我應該在模型層面做到這一點?或者我應該保存從單個字段返回的表單? (即application.original_form = params [:application])。

感謝您的幫助! 瑞安

編輯---

我在嘗試這種方法:

https://gist.github.com/1298567

我保存在一個連載場返回的參數。

有沒有人看到這樣的倒臺?這似乎是最簡單的方法。再次

謝謝!

Ryan

回答

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(原項目)

看看其他的Ryan的RailsCasts:

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

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

希望這有助於


編輯:

退一步講,限制你的數據庫/數據庫的大小轉儲,簡化你的架構和安全,保留了原圖,你可能想將原件存儲在單獨的文檔存儲中,例如你可以使用MongoDB。

如果你並不需要經常訪問的原件,然後在MongoDB中存儲這是一個結構化文檔可能是真的benefical,它會保持你的主應用程序少令人費解。

當您比較記錄時,您會像第一次那樣深度複製修改後的模型,然後通過原始記錄的「id」字段查找MongoDB記錄,然後比較兩者(兩者都很深克隆)。該解決方案的

額外的好處:它會使其難以accidentially修改原來的,因爲它沒有直接連接到SQL數據庫記錄。例如你不能意外做object.original = something

0

我還沒試過它,但它打賭它聽起來超級令人毛骨悚然! 您應該使用實例科朗和參考他們這樣的:

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。在我的情況下,用戶不會真的編輯除了原始的「模板」對象,所以沒有真正的理由來重新實例化對象圖。

但我對他人的解決方案感興趣。

是否有可能發佈要點?我可以給出更詳細的反饋。

相關問題