QA@IT

RailsのActiveRecordで1つのテーブルに対して複数のモデルをひもづける方法はありますか?実装方法としてありですか?

3534 PV

入力チェックにバリエーションがあり、多人数で開発するような場合を想定しています。
例えば伝票入力機能を実装する場合に、仮入力、予約、注文済み、配送などステータスごとに入力チェックが異なり、モデルを使用する画面、コントローラーも異なり、複数人で並行して開発を行うような場合です。
伝票テーブルに対して仮入力伝票モデル、予約伝票モデルのような実装をする方法はありますか?
検索など共通する処理もあるので、ジェネレーションギャップパターンで実装するべきなど、セオリーはありますでしょうか?

回答

(STIで。という回答も少し関連)

ステータス遷移をするリソースで、多人数で開発を行うからモデルのコードを分けたいという話だと理解しました。

STIの場合typeを変更するのがめんどくさい経験があるのであまりおすすめはしないです。
この方向で解決したいのであればSTIではなく、普通に複数のモデルで同じテーブルを参照してしまえばいいと思います。
(つまり、typeカラムを作らないでおけばいい)

default_scopeとbefore_saveをうまくやりくりすれば、ステータス遷移を伴うsaveも可能ですが、STIでtypeを変更するのがめんどくさいのと同様に、save実行後にインスタンスのクラスが変わるわけではなく、再度findする必要があることに注意が必要です。
(saveした瞬間にクラスまで変更できるようなやり方は申し訳ないけどわからないです)

そもそも解決したい問題が「多人数で開発を行うからモデルのコードを分けたい」なので、STIで言うところの各子クラス相当の処理をmoduleとして記述しておき、そのモデルではincludeのみ行うのが常套手段のような気がします。

編集 履歴 (0)
  • なるほど、ありがとうございます -

ActiveRecord が提供している、有名なパターンは STI(Single Table Inheritance) です。
伝票テーブルが、仮入力伝票モデル、予約伝票モデルで必要になる全カラムをもつことになります。

編集 履歴 (0)
  • STIの場合はレコードが他のクラスへ遷移することはできなさそうですがいかがでしょうか -
  • あるレコードを仮入力伝票モデルに対応づけていたけど、予約伝票モデルに対応づけることにした、といった変更は type カラムの値を変更すれば可能なのかもしれませんが、自分はそういう使い方をしたことはありません。 -
  • ありがとうございました -
  • 以前、Rails2系を使っている時にtypeを書き換えたい要件があって対応しましたが、強引にupdateして、必要があればfindし直すような形のものでした。saveが使えないので、他のクラスに遷移することはあまり考えられていない気がしています。 -
  • > tazyamah さん

    そうなのですね。情報ありがとうございます。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。