はじめに
突然ですが、「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.作成したファイルに、バリデーションや使用するメソッドを記述していく。
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を使ってほしい]
(https://qiita.com/9ro/items/10e3676741e09ffb98bb)
[RailsのForm Objectについて]
(https://zenn.dev/d0ne1s/scraps/303a255d892ab0)
[【Rails】Form Objectを使ってModelに依存しないFormを作成する]
(https://tech.mof-mof.co.jp/blog/rails-form-object/)
[【Ruby on Rails】フォームオブジェクトを使って検索キーワードをcontrollerに送る]
(https://qiita.com/kumackey/items/4f8f0cd39d02299d74ed)