2
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?

はじめに

Railsでnamespace付きモデルクラスを使用してSTI(Single Table Inheritance)を実現する場面に何度か遭遇していますが、そのたびに調べ直してしまっているのでまとめようと思います。

概要

Railsにおいて愚直にnamespaceがついたモデルクラスで、STI(Single Table Inheritence)をしようとすると以下のような挙動になります。

  • Read
    • 検索条件のtypeカラムにnamespaceを含めた定数名が入る
  • Write
    • typeカラムにnamespaceを含めた定数名が保存される
class Namespaced::Vehicle < ApplicationRecord; end
class Namespaced::Car < Namespaced::Vehicle; end
class Namespaced::Airplane < Namespaced::Vehicle; end

例えば、上記のようなnamespace付きモデル構成でSTIを利用するとします。
この場合、ActiveRecord越しにRead/Writeすると以下のようなクエリが発行されます。

app(dev)> Namespaced::Car.create(name: "lamborghini")
  TRANSACTION (0.4ms)  BEGIN
  Namespaced::Car Create (6.1ms)  INSERT INTO `vehicles` (`name`, `type`, `created_at`, `updated_at`) VALUES ('lamborghini', 'Namespaced::Car', '2024-09-17 14:30:48.257055', '2024-09-17 14:30:48.257055')
  TRANSACTION (3.9ms)  COMMIT

app(dev)> Namespaced::Car.all
  Namespaced::Car Load (3.4ms)  SELECT `vehicles`.* FROM `vehicles` WHERE `vehicles`.`type` = 'Namespaced::Car' /* loading for pp */ LIMIT 11

大抵の場合、このnamespace付きで扱うのは都合が悪いはずです。

解決策

基底クラスにself.store_full_sti_class = falseを設定することで、namespaceを省略して扱うことができます。

関連するPRは以下です。

実装例

class Namespaced::Vehicle < ApplicationRecord
  self.store_full_sti_class = false
end

class Namespaced::Car < Namespaced::Vehicle; end
class Namespaced::Airplane < Namespaced::Vehicle; end
app(dev)> Namespaced::Car.create(name: "lamborghini")
  TRANSACTION (0.2ms)  BEGIN
  Namespaced::Car Create (3.7ms)  INSERT INTO `vehicles` (`name`, `type`, `created_at`, `updated_at`) VALUES ('lamborghini', 'Car', '2024-09-17 14:43:39.617122', '2024-09-17 14:43:39.617122')
  TRANSACTION (2.0ms)  COMMIT

app(dev)> Namespaced::Car.all
  Namespaced::Car Load (1.3ms)  SELECT `vehicles`.* FROM `vehicles` WHERE `vehicles`.`type` = 'Car' /* loading for pp */ LIMIT 11
2
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
2
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?