Help us understand the problem. What is going on with this article?

【Rails】FormObjectを使ってほしい

More than 1 year has passed since last update.

RailsでForm Objectを導入はするのは今となっては珍しくもないかと思います。
それでも組織やチームに文化がない状態で投入してしまうと
それ自体が負債となる場合もあるんだろうなと感じたところもありました。

今回は普及のためにもForm Objectを作る方法を紹介してみようと思います

Form Objectとは?

単体のモデルに依存しない場合や
フォーム専用の特別な処理をモデルに書きたくない場合に用いたりします。

例えば1つのフォーム送信で複数のモデルの更新をしたい場合
バリデーションの責務が曖昧なものとなり関心事が多くなり
忘れたときに改めて解読するのも嫌になってしまうことがあります。
そのためにも責務を明確にするのは個人的には大切かなと。

責務ばかりを気にしていたら速度が失われてしまうため
状況を見つつ使い分けはしたいところ。。

メリットはあるか?

どんなに便利な手法だとしても
用法用量を守って触らないとろくな事にならないのはお察し。。
気を取り直してどういうメリットが有るかですが

  • ActiveRecordと同じバリデーションを使うことができる
  • Form Objectにパラメーターをそのまま渡すことができるためエラーメッセージを戻す処理が書きやすい
  • 責務がモデルとは言い切れないビジネスロジックをcontroller/viewから切り離せる
    • いわゆる単一責務の状態となりやすい

ユースケース

  • ユーザからの問い合わせを受け付けるフォームを実装したい
  • 未登録ユーザは氏名とメールアドレス、内容の取得と通知を目的とする

最初はこれでよかったのかもしれない。
ただ実際にふたを開けてみたら
登録済みのユーザはIDと内容だけがいいとか
そもそも入力項目を増やしたいだとか経験がありますよね。

Form

まずは今回の用件以外の関心ごとを減らすためにも
Form Objectの定義します

app/forms/contact_form.rb
class ContactForm
  include ActiveModel::Model

  attr_accessor :first_name, :last_name, :email, :body

  validates :first_name, presence: true
  validates :last_name, presence: true
  validates :email, presence: true
  validates :body, presence: true

  def save
    return false if invalid?
    # 保存, 通知, ロギング等
    true
  end
end

Controller

次にControllerの処理です。
Form Objectにロジックを寄せたおかげで
scaffoldで作られようなシンプルな形を維持できます。

app/controllers/contact_controller.rb
class ContactController < ApplicationController

  def index
    # お問い合わせ一覧
  end

  def new
    @contact = ContactForm.new
  end

  def create
    @contact = ContactForm.new(set_params)
    if @contact.save
      redirect_to :contacts, notice: 'お問い合わせを受け付けました。'
    else
      render :new
    end
  end

  private

  def set_params
    params.require(:contact).permit(:first_name, :last_name, :email, :body)
  end
end

Routes

config/routes.rb
Rails.application.routes.draw do
  resources :contacts, only: [:index, :new, :create]
end

まとめ

Form Objectは一つの選択肢ですが
導入もしやすくわかりやすいのはいいところではないかと思います。
現実はこんなにシンプルには行きませんが手段として知っているだけでも選択肢が増えるかと思います。

複数人で開発を行う場合は
レイヤーの立場を明確にするなど
認識を合わせてからの導入が良いのだろうという反省のお話でした。

9ro
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした