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 set
Artistを作成して中間テーブルにデータを追加するが、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件) を見る