railsで作業している時にコントローラで処理をしてしまっていました。
コントローラは入口、モデルは現場です。入口で作業まですると混みます。だから作業は現場に寄せる。
この考えが腑に落ちたで記事にします。
⸻
-
変わりやすい所と、変わりにくい所を分ける
• 入口まわり(URL・認証・パラメータ・返し方)はよく変わります。
• 仕事の決まり(計算・在庫の合わせ方・状態の移り変わり)は長く使います。
• だから、決まりはモデルに置くと、仕様変更の影響が広がりにくくなります。 -
意味を近くに集める
• そのデータに関する「必ず守る決まり」「計算して出る値」「状態の移り変わり」は、そのデータのそばに置くと読みやすいです。
• まとまっていると、丸め方・単位・境界の考え方がすぐ見つかり、直す場所も分かりやすくなります。 -
同じことは一度だけ書く
• 同じ計算を、別の画面や別のAPIでも使うことが多いです。
• モデルの一か所に置けば、コピペせずに済み、直すときも一回で済みます。 -
テストがかんたんになる
• ネット経由のテストは遅くて不安定になりがちです。
• モデルに寄せれば、純粋な計算だけを速く確実にテストできます。どこが悪いのかの切り分けも楽です。 -
コンソールでその場で試せる
• rails console で、特定のデータに対してすぐ評価できます。
• 小さく再現して原因を見つけたり、データを直したりしやすくなります。 -
速さの調整を“近く”で決められる
• includes/preload をどう使うか、同じリクエストで何度も計算しないようにするか(メモしておくか)、必要ならキャッシュするか——こうした判断は、データの形を知っている層で決めるのが良いです。
• ロジックがモデルにあれば、こうした調整がやりやすくなります。 -
名前がそのまま意味になる
• order.total_cents や user.activate! のように、名詞.動詞の形だと読むだけで意図が分かります。
• チームで共通の言い回しができ、会話もスムーズになります。 -
処理の“ひとかたまり”の境目がはっきりする
• 計算は確実に決まるもの、外のサービスとのやり取りは不確実なものです。
• これを分けると、やり直しの設計(失敗時の戻し方)もシンプルになります。計算はモデル、外のやり取りや段取りはサービスに置きます。 -
手間に対する見返りが大きい
• 一度モデルにまとめると、新機能、管理画面、CSV、定期処理などで何度も使い回せます。
• 逆にコントローラに残すと、そのたびに書き直しが増えがちです。
⸻
設計の注意
• モデルが大きくなりそうなら小分けにする。 値だけの小さなクラス、検索用のクラス、表示の整え専用、段取り用のサービス……と分けます。モデルには「そのデータだけの決まり」だけを残します。
• サービスに寄せすぎない。 サービスは段取り(外のやり取り・複数のモデル・まとめて保存)に限ります。計算や決まりはモデルに残します。
• コールバックは最小限。 監査や通知などにとどめ、状態の変更は publish! のような明示のメソッドにします。
• テストは層ごとに分ける。 計算はモデル/値のテスト、外のやり取りはサービスでスタブ、リクエストのテストは経路と権限の確認だけにします。
• 名前で意図を伝える。 order.total_cents のように読めば分かる名付けにします。
• 少しずつ移す。 まずはコントローラから「委ねる」だけ作り、動く最小を通してから似た場所も同じ形に寄せます。
⸻
モデルに置かないほうがよい場面
• 複数のモデルをまたいで一気に進める段取り(例:在庫の確保 → 決済 → 出荷の依頼)。
• 画面の見た目だけの整え。
• 外のサービスとのやり取りそのもの(API 呼び出しやキューへの送信)。
⸻
ひと言でまとめ
変わりやすい“入口”から、変わりにくい“意味のある場所”へロジックを移します。読むのも直すのも速くなり、使い回しや性能調整、運用も楽になります。