Rails3で多対多関連を作る

Rails3で多対多関連を作ってみて、ハマったところがあるのでメモしておく。
しかし多対多関連はいつのまにか has_many :through するのが当たり前になっているんだなぁ。

1.関連モデルを作る

基本的に「Rails3 レシピブック」通りだけど、モデルの attr_accesible で、"関連先モデル名_ids" のアトリビュートを許可してあげる必要がある。


1. 結合テーブルを作る

2. 結合テーブルに対応するモデルから、両モデルへのbelongs_to宣言をする。
これは昔から変わってない。

class Categorization < ActiveRecord::Base
  belongs_to :category
  belongs_to :entry
end

3. 多対多の関連を持つ双方のモデルで has_many宣言と、has_many :through宣言をする。さらにattr_accesibleも宣言する。

class Entry < ActiveRecord::Base
  has_many :categorizations      # ★★★ これ忘れがちだけど必要!
  has_many :categories, through: :categorizations
  attr_accessible :category_ids  # ★★★ これ忘れがちだけど必要!
end
class Category < ActiveRecord::Base
  has_many :categorizations      # ★★★これ忘れがちだけど必要!
  has_many :entries, through: :categorizations
  attr_accessible :entry_ids     # ★★★ これ忘れがちだけど必要!
end

2. Viewを作る

ドロップダウンリストが簡単に作れる。_form.html にこれだけ書いておけばOK。

<%= form_for @entry do |f| %>
  # モデルオブジェクト Category を選択対象とするドロップダウンリストを
  # 生成する
  <%= f.collection_select(:category_ids, Category.all, :id, :name, 
                   {selected: @entry.category_ids}, {multiple: true}) %>
<% end %>

これだけでnewもupdateも対応できてしまう。(scaffoldがある前提)
複数選択から1つだけ選択に変えたり、選択無しに変えたりしても、関連テーブルを適切に処理してくれる。
正直これだけでここまでやってくれるとは思わなかった。
さすが Rails!