カテゴリ: Rails 更新日: 2025/12/28

Railsのサービスオブジェクトとフォームオブジェクトを完全解説!初心者でもわかるapp/servicesの配置ルール

サービス/フォーム/クエリオブジェクト:app/services 等の配置ベストプラクティス
サービス/フォーム/クエリオブジェクト:app/services 等の配置ベストプラクティス

先生と生徒の会話形式で理解しよう

生徒

「Railsのプロジェクトを作ったら、コントローラやモデル以外にもファイルを置く場所があるって聞いたんですが、本当ですか?」

先生

「そうですね。実はRailsでは、処理を整理して管理しやすくするために、サービスオブジェクトやフォームオブジェクト、クエリオブジェクトといった設計パターンを使うことが多いんです。」

生徒

「名前だけで難しそうです…。具体的にどんなときに使うんですか?」

先生

「大丈夫です!今日は初心者でも理解できるように、例え話を交えながら、app/servicesなどに置くファイルのベストプラクティスを解説していきましょう。」

1. サービスオブジェクトとは?

1. サービスオブジェクトとは?
1. サービスオブジェクトとは?

Railsのサービスオブジェクトとは、アプリの中で「ひとつの大きな処理」をひとまとめにしたクラスのことです。例えば、ユーザー登録のときに「メール送信」「ログ保存」「外部APIとの連携」など複数の処理をまとめて管理したいときに便利です。

例えるなら「家事代行サービス」のようなもので、いろいろな仕事をまとめて依頼できる存在です。コントローラやモデルに複雑な処理を押し込めるのではなく、サービスオブジェクトに移すことで、コードがスッキリ読みやすくなります。


# app/services/user_signup_service.rb
class UserSignupService
  def initialize(user_params)
    @user_params = user_params
  end

  def call
    user = User.create(@user_params)
    WelcomeMailer.send_mail(user).deliver_later
    user
  end
end

このようにapp/services/に配置するのが一般的です。

2. フォームオブジェクトとは?

2. フォームオブジェクトとは?
2. フォームオブジェクトとは?

フォームオブジェクトは、複数のモデルにまたがる入力フォームを扱うときに使うクラスです。例えば「ユーザー登録」と同時に「住所情報」も登録したい場合、通常はUserモデルとAddressモデルを同時に操作する必要があります。そのままだとコントローラが複雑になってしまうため、フォームオブジェクトを用意します。

イメージ的には「受付係」がいて、ユーザーと住所の書類を一度にまとめて処理してくれる感じです。Railsではapp/forms/ディレクトリを作って配置することが多いです。


# app/forms/user_registration_form.rb
class UserRegistrationForm
  include ActiveModel::Model
  attr_accessor :name, :email, :password, :address

  def save
    user = User.create(name: name, email: email, password: password)
    Address.create(user: user, address: address)
  end
end

このようにフォームオブジェクトを使うと、複雑な入力処理をわかりやすくまとめることができます。

3. クエリオブジェクトとは?

3. クエリオブジェクトとは?
3. クエリオブジェクトとは?

クエリオブジェクトは、データベースに対する検索処理をまとめるクラスです。たとえば「アクティブなユーザーを一覧する」「特定の条件に合う注文を探す」といった複雑な検索ロジックをモデルに書くと、コードが読みにくくなります。

そこで、検索専用のクラスをapp/queries/に配置して整理します。クエリオブジェクトは「探偵」のような役割を持ち、必要な情報を的確に探してくれます。


# app/queries/active_users_query.rb
class ActiveUsersQuery
  def initialize(relation = User.all)
    @relation = relation
  end

  def call
    @relation.where(active: true).order(created_at: :desc)
  end
end

こうして分けることで、検索処理がスッキリ整理され、テストもしやすくなります。

4. ディレクトリ構造のベストプラクティス

4. ディレクトリ構造のベストプラクティス
4. ディレクトリ構造のベストプラクティス

サービスオブジェクトやフォームオブジェクト、クエリオブジェクトを導入するときは、専用のディレクトリを作成するのがおすすめです。Railsの標準には含まれていませんが、多くの開発現場では以下のような配置をしています。


my_app/
├─ app/
│  ├─ controllers/
│  ├─ models/
│  ├─ views/
│  ├─ services/   (大きな処理をまとめるクラス)
│  ├─ forms/      (フォーム入力をまとめるクラス)
│  └─ queries/    (検索処理をまとめるクラス)
├─ config/
│  ├─ routes.rb
│  └─ initializers/
└─ db/

このようにフォルダを整理することで、Railsのアプリが大きくなっても迷子にならずに開発を進められます。

5. どんな効果があるのか?

5. どんな効果があるのか?
5. どんな効果があるのか?

初心者の方にとって「フォルダを分けるだけで本当に意味があるの?」と思うかもしれません。しかし、この設計ルールを意識するだけで、以下のメリットがあります。

  • 読みやすさ:役割ごとにファイルが分かれるので、他の人が見ても理解しやすい。
  • 保守性:後から機能を追加したり修正したりするときに、どこを直せばいいかすぐわかる。
  • 再利用性:同じ処理を別の場所でも簡単に呼び出せる。

つまり、サービス/フォーム/クエリオブジェクトを適切に配置することは、Railsアプリを長く育てるための「掃除や片付け」と同じで、とても大事な習慣です。

まとめ

まとめ
まとめ

Railsにおけるサービスオブジェクト、フォームオブジェクト、クエリオブジェクトは、アプリケーションの構造を整理し、責務を分離するためにとても重要な役割を果たします。初心者の段階では、コントローラやモデルの中に処理を詰め込みすぎてしまい、どこで何をしているのか見えなくなっていくことがよくあります。しかし、処理の種類ごとに専用のクラスを定義して整理することで、アプリケーション全体の一貫性が保たれ、長く運用しても壊れにくく、拡張しやすい構造を作り上げることができます。サービスオブジェクトはひとまとまりの大きな処理、フォームオブジェクトは複数モデルにまたがる入力対応、クエリオブジェクトは複雑な検索ロジックと役割が明確であり、これらの特徴を理解することで、Rails開発の品質が飛躍的に向上します。

特に、Railsアプリが大きくなってきたときには、処理をどこに書くか迷いやすくなります。モデルが肥大化し「Fat Model」と呼ばれる状態になったり、コントローラが長くなりすぎて「Fat Controller」になってしまうこともあります。そこで、サービスオブジェクトを導入することで、ビジネスロジックが明確な場所に移され、読みやすさと保守性が高まります。また、フォームオブジェクトは複数モデルの同時保存に必要なロジックをきれいにまとめるのに非常に便利で、現実的なプロジェクトでは意外と利用機会が多いです。そしてクエリオブジェクトは、頻繁に使われる複雑な検索条件を共通化し、アプリ全体で使い回せる形にすることで、DRY(Don't Repeat Yourself)の原則を自然に守れる点が大きな魅力です。

これらのファイルの配置場所として、app/servicesapp/formsapp/queries を作成することは非常に合理的です。Rails標準には含まれていませんが、多くの現場で当たり前のように採用されており、ディレクトリ構造が明確になることで、プロジェクトを初めて触る人にとっても理解しやすい構成が実現できます。また、これらのクラスはテストしやすいという利点もあり、RSpecなどを使ったテストコードとの相性も良い構造となっています。

以下は、今回学んだ内容を整理したサンプルコードです。サービスオブジェクト、フォームオブジェクト、クエリオブジェクトの書き方の違いや特徴が比較できるよう、記事と同じタグ形式でまとめています。

サービスオブジェクトの例


# app/services/order_create_service.rb
class OrderCreateService
  def initialize(order_params, user)
    @order_params = order_params
    @user = user
  end

  def call
    order = @user.orders.create(@order_params)
    NotificationMailer.order_mail(order).deliver_later
    order
  end
end

フォームオブジェクトの例


# app/forms/profile_update_form.rb
class ProfileUpdateForm
  include ActiveModel::Model

  attr_accessor :user, :name, :email, :profile_text

  def save
    user.update(name: name, email: email, profile_text: profile_text)
  end
end

クエリオブジェクトの例


# app/queries/recent_orders_query.rb
class RecentOrdersQuery
  def initialize(relation = Order.all)
    @relation = relation
  end

  def call
    @relation.where("created_at >= ?", 7.days.ago).order(created_at: :desc)
  end
end

このようにコードを役割ごとに整理することで、開発体験が大きく改善されます。Railsは非常に柔軟なフレームワークであり、プロジェクト規模やチームメンバーの人数に応じて最適な構造を作りやすいことが特徴です。サービスオブジェクト・フォームオブジェクト・クエリオブジェクトを適切に配置すれば、コードが自然に整理され、理解しやすく、再利用しやすい形になります。初心者のうちは慣れないかもしれませんが、何度も使ううちに自然と身につき、複雑なアプリケーションでも迷わず開発を進められるようになります。

先生と生徒の振り返り会話

生徒:「サービスオブジェクトやフォームオブジェクトがあると、処理が整理される理由がよくわかりました!」

先生:「そうですね。責務を分けておくと後からの修正がとても楽になります。Railsは柔軟なので、こうした設計パターンを取り入れることでコード品質が上がりますよ。」

生徒:「特にフォームオブジェクトは実際の開発で役立ちそうですね。複数モデルをまとめて保存するのがスッキリ書けるのが驚きでした。」

先生:「クエリオブジェクトも便利ですよ。モデルに検索ロジックを書きすぎるとすぐに読みにくくなるので、専用クラスにまとめると再利用性も高まります。」

生徒:「app/services や app/forms にディレクトリを作って整理する理由も理解できました。構造が明確だと安心して開発できますね。」

先生:「その通りです。コードの整理はアプリケーションを長く育てるための基礎です。今のうちから意識しておくと、確実にレベルアップできますよ。」

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

Railsのサービスオブジェクトとは何ですか?初心者向けに教えてください。

Railsのサービスオブジェクトとは、1つの大きな処理をまとめて行うクラスのことで、主にapp/servicesディレクトリに配置します。ユーザー登録時のメール送信やログ出力、外部API連携など、複雑な処理をまとめて整理するために使われます。
関連記事:
カテゴリの一覧へ
新着記事
New1
データベース
SQLの処理が遅くなる原因とは?初心者向けにデータベースパフォーマンス最適化を完全解説
New2
Ruby
RubyのネストHash操作を徹底解説!digとtransformメソッドで複雑なデータも楽々
New3
Rails
Railsインデックス設計の極意!爆速サイトを作るためのスキーマ設計ガイド
New4
データベース
SQLのCOMMITとROLLBACKとは?トランザクション操作を初心者向けに完全解説
人気記事
No.1
Java&Spring記事人気No1
Ruby
PATHと環境変数の正しい設定!Windows・Mac・Linux別チェックリスト付き
No.2
Java&Spring記事人気No2
Rails
Railsで日本語と時刻の設定をしよう!初心者でも安心のlocale/zone初期設定チートシート
No.3
Java&Spring記事人気No3
Ruby
Rubyのハッシュを徹底比較!シンボルキーと文字列キーの違いと使い分け
No.4
Java&Spring記事人気No4
Rails
Railsマイグレーションの型選びを完全ガイド!初心者が迷わないカラム設計
No.5
Java&Spring記事人気No5
Ruby
WindowsでRubyをインストールする方法!RubyInstallerとMSYS2を使った完全ガイド
No.6
Java&Spring記事人気No6
Rails
RailsモデルとActive Record基礎|ID戦略を完全理解!AUTO INCREMENT・UUID・ULIDの比較と導入手順
No.7
Java&Spring記事人気No7
データベース
ACID特性とは?データベーストランザクションの信頼性を初心者向けに徹底解説
No.8
Java&Spring記事人気No8
Rails
RailsモデルとActive Record基礎|クエリログの読み方を理解してEXPLAIN・joins・includesの違いを学ぼう