6

さまざまな形式のファイルをストリームに追加できるフォームがあります。したがって、ストリームは多くのファイルで構成されています。これらのファイルは XML ファイルですが、基本的に異なるスキーマを持っています。ユーザーが必要なファイルを追加できるフォームが 1 つあります。STI を使用しています (データが既にテーブルにある場合にうまく機能します)。問題はテーブルにデータを追加することです。

フォームには 1 つの入力フィールドがあり、ユーザーがアップロードするファイルを選択できるようにする file_field だけです。正しいオブジェクトをインスタンス化できないフォームが 1 つしかないため、プログラムで実行する必要があります。その方法がわかりません。

type属性が提供されているため、フォームが送信されたときにレールがオブジェクトの書き込みタイプをインスタンス化するように、可能なタイプのドロップダウンを追加し、そのフィールドを「タイプ」と呼ぶだけですか?

これのベストプラクティスは何ですか..レール2.3.4を実行しています。

4

2 に答える 2

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 行のコードであるという事実が気に入りました。

于 2010-02-03T18:51:01.177 に答える
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
于 2010-02-01T15:56:01.760 に答える