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 3 years have passed since last update.

1回の送信で複数のレコードを作成したい

Last updated at Posted at 2021-12-21

前提

タイトル参照。
冷蔵庫の在庫管理をするオリジナルアプリを作成中です。
食材は名前、賞味期限、数量、値段を入力(バリデーションはまだ設けてないです)
これらをカテゴリーごとに表示、保存できるように試行錯誤中。

この「保存」の処理が、プログラミングを学び始めて4ヶ月の初心者にはとても難しく...

Ruby on Rails2.6.5を使用していると思います。(.ruby-versionというファイルにそう書いてあったので)

テーブル名

Categoriesテーブル
c_name
user(外部キー)

Itemsテーブル
name
category(外部キー)

他にもテーブルやカラムはありますが、試作段階で使用しているのはこれだけです。

最終的に落ち着いたコード

フォーム部分

<%= form_with model: @item_information, url: items_path, local: true do |f| %>
  <div>
  <% @categories.each do |category| %>
    <div>
      <div><%= category.c_name %></div>
      <% 2.times do %> <%# 後々JavaScriptを使用してフォームを増減させる予定 %>
        <div>
        <%= f.text_field :name, name:"[item][name][]" %>
        <input name="[item][category_id][]" type="hidden" value=<%= category.id %>>
                   <%# 1つ1つのフォームにcategory_idを付与するためにinputでねじ込んでます %>
        </div>
      <% end%>
    </div>
  <% end %>
  </div>
  <%= f.submit '追加' %>
<% end %>

こんな感じのフォームができました。
登録したカテゴリーが増えればそのぶんフォームも増えます。
form.png

コントローラー部分

class ItemsController < ApplicationController
# 省略
  def create
    @item_information = item_params
    @item_information.each do |item_data|
      @item = Item.new(item_data)
      if @item.valid?
        @item.save
      else
        render :new
      end
    end
    @categories = Category.where(user_id: current_user.id)
    @item_information = ItemNameInformation.new
    redirect_to root_path
  end

  private

  def item_params
    items = []

    item_data = params[:item]

    item_data[:name].zip(item_data[:category_id]) do |name, category_id|
      item = { name: name, category_id: category_id }
      items << item
    end
    return items
  end
end

item_paramsでparamsの値をハッシュを含む配列に作り替えて、
createアクションでeach文で回しながら保存しています。

今のところバリデーションを設けているのが外部キーしかないので、エラーへの本格的な対処は後々実装します。

懸念点

item_data[:name].zip(item_data[:category_id]) do |name, category_id|
  item = { name: name, category_id: category_id }
  items << item
end

この部分...
今は試作段階でnameとcategory_idしか使用してないのでいいんだけれど、
本格的に実装しようとした時、あと4つほどフォームを増やす予定です。
その値を全て.zipで繋ぐとして記述がものすごく長くなる気がしています。
でも、受け取る値を限定するためにカラム名を指定しないわけにもいかないし
改行はしても問題ないんだろうか...?

あとがき

アプリケーションの使いやすさを求めるためにも1度の送信で済ませる必要がありました。
もともとparamsで送られてきた値は、

item => {"name"=>["〇〇", "〇〇"], "category_id"=>["〇〇", "〇〇"]}

という感じでした。
これを、

item = [{name: "〇〇", category_id: "〇〇"}, {name: "〇〇", category_id: "〇〇"}]

という形で扱いたくて、binding.pryを使いながら探り探りでの実装でした。

ここ、こうした方がいいなどございましたらご教授ください:bow:

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?