はじめに
個人開発を通してRailsの一連の流れというかスタイルがわかってきた。ルーティングを設定し、modelをつくり、コントローラーをつくり、ビューファイルを書く。けれども調べてもわかりづらいことがあったりして大変だった。1対多の登録がそれだった。
1対多とは
1対多とは、あるテーブルのひとつのレコードが別のテーブルの複数のレコードと関係している状態である。例えば一人の図書館ユーザーが複数の本を借りているとすると、ユーザーと本は1対多の関係にあると言える。
私のアプリでは1日の日報と作業内容が1対多の関係にあった。一枚の日報に対して複数の作業を入力していくのだ。モデルの関係性の設定はできたし、バリデーションの設定もできた。しかし、いかにしてその要素を一括で登録するのかが難しかった。
複数の項目を一括で登録する
登録画面は問題なくかけた。
<!-- 略 -->
<%= form_with model: @report, local: true do |f| %>
<div class="form-group mb-4">
<label for="label-report" class="form-label">登録日</label>
<% if @report.reported_on.nil? %>
<%= f.date_field :reported_on, {class: "form-control" ,value:Date.today }%>
<% else %>
<%= f.date_field :reported_on, {class: "form-control"} %>
<% end %>
</div>
<div class="form-group mb-4">
<div class="form-row">
<div class="col-3 col-md-3">ジャンル</div>
<div class="col-6 col-md-6">やったこと</div>
<div class="col-2 col-md-2">時間</div>
<div class="col-1 col-md-1">-</div>
</div>
<div id="report_items">
<%= f.fields_for :report_items do |item| %>
<%= render "report_item_fields", f: item %>
<% end %>
<div class="row links" id="intersect-point">
<div class="col-12 text-center">
<%= link_to_add_association "", f, :report_items ,\
:"data-association-insertion-node" => "#intersect-point" ,class: 'fas fa-plus' %>
</div>
</div>
</div>
</div>
<div class="form-group mb-4">
<label for="label-report" class="form-label">コメント</label>
<%= f.text_area :content,class: "form-control form-control-sm" ,size: "2x3"%></p>
</div>
<%= f.submit "登録", {class: "btn-primary btn-lg"}%>
<% end %>
<!-- 略 -->
<div class="form-row nested-fields">
<div class="my-2 col-3 col-md-3">
<%= f.text_field :genre_name ,{:class => 'form-control' ,:list => 'datalistOptions3', :id => 'exampleDataList3' , :value => get_genre_name(f.object.genre_id) } %>
<datalist id="datalistOptions3">
<% @select_genre.each do |genre| %>
<option value= <%= genre.name %> >
<% end %>
</datalist>
</div>
<div class="my-2 col-6 col-md-6">
<%= f.text_field :content,class: "form-control form-control-sm w-100"%>
</div>
<div class="my-2 col-2 col-md-2">
<%= f.text_field :work_hours,class: "form-control form-control-sm w-100"%>
</div>
<div class="col-1 col-md-1 d-flex justify-content-center align-items-center">
<%= link_to_remove_association "", f ,\
class: 'fas fa-trash-alt' %>
</div>
</div>
ここで、report
が日報であり、report_items
が作業内容である。
report_items
は複数登録が可能であり、+とか-マークで項目を増やせる。これはcocoonというgemを使っているが、これはまた別のときに書きたい。
fields_for
を使うことで、異なるモデルも編集できる。つまりはreport
だけでなく`report_itemsも編集可能になるのだ。
これで登録ボタンを押すと、パラメータがコントローラに渡される。これを解析するのがちょっと面倒だった。
binding.pryでの確認
渡されるデータがどのような形であるのか、知る必要があった。binding.pryを使った。これをコードの途中で挟むことで、デバック作業を行える。時を停止し、変数の中のデータを確認したりできる。
createアクション中に挟む。
class ReportsController < ApplicationController
# 略
def create
binding.pry
end
end
paramsの中に何がはいっているのか。
pry(#<ReportsController>)> params
=> <ActionController::Parameters {"authenticity_token"=>"qyEey4ZqOElVMESUggFdPNOjsgsmDDK7yLZDtwuxv9yxVsI8kPkzspTbkVhyYyeppK1qR/mhG7ed1sjDR95wDA==", "report"=><ActionController::Parameters {"reported_on"=>"2021-10-17", "report_items_attributes"=>{"0"=>{"genre_id"=>"1", "content"=>"a", "work_hours"=>"3"}, "1"=>{"genre_id"=>"", "content"=>"", "work_hours"=>""}, "2"=>{"genre_id"=>"", "content"=>"", "work_hours"=>""}}, "content"=>"test"} permitted: false>, "commit"=>"登録", "controller"=>"reports", "action"=>"create"} permitted: false>
ここからの処理は過去の記事にも書いている。
そうして今に至る。
苦しさとの向き合い方
Railsに限らないことだが、この世はわからないことが多い。苦しい。わかるまで調べるのも一つの手だし、諦めるのも良いかもしれない。なんにせよ個人開発だ。継続を第一として付き合っていこう。
私はこのような類の苦しみはわりと心地が良い。