【Rails】DBのテーブルに紐づかないモデルってどう作れば良いのん?
概要
DBに紐づかない、ただどこからでも利用できるユーティリティが欲しいときに
class Sample < ApplicationRecord
def self.test
'test'
end
end
といった具合にモデルを作成していたんですが、これだけのためにApplicationRecord
を継承するのは絶対に違うよな〜と思っていました。
というわけで、こういうときどうすればいいのかGPT-4に聞いてみました。
結論
ApplicationRecord
を継承する代わりに、include ActiveModel::Model
を設定したモデルを作れば良い。
やりとり
質問:
SampleはDBにテーブルとして存在しないのですが、Railsで
class Sample < ApplicationRecord
def self.test
return "test"
end
end
をより適切に直す方法はありますか?
答え:
Railsで実際のデータベーステーブルに関連付けられていないモデルを定義するには、ActiveModelモジュールを使用します。これにより、データベーステーブルがなくても、モデルのような構造を持つクラスを作成することができます。
以下のようにSampleクラスを書き換えてみてください。
class Sample
include ActiveModel::Model
def self.test
return "test"
end
end
include ActiveModel::Model
が追加されていることに注意してください。これにより、SampleクラスはActiveModelモジュールの機能を取り込み、Railsのモデルのような振る舞いをすることができます。ただし、データベースのテーブルとの関連付けは持ちません。
この変更により、SampleクラスはApplicationRecord
から継承されず、データベーステーブルの存在を前提としないようになります。これで、Sample.test
メソッドを使用する際に問題がなくなるはずです。
質問:
Sampleのようなinclude ActiveModel::Modelが設定されたファイルと、ApplicationRecordを継承したファイルは、ディレクトリでどう分けるべきでしょうか?
答え:
Railsアプリケーションでは、通常app/models
ディレクトリにモデルを格納します。ただし、ActiveModel::Model
を使用したモデルとApplicationRecord
を継承したモデルを分ける場合、ディレクトリ構造を整理することが役立ちます。
以下のようにディレクトリを分けることが一般的です:
app/models
ディレクトリには、ApplicationRecord
を継承した通常のActiveRecord
モデルを格納します。これらのモデルはデータベーステーブルに関連付けられています。
app/models/non_database
(またはapp/models/active_models
やapp/models/non_persistent
など、適切な名前で)ディレクトリを作成し、ActiveModel::Model
を使用したモデルを格納します。これらのモデルはデータベーステーブルに関連付けられていません。
この構造にしたがってディレクトリを分けることで、プロジェクトの構造が整理され、非データベースモデルとデータベースモデルを簡単に識別できます。
ただし、Railsが新しく作成したディレクトリを自動的に読み込むようにするために、オートロードのパスを設定する必要があります。
config/application.rb
ファイルを開いて、Application
クラスのconfig
ブロック内に、以下のように新しいディレクトリを追加してください。
config.autoload_paths += %W(#{config.root}/app/models/non_database)
これにより、Railsはapp/models/non_database
ディレクトリ内のファイルも自動的に読み込むようになります。この変更を反映させるために、Railsアプリケーションを再起動してください。
この方法で、ActiveModel::Model
を使用したモデルとApplicationRecord
を継承したモデルを適切に分けることができます。
Discussion