前提
タイトル参照。
冷蔵庫の在庫管理をするオリジナルアプリを作成中です。
食材は名前、賞味期限、数量、値段を入力(バリデーションはまだ設けてないです)
これらをカテゴリーごとに表示、保存できるように試行錯誤中。
この「保存」の処理が、プログラミングを学び始めて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 %>
こんな感じのフォームができました。
登録したカテゴリーが増えればそのぶんフォームも増えます。
コントローラー部分
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を使いながら探り探りでの実装でした。
ここ、こうした方がいいなどございましたらご教授ください