0
0

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 1 year has passed since last update.

【Rails6】親子関係のモデルに対して一度に値を入力する多分最もシンプルな方法【fields_for】

Posted at

どうした?

RailsでToDoアプリを開発しています。
ToDoリストを作成する時、

  • 親モデル: Category
  • 子モデル: Todo

を1つの動作で同時に作成する方法を調べたので、そのアウトプットです。

目標物の確認

今回作成するアプリはcategories/indexページにて新規投稿します。
新規投稿エリアにはcategory.titletodo.contentの記入欄を用意し、「投稿」ボタンを1つ押すだけで両方のモデルに対してcreateされるようにします。

ToDoApp_設計書.png

動作環境

$ ruby -v
=> ruby 3.0.2

$ rails -v
=> rails 6.1.7

方法

Model

本アプリでは親モデルにCategory, 子モデルにTodoを指定しています。

Categoryモデル

class Category < ApplicationRecord
  # 親子関係の設定
  has_many :todos

  # controllerにてtodos_attributesが使えるようにする
  accepts_nested_attributes_for :todos
end

親モデルではaccepts_nested_attributes_for :子モデルを追加することで、コントローラにてパラメータ指定をする際に小モデルのカラムを指定ができるようになります。

Todoモデル

class Todo < ApplicationRecord
    # 親子関係の設定
  belongs_to :category
end

View

今回の機能を実装するのにポイントとなるのはfields_forメソッドです。
fields_forメソッドは親モデルのform_withに対して子モデルのフォームをネストする形で使用します。

<%= form_with model: @category do |f| %> <%# 親モデルのフォームを作成 %>
  <%= f.label :title, class: 'form-label' %>
  <li><%= f.text_field :title %></li>
  <%= f.fields_for :todos do |t| %> <%# fields_forで子モデルのフォームをネストする %>
    <%= f.label :content, class: 'form-label' %>
    <li><%= t.text_field :content %></li> <%# 変数tを使っていることに注意! %>
  <% end %>
  <%= f.submit '投稿' %>
<% end %>

Controller

class CategoriesController < ApplicationController
  def index
    # indexに関する内容
    @categories = Category.all

        # newに関する内容
    @category = Category.new
    @todo = @category.todos.build
  end

  def create
    @category = Category.new(category_params)
    if @category.save
      redirect_to categories_path
    else
      render 'categories'
    end
  end

  private
    def category_params
      params.require(:category).permit(:title, todos_attributes: [:id, :content, :_destroy])
    end
end

ストロングパラメータでは、Todoモデルに渡す値をtodos_attributesで設定しています。
_destroyは、Todoモデルのフォームが空のときに空データが送信されないために追加しています。

createアクションではCategoryモデルに関してnewsaveメソッドをおこなうだけで、Todoモデルに対しても同様のメソッドがなされます。

ステップアップ

複数のTodo.contentを一括で作成する方法に関する記事も執筆する予定です。

参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?