Ruby on Rails: テーブル間のリレーションシップ has_many belongs_to, has_one, has_and_belongs_to_many

ショッピングサイトを作るにあたっては避けて通れないややこしい概念だけど、調べてみたら面白い。
今回はUserとOrderの関係から探ってみた。

Userは複数のOrderをするので、Userモデルには has_many :orders, Orderモデルにはbelongs_to :userとするのが定石

まずは、Migration

lass CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :name
t.string :email

t.timestamps
end
end

def self.down
drop_table :users
end
end

class CreateOrders < ActiveRecord::Migration
def self.up
create_table :orders do |t|
t.string :name
t.integer :user_id

t.timestamps
end
end

def self.down
drop_table :orders
end
end

この二つを作る

#rake db:migration コマンドにてテーブル作成

app/model/order.rb

class Order < ActiveRecord::Base
belongs_to :user
end

app/model/user.rb

class User < ActiveRecord::Base
has_many :orders
end

has_many :orders宣言によってUserクラスには

orders
orders<<
orders.push
orders.replace
orders.delete
orders.delete_all
orders.destroy_all
orders.clear
orders.find
orders.count
orders.size
orders.length
orders.empty?
orders.sum
orders.uniq
orders.build
orders.create

これだけのメソッドが追加される。一対多関係なのでuserからすれば沢山のorderが存在するわけで、それをいじり倒すメソッドが必要というわけだ。

まずはコンソールで検証してみよう

>script/console
Loading development environment (Rails 2.1.1)
>> a = User.new
a = User.new
=> #

まずは空っぽのUserインスタンスが生成される。

>> a.orders
a.orders
=> []

子のArrayクラスを返すがまだ何もない。

>> a.orders.build
a.orders.build
=> #
>> a.orders
a.orders
=> [#]

buildメソッドは新たにorderオブジェクトをを生成し(セーブはしない)userへリンクさせる。

>> a.orders.build
a.orders.build
=> #
>> a.orders
a.orders
=> [#, #]

もう一回buildするともう一個くっつく

>> a.save
a.save
=> true
>> a
a
=> #
>> a.orders
a.orders
=> [#, #]

セーブするとOderオブジェクトたちのuser_idは親のid=4となっていることが分かる。

意外と簡単!