0
1

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 3 years have passed since last update.

乃木坂でポリモーフィック関連を実装してみた。

Posted at

ポリモーフィック関連について

なんとなくとっつきにくいが故に、勉強してしばらく経つとポリモーフィック...?となるので、楽しく実装してみました。備忘録的な感じなので、ゆるっと見ていって下さい。

通常のアソシエーション

どの坂道グループがどの楽曲を歌っているのかを、ポリーモーフィック関連を定義せずに実装すると...

nogizaka.rb
class Nogizaka < ApplicationRecord
  has_many :songs
end
keyakizaka.rb
class Keyakizaka < ApplicationRecord
  has_many :songs
end
hinatazaka.rb
class Hinatakizaka < ApplicationRecord
  has_many :songs
end
song.rb
class Song < ApplicationRecord
  belongs_to :nogizaka
  belongs_to :keyakizaka
  belongs_to :hinatazaka
end

問題点

  • ある楽曲を歌うアイドルの情報を取得したい場合、どのアイドルが歌っているのか確認しなくてはならない。(坂道ファンなら確認せずとも分かってしまうと思いますが...笑)
@song = Song.take #適当にインスタンスを取得
@song.nogizaka #乃木坂46の楽曲の場合
@song.hinatazaka #日向坂46の楽曲の場合
  • 46グループが増えた時に、songモデルにカラムを追加する必要がある。

ポリモーフィックで実装

  • referencespolymorphic: trueを設定するだけ
20200620xxxx_create_songs.rb
class CreateSongs < ActiveRecord::Migration[5.2]
  def change
    create_table :songs do |t|
      t.string :name
      t.references :songable, polymorphic: true, index: true #ココ!!
      t.timestamps
    end
  end
end
schema.rb
create_table "songs", force: :cascade do |t|
    t.string "name"
    t.string "postable_type" #typeで乃木坂クラスなのか欅坂クラスなのかを見分けている
    t.integer "postable_id"
    ...(以下略)
  end

モデル達も書き換えてあげる。意外と簡単です。

class Nogizaka < ApplicationRecord
  has_many :songs, as: :songable
end

class Keyakizaka < ApplicationRecord
  has_many :songs, as: :songable
end

class Hinatakizaka < ApplicationRecord
  has_many :songs, as: :songable
end

class Song < ApplicationRecord
  belongs_to :songable, polymorphic: true
  # Before ↓↓↓
  # belongs_to :nogizaka
  # belongs_to :keyakizaka
  # belongs_to :hinatazaka 
  #3行が1行になりました!
end

で、何が起こるの???

# @songが乃木坂の楽曲の場合
# 通常のアソシエーション
@song.nogizaka # =>name:"乃木坂46", year_of_formation:2011,...
#ポリモーフィック関連
@song.songable # =>name:"乃木坂46", year_of_formation:2011,...
  • 上記で、同じ乃木坂モデルのインスタンスが取得できる
  • なんとなくのイメージを掴んでもらえれば嬉しいです。

こんな書き方もできます

同名メソッドを各モデルに定義し、その中での挙動を変えます。

class Nogizaka < ApplicationRecord
  has_many :songs, as: :songable

  def cute_member
   "名前:#{name}, ペット:#{pet_name}"
  end
end


class Keyakizaka < ApplicationRecord
  has_many :songs, as: :songable
  
  def cute_member
   "名前:#{name}, 出身地:#{birthplace}"
  end
end


class Hinatakizaka < ApplicationRecord
  has_many :songs, as: :songable

  def cute_member
   "名前:#{name}, キャッチコピー:#{catch_copy}"
  end
end

結果

#@songが乃木坂の場合
@song.songable.cute_member 
=> "名前:与田祐希, ペット:ごんぞう"

#@songが欅坂の場合
@song.songable.cute_member 
=> "名前:森田ひかる, 出身地:福岡県"

#@songが日向坂の場合
@song.songable.cute_member 
=> "名前:上村ひなの, キャッチコピー:ひなのなの!"

まとめ

  • @song.songableで乃木坂モデル(欅坂、日向坂)のインスタンスが取れる。(イメージがつきにくく、ポリモーフィックを難解にしているのはこの辺りな気がしました。)
  • アイドルはやっぱり可愛い。。。
0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?