2

オブジェクトが別のクラスの正確に n 個のオブジェクトに関連付けられている関係をモデル化する最良の方法は何だろうと考えていました。has_one 関係を特定の値 n に拡張したいと考えています。

たとえば、TopFiveMoviesList は user に属し、ちょうど 5 つの映画を持っています。基になる SQL テーブルには、movie_id_1、movie_id_2、... movie_id_5 などのフィールドがあると思います。

has_many リレーションシップを実行して、モデル レベルで子の数を制限できることはわかっていますが、中間テーブルは必要ありません。

4

3 に答える 3

2

結合モデルを介してこのモデルを実装することが、ここで最善の策になると思います。これにより、Listモデルはリストロジックについて心配し、Movieモデルはムービーロジックについて心配することができます。映画とリストの関係を処理するためのNomination(名前は最高ではありませんが、私が何を意味するかを知っています)モデルを作成できます。また、制限が5の場合は、引き戻すノミネートの数を制限できます。

このアプローチの方が優れていると思う理由はいくつかあります。

movie.listsまず、関係を双方向(および)でトラバースできるようにしたい場合list.movies、5列のアプローチは非常に面倒になります。

ActiveRecordがhas nリレーションシップをサポートする方がはるかに優れていますが、そうではないため、そのフレームワークと戦うことになります。また、has nこの状況では、関係は少しもろいようです。ActiveRecordでそのような実装が実現するのを見たことがありませんが、それが実現するのを見るのは本当に興味があります。:)

于 2009-01-01T22:03:31.843 に答える
1

「モデル」ではなく「実装」を意味していると思いますか?たとえば、5 つの Movie エンティティで構成される Person エンティティがある場合、UML でのモデリングは非常に簡単です。

しかし、has_one と言うと、has_5 に行くときに問題が発生します。単純なスカラー値の場合、has_one はおそらく親エンティティのプロパティです。Has_5 はおそらく、UML の「構成されている」関係を通じて互いに関連する 2 つのエンティティです。

答えるべき主な質問はおそらく、「常に『トップ 5』になると保証できますか?」ということです。はいの場合は、前述のように列でモデル化してください。いいえの場合は、別のエンティティでモデル化します。

もう 1 つの質問は、おそらく「リファクタリングはどれほど簡単か?」です。単純な場合は、5 つの列から始めて、エンティティが変更された場合はリファクタリングしてエンティティを分離します。

いつものように、「最善」はビジネスおよび技術環境に依存します。

于 2008-12-31T15:22:47.923 に答える
1

私の最初の本能は結合テーブルを使用することですが、それが望ましくない場合は、User.movie[1-5]_id列が法案に適合します。( movie1_idRails の慣例の方がmovie_id_1.)

このRailsとActiveRecordにタグを付けたので、完全にテストされておらず、おそらく多少間違っているモデルコードを回答に追加します。:)

class User < ActiveRecord::Base
  TOP_N_MOVIES = 5
  (1..TOP_N_MOVIES).each { |n|  belongs_to "movie#{n}".to_sym, :class_name => Movie }
end

その行をマクロ スタイルのメソッドでラップすることもできますが、それがアプリケーションの一般的なパターンでない限り、それを行うとおそらくコードが読みにくくなり、DRY のメリットはほとんどありません。

また、検証を追加して、ユーザーのリストに重複する映画がないことを確認することもできます。

ムービー クラスをユーザーに関連付ける方法も同様です。

class Movie < ActiveRecord::Base

  (1..User::TOP_N_MOVIES).each do |n| 
    has_many "users_list_as_top_#{n}".to_sym, :class_name => User, :foreign_key => "movie#{n}_id"
  end

  def users_list_as_top_anything
    ary = []
    (1..User::TOP_N_MOVIES).each {|n| ary += self.send("users_list_as_top_#{n}") }
    return ary
  end

end

(もちろん、users_list_as_top_anything明示的な SQL として書き出す方がよいでしょう。今日は怠け者です。)

于 2008-12-31T23:36:27.567 に答える