Railsでももっとカジュアルにapp/models配下にクラス作っていいんじゃないかなーと思っているんだけどどうなんでしょうか
Railsのプロジェクトやってると、app/models
には ActiveRecord
だけ、それ以外のオブジェクトは app/services
とか app/forms
層みたいなところに定義しないといけないと思っている人がそれなりに多い気がする。
個人的には app/models
配下に責務を分けたActiveRecordでないクラスを作っていくのはむしろ積極的にやるべきだと思っている。むしろそうしないとXX層みたいなものを導入したとしても、本来モデルの振る舞いとして表現されるべきものが手続き的に書かれてしまったり、新しく導入したXX層の処理がファットになっていってしまったりするのではなかろうか。(ActiveRecord
のクラスと、そうじゃないプレーンなRubyクラスが app/models
に交じるのが気持ち悪いという意見はまあ理解できるけど)
たとえば
たとえば以下のようなクラスがあったとする。
class User < ApplicationRecord def nanka_fukuzatu_na_shori if user.hoge? private_na_method_a private_na_method_c else private_na_method_b end end private def private_na_method_a # なんかの処理 end def private_na_method_b # なんかの処理 end def private_na_method_c # なんかの処理 end end
見るとnanka_fukuzatu_na_shori
と private_na_method_a~c
は明らかに関連をもつひとまとまりの処理なので、こいつらを実行する実態はUserクラスではないところにあっても良さそうな気がする。
これを User::NankaFukuzatsuNaShoriHandler
を作って、そちらに責務を分けてみる
# app/models/user/nanka_fukuzatu_na_shori.rb class User:: NankaFukuzatsuNaShoriHandler attr_reader :user def initialize(user:) @user = user end def perform if user.hoge? private_na_method_a private_na_method_c else private_na_method_b end end private def private_na_method_a # なんかの処理 end def private_na_method_b # なんかの処理 end def private_na_method_c # なんかの処理 end end
( nanka_fukuzatu_na_shori
とかいう適当な名前で書き始めてしまったので User::NanakaFukuzatuNaShoriHandler#perform
みたいにしちゃったけど、Handler
、 Perform
みたいな抽象的な名前は避けたほうが良さそう)
Userクラスはこんな感じになる。
class User < ApplicationRecord def nanka_fukuzatu_na_shori nanka_fukuzatu_na_shori_handler.perform end private def nanka_fukuzatu_na_shori_handler @nanka_fukuzatsu_na_shori_handler ||= User::NankaFukuzatsuNaShoriHandler.new(user: user) end end
基本的にはこんな感じで責務を分割していって、あるモデルの振る舞いとして定義するのが微妙なものだけそれこそXXX層みたいなの作ってやるのがいいんじゃないかと最近は思うんだけど、各社どうなっているんだろう。
- Rails Wayから外れるので止めたほうがよい
- Concern使えば?
みたいな意見はありそうかなと思っています。