Railsのポリモーフィック関連を使って多対多を実現する

この記事を書いた人
井上 周

WEBのバックエンドエンジニア。金沢大学大学院→株式会社マイベスト。
最も得意な言語はRuby(Rails)。その他、GoやPython、TypeScriptsを使った開発を行っています。

井上 周をフォローする

個人開発として金沢観光情報サービスのhttps://notear.netを開発中にポリモーフィック関連でコードをすっきりさせたかったのでそのときに調べたことを書きます。

ポリモーフィズムとは

オブジェクト指向の3大要素

カプセル化、継承と並ぶ、オブジェクト指向の3大要素のうちの一つです。

ダックタイピング

“If it walks like a duck and quacks like a duck, it must be a duck”

「もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルである」

https://ja.wikipedia.org/wiki/%E3%83%80%E3%83%83%E3%82%AF%E3%83%BB%E3%82%BF%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0

オブジェクトの実態が違っても、決まった振る舞い(同じメソッドを呼び出すなど)をすることで、同じオブジェクトとして扱えることです。

いちいちオブジェクトの実態のことを考えてコードを書いていたらコードは汚くなるし、大変です。
メソッド(命令)を全部同じ名前で使えば、その内容についてはオブジェクトごとに勝手に変わっても大丈夫になります。

ポリモーフィック関連

ポリモーフィック関連とは、このポリモーフィズムを使ってモデルを関連づけることを言います。

やりたかったこと

例えばnotear.netでは、Cafe(カフェ)とSpot(観光スポット)をタグで検索できる機能をつけようと思いました。1つのSpotあるいはCafeに対して複数のSearchTag(タグ)が付随するようになります。

このときに、ポリモーフィックを使わないと、

class Cafe < ApplicationRecord
  has_many :search_tags, through: :cafe_search_tags
  has_many :cafe_search_tags
end

class Spot < ApplicationRecord
  has_many :search_tags, through: :spot_search_tags
  has_many :spot_search_tags
end

class CafeSearchTag < ApplicationRecord
  belongs_to :cafe
  belongs_to :search_tag
end

class SpotSearchTag < ApplicationRecord
  belongs_to :spot
  belongs_to :search_tag
end

class SearchTag < ApplicationRecord
  has_many :cafe_search_tags
  has_many :spot_search_tags
end

このようにCafeとSpotそれぞれと、SeachTagとの間に中間テーブルを定義してあげないといけません。

さらにこの書き方だと、SearchTagから観たときに、それがSpotにあるのかCafeにあるのかをチェックしなければいけません。
例えばあるタグが付随するCafeとSpotを引っ張りたいときなどは大変です。

そこでポリモーフィック関連を使って、以下のように書くことができました。

class Cafe < ApplicationRecord
  has_many :search_tags, through: :destination_search_tags
  has_many :destination_search_tags, as: :destinationable
end

class Spot < ApplicationRecord
  has_many :search_tags, through: :destination_search_tags
  has_many :destination_search_tags, as: :destinationable
end

class DestinationSearchTag < ApplicationRecord
  belongs_to :destinationable, polymorphic: true
  belongs_to :search_tag
end

class SearchTag < ApplicationRecord
  has_many :destination_search_tags
end

参考サイト

Active Record の関連付け - Railsガイド
Active Recordが提供するすべての関連付け機能(アソシエーション)について解説します。
Railsのポリモーフィック関連とはなんなのか - Qiita
はじめにRailsのポリモーフィック(polymorphic、多態性)関連について、実装方法を説明している記事は見かけるのですが、実際これがどんなものでどんな時に便利なのかを説明している記事があま…
Railsのポリモーフィック関連 初心者→中級者へのSTEP10/25 - Qiita
#Railsのポリモーフィック関連はじめに今回はポリモーフィック関連についてです。はて、ポリモーフィックとは?の方ように、ポリモーフィックについて簡単に説明して、実際に実装してみたいと思います。…
ダック・タイピング - Wikipedia
オブジェクト指向の3大要素 まとめ - Qiita
「オブジェクト指向の三大要素」について再復習の機会があったのでまとめてみた。オブジェクト指向の三大要素とはオブジェクト指向言語がもつ代表的な3つの特徴のことで、「カプセル化、継承、ポリモーフィズ…
タイトルとURLをコピーしました