0
0

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 1 year has passed since last update.

【Rails】ポリモーフィックを使用した抽象モデルの作成

Posted at

ポリモーフィック関連付けを使用し、抽象モデルを作成したのでそのアウトプットとなります。

前提条件

今回車を例に説明します。
これまでのサービスでは「SUV」の状態を管理するSuvClassが存在しました。
しかし、新しい概念「スーパーカー」SuperCarClassを導入することになりました。
そこで、抽象クラスCarClassを作成し、SuvClassSuperCarClassに従属させようと考えています。

※ そもそも設計に問題があるかもしれませんが、サンプルなのでお許しを。。

ポリモーフィック関連付けを使用した経緯

これから新たに増える可能性のある車の概念に対して、車を特定するユニークなidが必要でした。

関連付け

関連付けは以下のようになります。

モデル

sample.rb
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)のデータを取得できるようになります。

sample.rb
@car.carable

抽象クラス(Car)をどう活用していくのか?

親クラス(Suv, SuperCar)が作成されるタイミングで、Carが作成されるようにします。

SuperCarsController.rb
class SuperCarsController < ApplicationController
  def create
    super_car = SuperCar.new(super_car_params)
    super_car.build_cars # <= これで Car が作成される。
    super_car.save
  end
end

Carが作成されたことによって、以下のようにCaridを指定することで、親のデータを取得できます。

sample.rb
@car = Car.find(params[:id])
@car.carable

このように実装することで、新たな車の概念(CompactCar)などが登場しても、同様にCarクラスに従属させるように関連付けすれば、ユニークなidを取得できます。

まとめ

今回ポリモーフィック関連付けを初めて使用しましたが、便利だなという印象です。
しかし、外部キー制約(参照整合性制約)が使えなくなるなど問題点もあるので、そこは認識して導入を検討する必要がありそうです。

参考資料

Railsガイド
SQLアンチパターンを読んで (ポリモーフィック関連について)

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?