LoginSignup
0
1

More than 1 year has passed since last update.

【Rails】 Formオブジェクトの使い方

Last updated at Posted at 2022-10-05

背景

Formオブジェクトめちゃめちゃ便利だな〜と思ったので、まとめました。
開発環境は「Rails7」です。

Formオブジェクトとは?

FormとModelの役割を分ける時に使用するオブジェクト

FormはModelに依存している。
※Form_withでもモデルを元にHTMLが生成されたり、、、

Modelに依存しないので、複数のモデルを更新する専用フォームとかが作れるよ〜 ⇦重要

Formオブジェクトを使うとき

  • 1つのフォームで複数のモデルを更新したいとき
  • 特定のフォームでしか行わない処理(らしい)

今回のケース

記事と画像(1:多)を投稿するフォームを作成する。

post.rb

class Post < ApplicationRecord
    belongs_to :user
    has_many :photos, dependent: :destroy
    validates :caption, presence: true
end

photo.rb

class Photo < ApplicationRecord
    belongs_to :post
    validates :image, presence: true
    mount_uploader :image, ImageUploader    #アップローダー
end

1. フォームオブジェクトの作成

フォームオブジェクトは、 app/formsに作成することが推奨されている
ファイル名 ***_form.rb

今回作成したフォームオブジェクト
Formオブジェクト内に、モデルへの保存が必要になる、属性・バリデーションを全て定義する

class PostPhotosForm
    include ActiveModel::Model      # モデルの機能を利用するために記載
    include ActiveModel::Attributes # モデルの機能を利用するために記載
    extend CarrierWave::Mount       # アップローダーの使用

    # 属性の定義
    attribute :caption, :string     # Post
    attribute :user_id, :integer    # Post
    attribute :image, :string       # Image

    # Carrier Wave アップローダー
    mount_uploader :image, ImageUploader

    # バリデーション
    validates :caption, presence: true
    validates :image, presence: true
    validates :user_id, presence: true

    # レコードの保存
    def save
        # bool値を返す
        return false if invalid?

        # トランザクション処理
        ActiveRecord::Base.transaction do
            post = Post.create!(caption: caption, user_id: user_id)
            post.photos.build(image: image).save!
        end
    end
end

2. ビューの作成

modelにFormオブジェクトのインスタンスを指定

 <%= form_with(model: @post_photos, url: posts_path, local: true, data:{turbo: false}) do |f| %>
  <%= f.label :caption %>
  <%= f.text_field :caption %>
  <%= f.file_field :image %>
  <%= f.submit "投稿", class: "btn btn-primary" %>
<% end %> 

3. コントローラー

ストロングパラメータを定義

class PostsController < ApplicationController
    before_action :authenticate_user!

    # 記事の作成画面
    def new
        @post_photos = PostPhotosForm.new
    end

    # 記事作成処理
    def create
        @post_photos = PostPhotosForm.new(post_photos_params)

        if @post_photos.save
            redirect_to root_path, flash: {notice: '投稿が保存されました'}
        else
            flash[:alert] = "投稿に失敗しました"
            render :new, status: :unprocessable_entity
        end
    end

    private
    # PostPhotosForm ストロングパラメータ
    def post_photos_params
        params.require(:post_photos_form).permit(:caption, :image).merge(user_id: current_user.id)
    end
end

補足(バリデーションメッセージ)

通常のモデルと同様の記載方法

<ul>
    <% @post_photos.errors.full_messages.each do |error| %>
      <li><%= error %></li>
    <% end %>
</ul> 

まとめ

便利!

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