パーフェクトRoRの勉強メモです。
Active Record周りの整理。どういうSQLが流れるか、常に意識していきたい。
モデル
一対多の関係
例)User(一)は複数のTicket(多)を持つ
class User << ActiveRecord::Base
has_many :tickets
...
end
class Ticket << ActiveRecord::Base
belongs_to :user
...
end
上記の設定を入れることで、Ticketモデルのuser_idが外部キーであり、Userモデルの idが参照キーであると、Active Recordが解釈してくれる。
irb(main):007:0> user = User.find(1)
User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
# user(id=1)の持つ全チケットを表示
# where句でuser_id = 1が条件に入る
irb(main):008:0> user.tickets
Ticket Load (1.3ms) SELECT `tickets`.* FROM `tickets` WHERE `tickets`.`user_id` = 1
irb(main):023:0* ticket = Ticket.find(4)
Ticket Load (0.4ms) SELECT `tickets`.* FROM `tickets` WHERE `tickets`.`id` = 4 LIMIT 1
# ticket(id=4)を所有するユーザ(1つ)を表示
# where句でuser.id = ticket.user_id(1)が入る
irb(main):024:0> ticket.user
User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
多対多の関係
User(一)は複数のEventに参加している。
Event(一)には複数のUserが参加する。
これを、例えばeventsにuser_id, usersにevent_idを持たせた場合、同じUserが、違うevent_idで複数存在するなどの問題が起きる。
解決方法として、中間モデル(Ticket)で表現をする。
class User < ActiveRecord::Base
has_many :tickets
has_many :events, through: :tickets #EventとTicketをevent_idで内部結合し、ticket.user_id=ユーザIDで絞りこみしてEventへアクセス
...
end
class Event < ActiveRecord::Base
has_many :tickets
has_many :users, through: :tickets #UserとTicketをuser_idで内部結合し、ticket.event=id=イヴベントIDで絞り込みしてUserへアクセス
...
end
class Ticket < ActiveRecord::Base
belongs_to :user
belongs_to :event
...
end
irb(main):001:0> u = User.find(1)
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
irb(main):002:0> u.events
Event Load (0.5ms) SELECT `events`.* FROM `events` INNER JOIN `tickets` ON `events`.`id` = `tickets`.`event_id` WHERE `tickets`.`user_id` = 1
irb(main):007:0* event=Event.find(1)
Event Load (1.1ms) SELECT `events`.* FROM `events` WHERE `events`.`id` = 1 LIMIT 1
irb(main):008:0> event.users
User Load (0.4ms) SELECT `users`.* FROM `users` INNER JOIN `tickets` ON `users`.`id` = `tickets`.`user_id` WHERE `tickets`.`event_id` = 1