我有一个表单,允许我将不同格式的文件添加到流中。因此,流由许多文件组成,这些文件是XML文件,但基本上有不同的模式。我有一个表单,允许用户添加他们想要的任何文件,我正在使用STI(当数据已经在表中时效果很好),我的麻烦是将数据添加到表中。
表单有1个输入字段,只有一个file_field,允许用户选择要上传的文件。由于我只有一个表单,我无法实例化正确的对象,我必须以编程方式进行...而且我不知道该怎么做。
我只是(或者我可以)添加可能类型的下拉列表,并调用该字段'type',以便在提交表单时,rails将实例化对象的写入类型,因为提供了type属性?< / p>
最佳做法是什么..我正在运行rails 2.3.4。
答案 0 :(得分: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
对于我来说,使用最少的代码对我来说非常有用 - 我不知道它的hackish与否,但是它有效,并且相当干净。我喜欢它只有10行代码的事实。
答案 1 :(得分:0)
我不知道你有多少种类型,但我过去只使用过不同类型的独立控制器和视图。这样您就不会创建基类的新对象并尝试设置类型,您只需使用从基类继承的模型。资源的每个新/编辑页面都可以在form_for块中呈现共享部分。部分将包含您的file_field。
这样当提交表单时,它将转到正确的控制器,调用正确的resource.new,一切正常。
缺点当然是更多的文件和你链接到“添加新文件”的任何页面,你需要添加多个链接,如“添加新的这种类型的文件”,“添加新的那种类型的文件”等< / p>
至于在表单中设置类型我不确定它是否有效,我对此表示怀疑,但试试看(让我们知道)。您可以将该类型下拉为select_tag,并在更改时使用Javascript更改表单上的操作位置。
编辑并添加了基本工作
不是我喜欢这个解决方案&amp;我怀疑它绝不是最好的,但是如果你真的不想要单独的控制器并且你需要让它工作,你可以做这样的事情:
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