混合モデルのアプローチを検討しましたか?
コア通知フィールドに単一テーブルの継承を使用する場合。次に、すべての一意のアイテムを特定のテーブル/モデルにオフロードします。通知サブクラスとの関係は 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_details
のNotification.all
.
私のユースケースでは機能しますが、現時点ではこの宝石は十分にテストされていないことに注意してください。