2009-03-07 7 views
4

こんにちはスタックオーバーフロー:私はムービークリップ、mp3、写真を格納しているいくつかの異なるモデル(ムービー、ソング、写真など)を持つRuby on Railsアプリケーションを構築しています。私はユーザーがこれらのモデルのいずれかにコメントできるようにして、どのコメントが公開されているかをコントロールできるようにしたいと思います。私はよ、私はコメントテーブルに推測している次に多くのモデルにコメントを追加するベストプラクティスとは何ですか?

has_many :comments 

:各モデルを

belongs_to :movie 
belongs_to :song 
belongs_to :photo 

そしてネクタイ:

はとのコメントモデルを作成するためのベストプラクティスです

comment, movie_id, song_id, photo_id 

これは、このようなものを構築する正しい方法ですか、それとも、より良い方法ですか?あなたの助けを前にありがとう。

答えて

0

私はRoRの経験を持っていませんが、データベースレベルで継承を使用してオフにしますが、おそらくより良いと思います。この場合には、お使いのDBMSを仮定すると、これをサポートしています。

CREATE TABLE item (int id, ...); 
CREATE TABLE movie (...) INHERITS (item); 
CREATE TABLE song (...) INHERITS (item); 
[...] 
CREATE TABLE comments (int id, int item_id REFERENCES item(id)); 

別のアプローチは、タイプを持つ単一のテーブル可能性があり列:

CREATE TABLE item (int id, int type...); 
CREATE TABLE comments (int id, int item_id REFERENCES item(id)); 

これまで説明したとおり、RoRを使用してこれを正確に実装する方法はわかりません。

4

acts_as_commentableを使用してください。これは、commentable_type(コメントされた項目のモデル名)とcommentable_id(モデルのID)を持つコメントテーブルを作成します。そして、あなたがあなたのモデルに必要なこと:

movie_comments, song_comments, photo_comments 

してから使用してください:

class Photo < ActiveRecord::Base 
    acts_as_commentable 
end 
+0

私はこのアプローチが気に入らない理由は、モデル名をデータベースレコードに結びつけるからです。モデルの名前を変更すると、テーブル名を変更するだけでは簡単ではありません。あなたの変更に合わせて、commentable_typeテーブル内のすべてのエントリを変更することを忘れないでください。 –

+0

モデルの名前を変更している場合、commentable_type列を更新するためにdbマイグレーションを作成するコストは、コードを変更するコストに比べて簡単です。 –

1

コメントの種類ごとに関係を保持するテーブルを作成します

class Movie < ActiveRecord::Base 

    has_many :movie_comments 
    has_many :comments, :through => :movie_comments 

end 

class MovieComment < ActiveRecord::Base 
    include CommentRelationship 
    belongs_to :comment 
    belongs_to :movie 
end 

することができますモジュール(CommentRelationship)を使用して、関係テーブル間の共通機能をすべて保持する(movie_comments)

このアプローチでは、それぞれのタイプ間で同様の機能を実現しながら、タイプに応じてコメントを異なる方法で処理できる柔軟性が得られます。また、あなたが各列のNULLエントリのトンで終わるません:

comment   | movie_id | photo_id | song_id 
---------------------------------------------------- 
Some comment   10   null  null 
Some other comment  null  23  null 

これらのヌルは間違いなくあなたが異なったデータベースを構築すべきである印です。

0

おそらく、サラが示唆していることを行い、コメントを処理する既存のプラグインの1つを使用することをお勧めします。

自分でロールを張ったり、カバーの下で何が起こるかを理解したい場合は、Railsが継承を処理する方法についてのシングルテーブル継承について読む必要があります。基本的に、あなたは、単一のcommentsテーブルALA必要があります。

# db/migrate/xxx_create_comments 
create_table :comments do |t| 
    t.string :type, :null => false 
    t.references :movies, :songs, :photos 
end 

を今、あなたは

class Comment < ActiveRecord::Base 
    validates_presence_of :body, :author 
    # shared validations go here 
end 

class SongComment < Comment 
    belongs_to :song 
end 

class MovieComment < Comment 
    belongs_to :movie 
end 

class PhotoComment < Comment 
    belongs_to :photo 
end 

としてあなたのコメントの種類を定義することができますすべてのコメントはcomments、単一のテーブルに格納されますが、PhotoComment.allはコメントだけを返します。そのためにはtype == "Photo"です。

+0

サブクラスの名前以外に、型として格納されるものを定義する方法はありますか?例:t.references {:movies => 1、photos => 2、:songs => 3}、PhotoComment.allはtype == 2となります。 –

+0

私には分かりませんが、なぜそうしますか? –

1

個人的に私はそれをこのようにモデル化するだろう:すべての後に

Media table (media_id, type_id, content, ...) 
. 
MediaType table (type_id, description, ...) 
. 
MediaComments table (comment_id, media_id, comment_text, ...) 

を、歌、映画、または写真の間にデータベースに違いはありません。それはすべてバイナリデータです。このモデルでは、再コーディングすることなく新しい「メディアタイプ」を追加できます。新しい "MediaType"レコードを追加し、データをMediaテーブルに投げます。

さらに柔軟性の高い方法です。

+0

これはスマートなアイデアであり、変更を簡単にします。 – Tilendor

関連する問題