2010-02-01 69 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