タグ管理できるメモ帳を作る (1)

今回は関係ないですが、さくらで動かしている Rails に gateway.cgi を導入してみました。感激するほど爆速ですよっ!
さて初心者アプリにありがちなメモ帳です。メール投稿とか夢が広がりんぐです。今回はタグ管理できるメモ帳を作ってみたいと思います。スマートなやり方は知りませんが、多対多の関係になるので、メモのテーブルとタグのテーブル、そしてメモとタグのそれぞれの id を格納して関連付け行う、関連テーブルが必要です。最初に1対多じゃないの?と考えちゃってた辺り、慣れるまで複雑な所ですね。
今回みたいな単純な多対多関連を実現するには has_many とかじゃなくて has_and_belongs_to_many という長ったらしい名前で宣言します。略して habtm とか呼ばれてるらしいです。

まずはテーブルを作る

memo と tag のマイグレーションは scaffold で自動生成しました。いい加減 scaffold 離れした方がいいですね。関連テーブルのモデルは要らないので、マイグレーションファイルだけ作成します。関連テーブルにも命名規則があり、memos テーブルと tags テーブルの関連テーブルであれば memos_tags という名前になります。memos_tags に id は必要なく、memo_id (integer) カラムと tag_id (integer) カラムさえあれば良いです。
関連テーブルのマイグレーションファイルはこんな感じ。

class CreateMemosTags < ActiveRecord::Migration
  def self.up
    create_table(:memos_tags, :id => false) do |t|
      t.integer :memo_id
      t.integer :tag_id
    end
  end

  def self.down
    drop_table :memos_tags
  end
end

そしてテーブル作成。

% script/generate scaffold memo title:string content:string tag:string
% script/generate scaffold tag name:string
% rake db:migrate 

habtm の宣言

Memo と Tag それぞれのモデル内で habtm の宣言をします。

class Memo < ActiveRecord::Base
  has_and_belongs_to_many :memos
end

Tag にも。

class Memo < ActiveRecord::Base
  has_and_belongs_to_many :memos
end

挙動の確認

% script/console
>>  Tag.create( :name => 'test' )
>>  kamo = Memo.create( :title => 'テストだよう', :tag => 'test' )
>>  kamo.tags << Tag.find( :all, :conditions => ["name = ?", kamo.tag] )

これで関連付けたいアイテムの id が memos_tags テーブルに登録されます。1つのタグに複数のメモを関連付けて

% script/console
>>  tag = Tag.find(0)
>>  tag.memos.each do |r|
?>  puts r.title
?>  end

こんな感じで取り出せるよ!


次は登録画面。テーブル相関図をダイアリーのお絵描きツールや表組みで描けば分かり易かったですね。