Railsメモ(14) : 多対多のリレーションをhas_many throughで作成する
これまでにSongモデルを作成しているが、今度はArtistモデルを作成する。
Songは"featuring"などで複数のArtistが関わっており、逆にArtistは複数のSongを持っているため、これらのモデルに多対多のリレーションを作成する。
Artistモデルの作成
まず、Artistモデル(ひとまずnameだけ)を下記コマンドで作成してdb:migrateを実行する。
$ rails g model Artist name:string $ rake db:migrate
show-modelsで確認すると以下のようになる。
$ rails c [1] pry(main)> show-models Artist id: integer name: string created_at: datetime updated_at: datetime Song id: integer title: string display_artist: string ranking: integer year: integer created_at: datetime updated_at: datetime
多対多のリレーションを作成
SongとArtistの間に多対多のリレーションを作成するために、まず中間モデルを作成する。
$ rails g model SongArtist song:references artist:references $ rake db:migrate
続いて、それぞれのモデルのファイルを編集する。
app/models/song.rb
class Song < ActiveRecord::Base …省略… has_many :song_artists has_many :artists, through: :song_artists end
app/models/artist.rb
class Artist < ActiveRecord::Base has_many :song_artists has_many :songs, through: :song_artists end
show-modelsで以下のように多対多のリレーションが確認できる。
$ rails c [1] pry(main)> show-models Artist id: integer name: string created_at: datetime updated_at: datetime has_many :song_artists has_many :songs (through :song_artists) Song id: integer title: string display_artist: string ranking: integer year: integer created_at: datetime updated_at: datetime has_many :artists (through :song_artists) has_many :song_artists SongArtist id: integer song_id: integer artist_id: integer created_at: datetime updated_at: datetime belongs_to :artist belongs_to :song
rails consoleで多対多のリレーションを確認する
多対多のリレーションが正しく動作するかrails consoleで確認してみる。
試しに"Sam Smith"に関連するArtistデータを追加するが、関連する曲は3曲存在する。
Song.where("display_artist LIKE ?", "%Sam Smith%").select("id, title, display_artist")
Song Load (2.0ms) SELECT id, title, display_artist FROM "songs" WHERE (display_artist LIKE '%Sam Smith%')
+------+--------------+---------------------------------+
| id | title | display_artist |
+------+--------------+---------------------------------+
| 2410 | Stay with Me | Sam Smith |
| 2428 | Latch | Disclosure featuring Sam Smith |
| 2482 | La La La | Naughty Boy featuring Sam Smith |
+------+--------------+---------------------------------+
3 rows in setArtistを作成して中間テーブルにデータを追加するが、Artistを主とした追加や、Songを主としたデータの追加が可能である。
[1] pry(main)> sam = Artist.create name: "Sam Smith"
[2] pry(main)> dis = Artist.create name: "Disclosure"
[3] pry(main)> nau = Artist.create name: "Naughty Boy"
[4] pry(main)> Artist.all.select("id, name")
+----+-------------+
| id | name |
+----+-------------+
| 1 | Sam Smith |
| 2 | Disclosure |
| 3 | Naughty Boy |
+----+-------------+
3 rows in set
[5] pry(main)> sam.songs << Song.find(2410)
[6] pry(main)> sam.songs << Song.find(2428)
[7] pry(main)> sam.songs << Song.find(2482)
[8] pry(main)> song1 = Song.find(2428)
[9] pry(main)> song1.artists << dis
[10] pry(main)> song2 = Song.find(2482)
[11] pry(main)> song2.artists << nau
[12] pry(main)> SongArtist.all.select("id, song_id, artist_id")
+----+---------+-----------+
| id | song_id | artist_id |
+----+---------+-----------+
| 1 | 2410 | 1 |
| 2 | 2428 | 1 |
| 3 | 2482 | 1 |
| 4 | 2428 | 2 |
| 5 | 2482 | 3 |
+----+---------+-----------+
5 rows in set多対多のリレーションのデータは以下のような方法でアクセス可能になっている。
[1] pry(main)> Artist.find(1).songs.select("songs.id, songs.title, songs.display_artist")
+------+--------------+---------------------------------+
| id | title | display_artist |
+------+--------------+---------------------------------+
| 2410 | Stay with Me | Sam Smith |
| 2428 | Latch | Disclosure featuring Sam Smith |
| 2482 | La La La | Naughty Boy featuring Sam Smith |
+------+--------------+---------------------------------+
3 rows in set
[2] pry(main)> Song.find(2428).artists.select("artists.id, artists.name")
+----+------------+
| id | name |
+----+------------+
| 1 | Sam Smith |
| 2 | Disclosure |
+----+------------+
2 rows in set
- 作者: すがわらまさのり,前島真一,近藤宇智朗,橋立友宏
- 出版社/メーカー: 技術評論社
- 発売日: 2014/06/06
- メディア: 大型本
- この商品を含むブログ (8件) を見る