Railsの複数/クラステーブル継承

クライアント、マネージャー、ユーザーなど、いくつかのモデル(名前、電子メール、位置など)が同じである場合、多くの人が問題に直面します。 さらに、各モデルには固有のフィールドとメソッドもあります。 この場合(抽象的に論じる)、共通のフィールドを対応する検証とともに別のテーブルpeople(Personモデル)に配置し、Client、Manager、およびUserに特定のもののみを残すことは論理的です。



いくつかの例を続けることができます。製品-冷蔵庫、電話、トースター。 車両-車、トラック、オートバイなど。 問題はかなり一般的です-Railsのソリューションオプションは何ですか?



オプション



単一テーブル継承(STI)


これについては、特にRails GuidesとHabréのこちらこちらで多くのことが書かれています 。 一番下の行は、特別なタイプフィールドを使用して「誰が誰であるか」を明確にするために、Client、Manager、およびUserのエントリを同じPeopleテーブルに配置することです。 以下に例を示します。 それは条件付きで、一般的なフィールドはアスタリスクでマークされ、プライベートフィールドはモデル名の大文字でマークされます:



type | name* | email* | position (M) | company (C) | hobby (U) ----------------------------------------------------------------------------------------- manager | Slartibartfast | a@b.com | Planet designer | NULL | NULL client | Ford | c@d.com | | Megadodo Publications | NULL user | Arthur | e@f.com | NULL | NULL | Travelling
      
      





ただし、この場合、Managerはユーザーから異常な趣味のプロパティを取得します。 また、趣味マネージャーのフィールドは常に空です。 この場合のユーザー、クライアント、およびマネージャーは、独自のテーブルを持たないPersonのサブクラスであり、それぞれの一意のプロパティは親テーブル/モデルで宣言する必要があります。



原則として、これに目を向けることはできますが、Managerがクライアントとユーザーとは関係のない42個の独自のフィールドの作成を必要とする場合はどうでしょうか? この場合、特定のフィールドを個別のクライアント、ユーザー、およびマネージャーテーブルに転送し、人々に共通のフィールドだけを残し、必要な関係を構築するためのタイプとIDを残す方が論理的です。 Googleが示唆しているこのようなスキームは複数テーブルの継承と呼ばれますが、残念ながら、Railsはそれについてまだ何も知らないため、開発者フォーラムでの簡単な検索が示すように、予見できる将来にはなりません。



ネストされた属性+委任


この問題は次のように解決できます。



 class Manager < ActiveRecord::Base belongs_to :person #  accepts_nested_attributes_for :person delegate :name, :email, to: :person #  validates_presence_of :position end Company.find(42).managers.create(position: 'Paranoid android', person_attributes: { name: 'Marvin', email: 'whats_the@point_to.be' })
      
      





原則としてこれはオプションですが、この場合、レコードを作成または変更するときは常に共通の属性を個別のハッシュで分離し、フォームを表示するときはfields_forヘルパーを使用する必要があります。また、同じRailsガイド。



両方のモデルを「シームレスに」マージし、共通フィールドマネージャー、ユーザー、クライアントの実装の特殊性をアプリケーションの他のクラスの観点から完全に分離したいと思います。



自分の庭


明らかな理由から、私はそれをだまそうとは思いませんが、「rails multiple table inheritance」または「rails class table inheritance」の組み合わせを見れば、MTIを実装するための多くのオプションが見つかります。



宝石


最初からすべてがすでに行われていると仮定することは最初から論理的でした。それが私が見つけたものです。 Githubのリポジトリに関するあまり詳細ではない研究では、 active_record-acts_asのみがそれらから生きて発展していることが示されています。 Readmeは複製しません。gemの使用方法を明確に説明しています。 問題をざっと見てみると、プロジェクトはまだ初期段階にありますが、IMOは適切なテストカバレッジで非常に適用可能です。



同様の問題が発生しましたか? 他のソリューションを知っていますか? コメントであなたの意見を聞いてうれしいです。



All Articles