Rails でフォーム送信時のプルダウンメニューの項目をCSV インポートしてDB のデータから表示したい


はじめに

Rails でフォーム送信時のプルダウンメニューの項目をCSV インポートしてDB のデータを使って表示する為の備忘録です。

環境

  • macOS 10.15.6
  • Ruby 2.5.7
  • Rails 5.2.3
  • rspec-rails 4.0.1
  • capybara 3.32.2

参考URL

CSV インポート関連
https://qiita.com/Ryuta1346/items/c21cb70b9879c66c8639
https://qiita.com/SoarTec-lab/items/50e046ea2a2764c12c21
https://docs.ruby-lang.org/ja/latest/class/CSV.html
https://qiita.com/3yatsu/items/416411c0a8f696dbf99e
https://qiita.com/rllllho/items/672e336a03335cba6b34

プルダウンメニュー関連
https://qiita.com/HrsUed/items/56677d6c266d8a53ffa7
https://qiita.com/kawakami_shotaro/items/11a677bf34136cb7686d
https://qiita.com/colorrabbit/items/b58888506e41d1370fd1
https://crieit.net/posts/Rails-collection-select
https://qiita.com/_akira19/items/c218186983f444c2d794

国コード一覧CSV
https://qiita.com/tao_s/items/3yy2b90a2751bfbdd585ea

目標

  1. プルダウンメニューの選択肢をCSV インポートする
  2. プルダウンメニューの選択項目をDB のデータを使い表示する

見た目のイメージです↓

プルダウンメニューの選択肢はDB に保存しているカラムの情報を使って表示します↓

実装

CSV インポートとフォームのプルダウン化を分けて解説します。

1. プルダウンメニューの選択肢をCSV インポートする

  1. 国名一覧保存用にCountry モデル作成
  2. db/seeds.rb にインポート処理を追加
  3. rails コマンドでインポート処理を実行

Ruby のCSV ライブラリを使用してインポート処理を行います。
今回は以下のようなCSV から国名一覧をインポートしました。
作成したCSV ファイルはルートディレクトリに追加しました。

country.csv
番号,国・地域名,ISO 3166-1に於ける英語名,数,三字,二字,場所,各行政区分
1,アイスランド,Iceland,352,ISL,IS,北ヨーロッパ,ISO 3166-2:IS
2,アイルランド,Ireland,372,IRL,IE,西ヨーロッパ,ISO 3166-2:IE

CSV は国コード一覧CSV を使わせて頂きました。

1. Country モデル作成

下記のようなモデルを作成しました。
region カラムは今回は使っていません。

attribute type
country_name string
region string
# Country モデル作成
$ rails g model Country country_name:string region:string

2. インポート処理を追加

インポート処理はseeds.rb に追記しました。
別途ファイルを作成しrunner コマンドで実行する方法もあるようです。

seeds.rb
require "csv"

# CSV ファイルへのパスは絶対パスで指定
CSV.foreach("country.csv", headers: true) do |row|
  Country.create!(
    country_name: row["国・地域名"],
    region: row["場所"]
  )
end

3. インポート処理を実行

rails コマンドでCSV インポートを実行します。
seed ファイルに他の処理も書いていたので今回はDB 内を全削除してインポートし直しました。

# CSV をインポートしてDB に保存する場合はこれだけ
$ rails db:seed

# DB を消去して全て入れ直す
$ rails db:migrate:reset
$ rails db:seed

# rails コンソールでインポートされたか確認
$ rails c
# インポートした国名の件数を確認
> Country.count
249

2. プルダウンメニューの選択項目をDB のデータを使い表示する

新規投稿時のフォーム送信のView ファイルを修正します。

view/model_names/new.html.erb
# 修正前
<%= form_with model: @model_name do |f| %>
  <%= f.label :country %>
  <%= f.text_field :country %>

  <%= f.submit "送信" %>
<% end %>
view/model_names/new.html.erb
# 修正後
<%= form_with model: @model_name do |f| %>
  <%= f.label :country %>
  <%= f.collection_select :country, Country.all, :id, :country_name, prompt: "国を選択してください" %>

  <%= f.submit "送信" %>
<% end %>
# collection_select の文法
<%= f.collection_select <保存先のカラム名>, <表示用の配列データ>, <保存する値のカラム名>,  <表示用のカラム名>, <オプション> %>
  • 保存先のカラム名: country
  • 表示用の配列データ: Country.all
  • 保存する値のカラム名: id
  • 表示用のカラム名: country_name
  • オプション: prompt オプションで国を選択してくださいを表示

collection_select の使い方についてはこちら解説が非常に分かりやすいです。

学び

  • 検索などその後の処理も考慮してインポートを行う
  • 選択肢が縦に長くなってしまうので、階層を持たせるなどして使いやすさを考慮した使用に変更したい

追記

RSpec でのプルダウンの表示テスト時にtest 環境でもseeds.rb の初期データが必要になったので環境別にseeds.rb を分割しました。
test 環境でのプルダウンの表示がされていない事に気付かずハマってしまったので備忘録を追加しました。