11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ActiveRecord 1対多、多対多の表現

Last updated at Posted at 2014-12-30

パーフェクトRoRの勉強メモです。
Active Record周りの整理。どういうSQLが流れるか、常に意識していきたい。

モデル

一対多の関係

例)User(一)は複数のTicket(多)を持つ

image


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が参加する。

image

これを、例えばeventsにuser_id, usersにevent_idを持たせた場合、同じUserが、違うevent_idで複数存在するなどの問題が起きる。

解決方法として、中間モデル(Ticket)で表現をする。

image

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

11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?