2010-02-01 67 views
6

我有一個表單,允許我將不同格式的文件添加到流中。所以,一個流由許多文件組成,這些文件是XML文件,但基本上有不同的模式。我有一種允許用戶添加他們想要的任何文件的形式,我使用的是STI(當數據已經在表格中時工作良好),我的麻煩是將數據添加到表格中。使用一種形式的軌道STI

表單有1個輸入欄,只是一個file_field,允許用戶選擇他們想要上傳的文件。由於我只有一種形式,我無法實例化正確的對象,所以我必須以編程方式執行此操作..我不確定如何執行此操作。

我只是(或者我可以)添加一個可能的類型下拉列表,並調用該字段'type',以便當提交表單時,rails會實例化對象的寫入類型,因爲提供了type屬性?

這是什麼最佳做法..我正在運行rails 2.3.4。

回答

3

我找到了解決辦法,在http://coderrr.wordpress.com/2008/04/22/building-the-right-class-with-sti-in-rails/#comment-1826

class GenericClass < ActiveRecord::Base 
    class << self 
    def new_with_cast(*a, &b) 
     if (h = a.first).is_a? Hash and (type = h[:type] || h['type']) and (klass = type.constantize) != self 
     raise "wtF hax!!" unless klass < self # klass should be a descendant of us 
     return klass.new(*a, &b) 
     end 

     new_without_cast(*a, &b) 
    end 
    alias_method_chain :new, :cast 
    end 
end 

這對我來說很好,只需要最少的代碼 - 我不知道它是否存在危險,但它的工作原理,而且很乾淨。我喜歡它只有10行代碼的事實。

+1

加1表示「wtF hax !!」 – tybro0103 2011-02-07 22:02:53

0

我不知道你有多少種類型,但我過去只是使用不同類型的控制器和視圖。這樣你就不會創建基類的新對象並嘗試設置類型,只需使用從基類繼承的模型即可。您資源的每個新/編輯頁面都可以在form_for塊中呈現共享的部分。該部分將包含你的file_field。

這種方式當表單被提交時,它會去正確的控制器,調用正確的resource.new,一切正常。

當然缺點是更多的文件和任何頁面,你鏈接到「添加新文件」,你需要添加多個鏈接,如「添加新的這種類型的文件」,「添加新的文件類型」等

至於設置表單中的類型,我不確定這是否有效,我懷疑它,但只是試一試(讓我們知道)。你可以讓這個類型下拉一個select_tag,當改變時使用Javascript來改變表單上的動作位置。

編輯和添加周圍

不是基礎性的工作,我喜歡這個解決方案&我懷疑它絕不是最好的,但如果你真的不想要獨立的控制器,你需要得到它的工作你可以做這樣的事情:

class XmlFile < ActiveRecord::Base 
end 

class XmlFileTypeA < XmlFile 
end 

class XmlFileTypeB < XmlFile 
end 

def create 
    # Leaving this case statement in the controller for simplicity but you probably want to move this to the model 
    case params[:chosen_xml_type] 
     when "file_type_a" 
     @item = XmlFileTypeA.new(params) 
     when "file_type_b" 
     @item = XmlFileTypeB.new(params) 
     else 
     raise "Unknown file type!" 
     etc 
    end 
end 
+0

是的,我真的想避免爲每個控制器創建一個單獨的控制器,即使目前我只有兩種文檔類型,它可能會更快 - 更快。 Rails使得它看起來很容易實現STI ..它是 - 但只是檢索信息,我甚至找不到STI實現的「新」形式的示例。 – Rabbott 2010-02-01 16:04:44

+0

查看我編輯的帖子,呈現視圖的新動作會創建@xml_file = XmlFile.new,創建動作會根據用戶的選擇爲您創建正確的文件類型。希望這是清晰的泥!? – tsdbrown 2010-02-01 16:22:51

+0

這更接近了,感謝您的更新! 既然控制器是實際實例化對象的東西,它不會停留在那裏嗎? 我認爲,畢竟這個研究,我正在尋找的是你可以調用classify.constanize.new或類似的東西..任何想法我在說什麼的方法。你可以從下拉菜單中使用該值,並創建該類型的對象。 – Rabbott 2010-02-01 17:15:50