12

私はここ数時間、どのルートに行くべきかを考えて苦しんでいます。通知モデルがあります。今までは notification_type 列を使ってタイプを管理していましたが、通知のタイプごとに動作が異なるため、別々のクラスを作成したほうがよいと思います。

現在、通知を送信する方法は 3 つあります: SMS、Twitter、E メール

各通知には次のものが含まれます。

id
subject
message
valediction
sent_people_count
deliver_by
geotarget
event_id
list_id
processed_at
deleted_at
created_at
updated_at

性感染症は良い候補のようですね。もちろん、Twitter/SMS には件名がなく、Twitter には sent_people_count、valediction はありません。この場合、彼らはほとんどの分野を共有していると言えます。ただし、Twitter の「reply_to」フィールドと DM のブール値を追加するとどうなるでしょうか。

ここでの私の要点は、現時点では STI は理にかなっているということですが、これは、MTI から始めるだけでなく、将来的に自分自身を蹴っている可能性があるということですか?

さらに複雑なことに、私は一種の通知である Newsletter モデルが必要ですが、違いは event_id または delivery_by を使用しないことです。

通知基本クラス フィールドの約 2/3 を使用して、通知のすべてのサブクラスを確認できました。STI は簡単に使用できますか? それとも MTI を使用する必要がありますか?

4

4 に答える 4

20

混合モデルのアプローチを検討しましたか?

コア通知フィールドに単一テーブルの継承を使用する場合。次に、すべての一意のアイテムを特定のテーブル/モデルにオフロードします。通知サブクラスとの関係は 1 つです。

セットアップのオーバーヘッドが少し増えますが、すべてのクラスとテーブルが定義されると、かなり DRY になります。物を保管するのにかなり効率的な方法のようです。熱心な読み込みを使用すると、データベースに過度の負荷がかかることはありません。

この例では、電子メールには固有の詳細がないと仮定します。これがどのようにマッピングされるかです。

class Notification < ActiveRecord::Base
  # common methods/validations/associations
  ...

  def self.relate_to_details
    class_eval <<-EOF
      has_one :details, :class_name => "#{self.name}Detail"
      accepts_nested_attributes_for :details
      default_scope -> { includes(:details) }
    EOF
  end
end

class SMS < Notification
  relate_to_details

  # sms specific methods
  ...
end

class Twitter < Notification
  relate_to_details

  # twitter specific methods
  ...
end

class Email < Notification

  # email specific methods
  ...
end

class SMSDetail < ActiveRecord::Base
  belongs_to :SMS, :class_name => "SMS"           

  # sms specific validations
  ...
end

class TwiterDetail < ActiveRecord::Base
  belongs_to :twitter

  # twitter specific validations
  ...
end

各詳細テーブルには、通知 ID と、通知テーブルに含まれていないコミュニケーション ニーズを形成する列のみが含まれます。ただし、メディア固有の情報を取得するための追加のメソッド呼び出しを意味します。

これは素晴らしいことですが、必要だと思いますか?

設計上必要なものはほとんどありません。CPU とストレージ スペースのコストが低下するにつれて、必要な設計コンセプトも低下します。私がこのスキームを提案したのは、STI と MTI の両方の長所を提供し、それらの弱点のいくつかを取り除いたからです。

利点に関する限り:

このスキームは、STI の一貫性を提供します。再作成する必要のないテーブル。リンクされたテーブルには、行の 75% が空である約数十の列があります。サブクラスの作成も簡単です。新しいタイプが基本的な通知フィールドで完全にカバーされていない場合にのみ、一致する Details テーブルを作成する必要があります。また、すべての通知を単純に繰り返すこともできます。

MTI を使用すると、新しい通知の種類ごとに同じ列を再定義する必要なく、クラスのニーズを満たすためのストレージの節約とカスタマイズの容易さが得られます。ユニークなものだけ。

ただし、このスキームには STI の大きな欠点もあります。テーブルは 4 を置き換える予定です。これは、巨大になると速度低下を引き起こし始める可能性があります。

簡単に言えば、このアプローチは必要ありません。問題を効率的に処理するための最もドライな方法だと思います。非常に短期的には、STIがそれを行う方法です。非常に長い目で見れば、MTI が進むべき道ですが、何百万もの通知を受け取るポイントについて話しているのです。このアプローチは、簡単に拡張できる優れた中間点です。

詳細な宝石

あなたのソリューションに宝石を作成しました: https://github.com/czaks/detailed。これを使用すると、 Notification クラスを次のように単純化できます。

class Notification < ActiveRecord::Base
  include Detailed
end

残りは前の方法で進みます。

追加のボーナスとして、サブクラス固有の属性に直接アクセス (読み取り、書き込み、関連付け) できるようにnotification.phone_numberなりました: に頼ることなく: notification.details.phone_number。メイン クラスとサブクラスにすべてのコードを記述して、Details モデルを空のままにすることもできます。通常Notification.all_with_detailsNotification.all.

私のユースケースでは機能しますが、現時点ではこの宝石は十分にテストされていないことに注意してください。

于 2009-10-28T01:43:44.747 に答える
3

限られた情報を考えると、私はSTIに固執すると思います.

重要な質問は次のとおりです: アプリ内に、すべての種類の通知をまとめて検討したい場所はありますか? もしそうなら、それは性感染症に固執したいという強いサインです。

于 2009-10-28T14:06:17.873 に答える
2

これが古いことは知っていますが、解決策を思いついた後、どこでも使用できる可能性のある答えが見つかりました! 私は最近、Rails で複数テーブルの継承とクラスの継承を実装する有望なプロジェクトをフォークしました。私は数日かけて迅速な開発、修正、コメント、ドキュメントを行い、CITIER Class Inheritance and Table Inheritance Embeddings for Rails として再リリースしました。

Twitter、E メール、および SMS が Notification から継承するモデルを構築するだけで、必要なことを実行できるはずです。次に、通知の移行には共通の属性のみを含め、3 つのサブタイプの移行には固有の属性を含めます。

または、ルート Notification クラスで関数を定義し、それをサブクラスでオーバーロードして、別のものを返すこともできます。

見てみましょう: https://github.com/PeterHamilton/citier

とても便利だと思います!(ちなみに)問題とテスト、コードのクリーンアップなどでコミュニティの助けを歓迎します!これは多くの人が高く評価するものであることを私は知っています。

ただし、私が言ったように、日々改善/進化しているため、定期的に更新してください.

于 2011-04-28T23:36:52.037 に答える
1
has_one :details, :class_name => "#{self.class.name}Detail"

動作しません。クラス定義のコンテキストでの self.class.name は「Class」であるため、:class_name は常に「ClassDetail」です。

したがって、次のようにする必要があります。

has_one :details, :class_name => "#{self.name}Detail"

でもとてもいいアイデア!

于 2009-11-13T08:14:44.533 に答える