0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Formオブジェクトパターンについて

Posted at

#はじめに
Formオブジェクトパターンについて、簡潔にまとめてみました。
細かい部分の説明は省略していますが、大まかな概要についてはこの記事で理解ができるかと思います

#Formオブジェクトパターンとは

Formオブジェクトパターンとは、Railsの開発における実装パターンのことで、有名なものとして、1つのフォームから複数のモデルを操作する際に使います。

もう少しイメージしやすくすると、例えば個人情報に関するモデルと、商品情報に関するモデルの合体版モデルを擬似的に作成するといった感じです。

#メリットはなんなのか?

例えば、1つのフォームから個人情報と商品情報を入力させるとします。このとき、送られた情報は個人情報モデルのバリデーションと商品情報のバリデーション、それぞれで処理を行います。この時点で、すでに非効率ですが、例えば個人情報モデルでも商品情報モデルでもバリデーションの通過ができずエラーが発生したときに、
それぞれのエラーメッセージを表示させないとダメです。
これはめんどくさい…

そんな時に、合体版のようなモデル、Formオブジェクト使えば、バリデーションなどの処理は一括だが保存の際はそれぞれのDBに保存してくれるわけです。

#実際に作成してみよう

以下に2つのモデルがあるとします

user.rb

class User < ApplicationRecord

  has_many :items

  validates :name,presence:true
  # 数字3桁、ハイフン、数字4桁の並びのみ許可する
  validates :postal_code, presence: true, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "is invalid. Include hyphen(-)"}
  
item.rb

class User < ApplicationRecord
  belongs_to :user

  validates :item_name,presence:true

これら2つのモデルのまえに、合体版のようなモデル
user_item.rbを作成します。

user_item.rb

class UserItem
  include ActiveModel::Model
  attr_accessor :name,:postal_code,:item_user
  

  def save
    User.create(user: user,:postal_code: postal_code)
   Item.create(item_name:item_name)
  end
end

クラスにActiveModel::Modelをincludeすると、そのクラスのインスタンスはActiveRecordを継承したクラスのインスタンスと同様に form_with や render などのヘルパーメソッドの引数として扱え、バリデーションの機能を使用できるようになります。

なお、元々のモデルに記載したvalidatesは必要ないので削除しましょう。

このように、Formオブジェクトを使用することで、一括でバリデーションをかけることができます。

#おわりに

用事帰りに車の中で執筆しました。
とても酔いましたが、自分でも新しい発見があったのでアウトプット大事ですね。

誰かのためになれば嬉しいです

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?