LoginSignup
29
21

More than 1 year has passed since last update.

[Rails]大変便利なFormオブジェクトはご存知でしょうか?

Posted at

はじめに

突然ですが、「Formオブジェクト」というものを知っていますでしょうか?
便利なものなのですが、意外と使われていない人もいるかと思います。
これを知ってることで、開発がよりスムーズに進無こと間違いなしです!!

Formオブジェクトとは?

モデルとフォームの責務を切り分けられる事で、単体のモデルに依存しない場合や、フォーム専用の特別な処理をモデルに書きたくない場合に用いたりします。

Railsのフォームは基本的にモデルに依存しています。例えば1つのフォーム送信で複数のモデルの更新をしたい場合バリデーションの責務が曖昧なものとなり、可読性も低下するため、責務を明確にするということで使います。
1つのフォームで複数モデルの操作をしたいときにForm Objectを使うと、処理がすっきりかける。またログインに関する処理など、特定のフォームでしか行わない処理もForm Objectに書くと良い。

メリット

  • modelとformで入力値の検証かビジネスロジックの検証かを分別することができる。
  • 一度のフォーム送信時に複数の ActiveRecordモデルを更新しやすくできる。
  • 同じ処理をmodelに対して行う際にForm層の再利用が可能になる。
  • ActiveRecordと同じバリデーションを使うことができる。
  • Formオブジェクトにパラメーターを渡すことができるためエラーメッセージを戻す処理が書きやすい。
  • ビジネスロジックをcontroller/viewから切り離せる(単一責務の状態)。

ユースケース

  • ユーザからの問い合わせフォームの実装
  • 1つの記事に複数の画像を保存する処理(has_manyな関係)
  • ユーザーのログイン処理
  • APIのパラメーターに対するバリデーション

使い方

1.appディレクトリにformsディレクトリを作成

$ mkdir app/forms

2.利用したいフォームのFormオブジェクトを作成

$ touch app/forms/sample_form.rb

3.作成したファイルに、バリデーションや使用するメソッドを記述していく。

app/forms/sample_form.rb
class SampleForm
  include ActiveModel::Model # 通常のモデルのようにvalidationなどを使えるようにする
  include ActiveModel::Attributes # ActiveRecordのカラムのような属性を加えられるようにする

  attribute :first_name, :string
  attribute :last_name, :string
  attribute :email, :string
  attribute :body, :string

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

  def save
    処理
  end
end

コントローラーにも記述する。

class SamplesController < ApplicationController
...

  def new
    @sample = SampleForm.new
  end

  def create
    @sample = SampleForm.new(sample_params)
    if @sample.save
      redirect_to :samples, notice: 'サンプル情報を作成しました。'
    else
      render :new
    end
  end

  private

  def sample_params
    params.require(:sample).permit(:first_name, :last_name, :email, :body)
  end
end

終わりに

開発の規模が大きくなるほどに、コントローラーやモデルは膨大になり、ごちゃごちゃしてきます。
そういう時に、処理ごとに切り分けてまとめることは可読性も上がってとても重要なことです。
状況を見て利用してみても良いかなと思います!

参考

【Rails】FormObjectを使ってほしい

RailsのForm Objectについて

【Rails】Form Objectを使ってModelに依存しないFormを作成する

【Ruby on Rails】フォームオブジェクトを使って検索キーワードをcontrollerに送る

29
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
21