はじめに
個人アプリで受発注管理機能を実装したので、その時に学んだ複数レコードの一括保存のやり方についてアウトプットします。
参考資料
今回の記事を作成するにあたり、以下の記事を大いに参考にさせていただきました。本当にありがとうございました。
【Rails 5】モデルを一括登録する手順
【Rails 6】form_with用いて一括登録する
1.2. 一括登録フォームの実装
制作物
前提条件
Productモデル
Column | Type |
---|---|
name | string |
price | integer |
unit | string |
availability | boolean |
models/product.rb
class Product < ApplicationRecord
with_options presence: true do
validates :name
validates :unit
validates :price, numericality: {only_integer: true, greater_than_or_equal_to: 0 }
validates :availability, inclusion: { in: [true, false] }
end
end
方針
- 複数商品を一括保存するためのコレクションモデルを作成
- コントローラーで、一括登録のための処理を記述
- ビュー画面で複数の商品を一括登録できるフォームを作成
1. 複数商品を一括保存するためのコレクションモデルを作成
modelsディレクトリの中にformディレクトリを作成し、その中にProductCollectionモデルとBaseモデルを作成します。
models/form/product_collection
class Form::ProductCollection < Form::Base
FORM_COUNT = 10 #ここで、作成したい登録フォームの数を指定
attr_accessor :products
def initialize(attributes = {})
super attributes
self.products = FORM_COUNT.times.map { Product.new() } unless self.products.present?
end
def products_attributes=(attributes)
self.products = attributes.map { |_, v| Product.new(v) }
end
def save
Product.transaction do
self.products.map do |product|
if product.availability # ここでチェックボックスにチェックを入れている商品のみが保存される
product.save
end
end
end
return true
rescue => e
return false
end
end
models/form/base.rb
class Form::Base
include ActiveModel::Model
include ActiveModel::Callbacks
include ActiveModel::Validations
include ActiveModel::Validations::Callbacks
end
2. コントローラーでインスタンスの生成および、データの処理
controllers/products_controller.rb
class ProductsController < ApplicationController
def new
@form = Form::ProductCollection.new
end
def create
@form = Form::ProductCollection.new(product_collection_params)
if @form.save
redirect_to products_path, notice: "商品を登録しました"
else
flash.now[:alert] = "商品登録に失敗しました"
render :new
end
end
private
def product_collection_params
params.require(:form_product_collection)
.permit(products_attributes: [:name, :price, :unit, :availability])
end
end
@form = Form::ProductCollection.new
により、先ほど作ったモデルのインスタンスが生成されます。
ストロングパラメータはproducts_attributesで受け取ります。
3. ビュー画面で複数の商品を一括登録できるフォームを作成
views/products/new.html.haml
= form_with model: @form, url: products_path, method: :post, local: true do |form|
%table
%thread
%tr
%th 登録
%th 商品名
%th 販売価格(円)
%th 発注単位
%tbody
= form.fields_for :products do |f|
%tr
%td.text-center
= f.check_box :availability
%td
= f.text_field :name
%td
= f.text_field :price
%td
= f.text_field :unit
= form.submit "一括登録"
= link_to "戻る", :back
form_withとfields_forを使って複数登録できるフォームを作成しています。
これで、一括保存ができると思います。
最後に
ご覧いただきありがとうござました。何か間違いがあれば、ご指摘をお願いします。