ポリモーフィック関連付けを使用し、抽象モデルを作成したのでそのアウトプットとなります。
前提条件
今回車を例に説明します。
これまでのサービスでは「SUV」の状態を管理するSuvClass
が存在しました。
しかし、新しい概念「スーパーカー」SuperCarClass
を導入することになりました。
そこで、抽象クラスCarClass
を作成し、SuvClass
、SuperCarClass
に従属させようと考えています。
※ そもそも設計に問題があるかもしれませんが、サンプルなのでお許しを。。
ポリモーフィック関連付けを使用した経緯
これから新たに増える可能性のある車の概念に対して、車を特定するユニークなid
が必要でした。
関連付け
関連付けは以下のようになります。
モデル
class Car < ApplicationRecord
belongs_to :carable, polymorphic: true
end
class Suv < ApplicationRecord
has_one :cars, as: :carable
end
class SupreCar < ApplicationRecord
has_one :cars, as: :carable
end
マイグレーション
class CreateCars < ActiveRecord::Migration[5.2]
def change
create_table :cars do |t|
t.references :carable, polymorphic: true
t.timestamps
end
end
end
このように関連付けすることで、Car
モデルのインスタンスから、親(Suv, SuperCar)のデータを取得できるようになります。
@car.carable
抽象クラス(Car)をどう活用していくのか?
親クラス(Suv
, SuperCar
)が作成されるタイミングで、Car
が作成されるようにします。
class SuperCarsController < ApplicationController
def create
super_car = SuperCar.new(super_car_params)
super_car.build_cars # <= これで Car が作成される。
super_car.save
end
end
Car
が作成されたことによって、以下のようにCar
のid
を指定することで、親のデータを取得できます。
@car = Car.find(params[:id])
@car.carable
このように実装することで、新たな車の概念(CompactCar
)などが登場しても、同様にCar
クラスに従属させるように関連付けすれば、ユニークなid
を取得できます。
まとめ
今回ポリモーフィック関連付けを初めて使用しましたが、便利だなという印象です。
しかし、外部キー制約(参照整合性制約)が使えなくなるなど問題点もあるので、そこは認識して導入を検討する必要がありそうです。