🤓

seedファイルとhidden_fieldを使って別テーブルに保存する方法

2022/03/08に公開

やりたいこと

  1. seedファイルに用意したデータをテーブルに入れる
  2. それをビューに表示させる
  3. ビューに表示された文字列をクリックすると、別のテーブルに保存される

完成図イメージ
完成のビューイメージ

seedファイルの準備

初期データをseed.rbに記述します。

Activityモデルに入れたいのでActivity.insert_allに続けて、配列の中にハッシュを記述する形にします。
idは後からビューの表示などに使うので数字を振っておきます。
すべて記述できたらターミナルでrails db:seedします。

ポイント!
seed.rbに変更があった場合にそのままrails db:seedしてしまうと、すでにseedしているデータと重複してしまいます。そのため、冒頭にActivity.destroy_allとし、毎回リセットさせるようにします。

seed.rb
Activity.destroy_all
Activity.insert_all([
  # ごみのセクション
  { id: 1, activity: 'レジぶくろをもらわない' }, 
  { id: 2, activity: 'マイエコバッグを使う' }, 
  { id: 3, activity: 'マイはしを持ち歩く' }, 
  { id: 4, activity: 'いらなくなったものを他の人にゆずる' }, 
  { id: 5, activity: '分べつしてごみをすてる' }, 
  { id: 6, activity: 'リサイクルされた物を買う' },
  { id: 7, activity: 'ごみ拾いにさんかする' }, 
  { id: 8, activity: 'ペットボトルのキャップとラベルをはずして分べつする' }, 
  { id: 9, activity: 'こわれたものはしゅうりして使う' }, 
  { id: 10, activity: '「もったいない」をさがす' }, 
  # スマートムーブのセクション
  { id: 11, activity: '近くの場所に行くときは自転車に乗る' }, 
  { id: 12, activity: '近くの場所に行くときは歩く' }, 
  { id: 13, activity: '電車に乗る' }, 
  { id: 14, activity: 'バスに乗る' }, 
  # 学習のセクション
  { id: 15, activity: '「生物多様性」について調べる' }, 
  { id: 16, activity: '「地球温暖化」について調べる' }, 
  { id: 17, activity: '「ごみ問題」について調べる' }, 
  { id: 18, activity: '「絶めつ危ぐ種」について調べる' }, 
  { id: 19, activity: '「3R」について調べる' }, 
  { id: 20, activity: '「オゾンそう」について調べる' }, 
  { id: 21, activity: '「砂ばく化」について調べる' }, 
])

ビューの記述

activities_controller.rb
class ActivitiesController < ApplicationController
  def new
    @activities = Activity.all
  end
end
new.html.erb
<div class="my-5">
    <% @activities[0,9].each do |activity| %>
      <div class="flex align-center my-7">
        <h4 class="text-md text-gray-800 ml-4 hover:border-b-2 hover:border-green-500">
          <%= activity.activity %>
        </h4>
      </div>
    <% end %>
</div>

Activityモデルからインスタンスを生成したデータをeachメソッドで展開して表示します。
このとき、前述の完成イメージのようにカテゴリごとに表示させたいので手動で分けます。
new.html.erbの2行目に注目です(なぜファイル名がindexではなくnewなのかは後述)。

@activitiesの後ろの[0,9]は「配列の0番目から9個分取得する」という意味を表します。
つまり、id:1からid:10までを取得しています。

そのため、次のカテゴリのかたまりをビューで表示させるためには

new.html.erb
<div class="my-5">
    <% @activities[10,4].each do |activity| %>
      <div class="flex align-center my-7">
        <h4 class="text-md text-gray-800 ml-4 hover:border-b-2 hover:border-green-500">
          <%= activity.activity %>
        </h4>
      </div>
    <% end %>
</div>

このように[10,4]と記述して、「配列の10番目から4個分取得」し、
id:11からid:14までを取得させます。

詳細はRuby公式ドキュメントのself[start, length]を確認しましょう
https://docs.ruby-lang.org/ja/latest/method/Array/i/=5b=5d.html

DBへの保存どうやるか

さて、上記の手順で表示させた文字列を取得して、ユーザーと紐づけてデータベースに保存させたいわけです。

今回、Railsのヘルパーメソッドhidden_fieldを使用します。

https://railsdoc.com/page/hidden_field

<%= f.hidden_field :activity_id, :value => activity.id %>

第一引数にパラメーター名(シンボル)、第二引数にvalueとして受け渡します。
これ、htmlだとどうなってるかというと、

<input value="1" type="hidden" name="activity[activity_id]" id="activity_activity_id">

(valueに1が入っているのは例です。idが5だと、ここは5になります)

これと、form_withでフォームの形を作ると、下のように記述ができます。

activities_controller.rb
class ActivitiesController < ApplicationController
  def new
    @user_activity = Activity.new
    @activities = Activity.all
  end

  def create
    @user_activity = UserActivity.new({ activity_id: params[:activity][:activity_id], user_id: current_user.id })
    @user_activity.save
  end
end
new.html.erb
<div class="my-5">
    <% @activities[10,4].each do |activity| %>
        <%= form_with model: @user_activity, path: user_activities_path, local: true do |f|%>
            <div class="flex align-center my-7">
                <%= button_tag type: 'submit' do %>
                    <svg>
                      # 省略
                    </svg>
                <% end %>
                <h4 class="text-md text-gray-800 ml-4 hover:border-b-2 hover:border-green-500">
                  <%= activity.activity %>
                </h4>
                <%= f.hidden_field :activity_id, :value => activity.id %>
            </div>
        <% end %>
    <% end %>
</div>

先ほどのファイル名をnewとしている話ですが、この画面でcreateしたいからnewとしていたんです。アクションとビューを対応させたほうがわかりやすいかと思いまして。

問題点

今のところ、seedファイルのレコードを増やすつもりがないのでこの方法でも問題ないと思っています。
しかし、今後増やす、となった場合に、カテゴリごとにビューを分けていることもありメンテナンスしにくい点と、大規模データには対応できないというのが問題点ですね。

参考

f.hidden_fieldとhidden_field_tagの使い方【Ruby on Rails】

Discussion