【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