関連付けるテーブルは同じなのだが、条件によって別のオブジェクトとして関連付けるレコードを決定する方法がないか探してみた。
具体的に言うと、現在、次のようなテーブルがあって、
create table books (
id int(11) not null auto_increment,
title varchar(255) default null,
comment text
)
本のタイトル(簡単のために本の情報をタイトルだけとしている)とコメントが格納できます。ここでコメントの種類が増えて、ネタばれコメントを追加したくなったとする。
一番素朴な方法は、booksテーブルにnetabareカラムを直接追加してcommentカラムと同じ様に持てばいいわけだが、そもそもコメントは本の情報ではないし、ネタばれコメントにいたっては更にそうだ。
そこでコメントを別テーブル化したくなる。
class Book < ActiveRecord::Base
has_one :comment
has_one :netabare
:
class Comment < ActiveRecord::Base
belongs_to :book
:
class Netabare < ActiveRecord::Base
belongs_to :book
:
とかするわけであるが、これだとモデルクラスとテーブルが2つ増える。
コメントとネタばれは、ユーザの用途は違うがDBに持つ情報としてはほぼ同じであるので、commentsテーブルは共通にできないだろうか。
has_one, belongs_toのリファレンスを見ると、その為に使えそうな:conditionsというオプションが存在した。
commentsテーブルは共通とし、comment_typeというカラムを用意し、これが1の場合、通常のcomment、2の場合ネタばれコメントとして進めてみる。まずはマイグレーションの作成だ。現在コメントはbooks.commentに格納されているので、データの移行も考えた頑張ったマイグレーションを作成する必要がある。
新テーブルcommentsの追加 books.commentからcommentsにcomment_type=1でデータ移行 books.commentカラムの削除 commentsテーブルにbook_id,comment_typeの複合インデックス