5

私は多くの異なるモデル (20 近く) を持っており、いくつかの共通の属性を共有していますが、他のモデルではある程度異なっています。STIは一見魅力的に見えますが、急速な製品開発により、さまざまなモデルが時間の経過とともにどのように進化するかはわかりません。

私たちのアプリケーションとよく似ているのは、Yelp です。Rails で Yelp はどのように何かを管理しますか? すべての投稿には、「住所」などの共通の属性があります。それでも、それらは他のものとはかなり異なります。たとえば、レストランには予約オプションがあり、他のレストランには予約オプションがない場合があります。レストランには、「アルコール可」など、他のレストランには当てはまらない属性がたくさんあります。STIでこれを行うと、すぐに手に負えなくなります。

それで、次善の選択肢は何ですか?PostgresでHStore?私は HStore を小さなこと以外に使用することに慣れていません。HStore は、いくつかの問題を解決する一方で、データ型の欠如、参照整合性チェックの欠如などの問題をもたらします。構築する基盤として、強固なリレーショナル データベースが必要です。したがって、Yelp の場合、おそらく、レストランのモデルが私が目指すところです。私はここのような提案を見てきました - http://mediumexposure.com/multiple-table-inheritance-active-record/、しかし、私は非常に一般的な何かを得るために多くのモンキーパッチを行うことに満足していません.

それで、他にどのような選択肢が存在するのか(もしあれば)、それともただ弾丸を噛んで歯を磨いて、それらの共通の属性を20のモデルにコピーする必要があるのでしょうか? 私の問題は、コード自体ではなく、移行ファイルに起因すると考えています。たとえば、テーブルをループしてそれらの属性をテーブルに設定するように移行をセットアップした場合、異なるモデルを使用することで問題の範囲を軽減できたでしょうか?

別のモデルで将来的に多くの問題を引き起こす可能性のある重要な何かを見落としていますか?

4

2 に答える 2

6

ここにいくつかのオプションがあります。

  1. 頑張って、同じ属性をたくさん持つ 20 種類のモデルを作成してください。これらのモデルは時間の経過とともに変動する可能性があります (特定の 1 つの型に新しいフィールドを追加する) ため、STI を使用して 200 列のテーブルを作成します。おそらくそうではないかもしれません - 特に探索的/アジャイルなソフトウェアでは、未来は見えにくいです。

  2. 非参照フィールドを NoSQL (ドキュメント) データベースに格納します。リレーショナルなレコードの部分 (ユーザーには多くのレビューがあり、レビューには 1 つのビジネスがあります) にはリレーショナル データベースを使用しますが、タイプ固有のものは NoSQL データベースに保持します。external_document_idRails モデルとexternal_record_idNoSQLドキュメント スキーマに を保持してexternal_record_type、最終的に使用する NoSQL ORM を使用して、喫煙を許可するすべてのバーを引き続きクエリできるようにします。

  3. 属性モデルを作成します。andフィールドbelongs_to :parent_object, polymorphic: trueを持つ属性。このアプローチを使用すると、基本モデルができ、各ビジネスでそれが可能になります。ビジネスの特定の (非リレーショナル?) 属性 ( ) は 1 つのレコードです。のキーは、文字列にすることも、Ruby 定数の数値にすることもできます。基本的にエンティティを使用して、オプション #2 の SQL バージョンを作成しています。これは良いオプションかもしれません。私はこれをユーザー モデルまたはプロファイル モデルに使用しました。(ただし、このアプローチには注意が必要なパフォーマンス ヒットがいくつかあります)。keyvalueBusinesshas_many :attributesallows_smokingAttributeAttributeAttribute

サブクラスのように聞こえるものに対して、これほど多くの (独立した) モデルを使用することについて、私は本当に心配しています。懸念を使用することで、一般的な動作/メソッドを DRY できる可能性があります (ミックスインの概念に対する構文糖衣、Rails 4 の懸念に関する素晴らしい SO 回答を参照してください)。もちろん、(最初の) 移行の問題はまだあります。

于 2013-07-06T02:30:45.313 に答える
1

ここに別のオプションを追加します: Serialized LOB (272)。ActiveRecord を使用すると、オブジェクトに対してこれを行うことができますserialize:

class User < ActiveRecord::Base serialize :preferences end

user = User.create(preferences: { "background" => "black", "display" => large }) User.find(user.id).preferences # => { "background" => "black", "表示" => 大 }

( ActiveRecord::Baseドキュメントのコード例)

理解しておくべき重要な結果は、シリアライズされた LOB に格納された属性は索引付けできず、パフォーマンスの高い方法で検索できないことです。後で列をインデックスとして使用できるようにする必要があることがわかった場合は、[ほとんどの場合] Ruby プログラムを作成して変換を実行する必要があります (ただし、デフォルトではシリアル化は Yaml で行われるため、任意の Yaml パーサーで十分です)。

利点は、このパターンを適用するためにスタックにテクノロジーの変更を加える必要がないことです。収集したデータの量に基づいて、このパターンから移行するのは簡単です。

于 2013-07-10T03:29:20.597 に答える