はじめに
2024年4月から、プログラミングスクールRUNTEQでプログラミングを学んでいるしまたまと申します!
Railsでとあるアーティストの掲示板を作成するにあたり、初期データをseeds.rbファイルで用意しようとしたところ、非常に長くなってしまいました。
# 1つ目のイベント
Event.create!(
title: 'BLT LIVE BOOSTER vol.1',
place: '恵比寿LIQUIDROOM',
place_prefecture: 'Tokyo'
date: '2021-06-03',
category: 'event'
)
# 2つ目のイベント
Event.create!(
title: 'ROCK IN JAPAN 2024',
place: '蘇我スポーツ公園',
place_prefecture: 'Chiba'
date: '2024-08-01',
category: 'fes'
)
# 3つ目のイベント
Event.create!(
title: 'JAPAN JAM 2024',
place: '蘇我スポーツ公園',
place_prefecture: 'Chiba'
date: '2024-05-01',
category: 'fes'
)
...
# これを全ライブ分(自分の場合130個)+全楽曲分も記述しないといけない!?
長〜いですね。ヒューマンエラー待ったなしです。
そこで調べてみたところ、Excel等の表形式で作成したデータをデータベースに入れる方法が見つかりました。
今回のRUNTEQアドベントカレンダーのテーマが「プログラミングでの"ワクワク"」ということで、「こんなにめんどくさい記述を表にできるんですかっ!?」とワクワクしたので、記事にして投稿します!
対象読者
- Railsで大量の初期データを表形式で作成・利用したい方
- 開発環境と本番環境で同じデータを使用したい方
環境
- MacBookPro M2
- Rails8.0
- Ruby3.2.3
- Docker
- (デプロイ先)Fly.io
前提
- 各テーブルの作成と、リレーション(
belongs_to
やhas_many
等)の記述、使用するenumの設定は済んでいるものとします。 - 今回は「seeds.rbとは?」に関する具体的な説明は省きます。簡単に言うと、初期データを作成するためのファイルです。詳細が気になる方は、下記の記事をご覧ください。
参考ページ:Railsガイド
参考ページ:railsのseedの書き方いろいろ
作業の流れ
- 表形式でのデータ作成
- csv形式でRailsアプリに保存
- seeds.rbにデータ作成のためのコードを記述
- 開発環境のデータベースにデータを作成
- 本番環境のデータベースにデータを作成
1. 表形式でのデータ作成
ExcelやNumbersなど、普段お使いの表作成ソフトをご使用ください。
なお、必ず「csvで書き出し/エクスポート」ができることをご確認ください。
今回はGoogleスプレッドシートを使用します。
✏️ データ作成
今回は、Eventsテーブルのデータを作成します。下記のように記述しました。
1行目には、テーブルのカラム名を記述しています。
2行目以降に、作成したいデータの内容を記述しています。
- enumを設定しており、データ型をintegerにしているカラムも、enumのキーを記述してください。
(例)enum :category, { tour: 1, one_man: 2, ... }
としている場合、表にはtour
やone_man
等を入力する(1
や2
ではない)。
作成ができたら、名前をつけて保存してください。ファイルの名前は、テーブル名にすることをおすすめします。
2. csv形式でRailsアプリに保存
✏️ Railsアプリにcsvファイル保存用のディレクトリを作る
Railsアプリのルートディレクトリで、下記コマンドを実行してください。
mkdir db/csv
✏️ 作成した表をcsv形式に変換してアプリに保存する
db/csv内に、先ほど作成した表を、「csv形式で保存」してください。Googleスプレッドシートでは、
ファイル > ダウンロード > カンマ区切り形式(.csv)
で保存できます。
(csvファイルにする理由)
csv形式は、表↔︎表形式のデータもRailsアプリ内で取り扱えるようになるなど、互換性が高いため。
参考ページ:CSVファイルとExcel(エクセル)ファイルの違いとは?
3. seeds.rbにデータ作成のためのコードを記述
✏️ 記述内容
以下を参考に、データ作成を行うコードを記述してください。
require "csv"
CSV.foreach('db/csv/events.csv', headers: true) do |row|
Event.find_or_create_by!(name: row['name'], date: row['date']) do |event|
event.category = row['category']
event.name = row['name']
event.date = row['date']
event.place = row['place']
event.place_prefecture = row['place_prefecture']
end
end
参考ページ:【Rails】rake seedコマンドでCSVファイルからDBに読み込ませる方法
参考ページ:Rails|csvファイルを利用したテストデータの挿入
✏️ コードの解説
require 'csv'
CSV.foreach('db/csv/events.csv', headers: true) do |row|
csvファイルの各行(1行目を除く)に対して、処理を行うことを宣言しています。
foreach
は、csvファイルを読み込むためのメソッドです。
- 第一引数(
'db/csv/events.csv'
)で、処理を行いたいcsvファイルがどのパスにあるのかを示しています。 - 第二引数(
headers: true
)で、csvファイルの1行目をヘッダーとして扱うことを指定しています。
参考ページ:Rubyリファレンスマニュアル singleton method CSV.foreach
Event.find_or_create_by!(name: row['name'], date: row['date']) do |event|
その行のデータがすでに存在するかを検索し、データを作成するかを判定しています。
find_or_create_by!
メソッドは、データがすでにある場合はデータ作成をスキップするメソッドです。
- 使用するメリット
- データ登録後にcsvファイルに新たにデータを追加してデータ作成コマンドを実行しても、追加分だけがデータベースに登録される。
-
create!
メソッドでは生じてしまうデータの重複を防ぐことができる。
- 今回は、引数に
name: row['name'], date: row['date']
を指定しています。Event.name
(イベント名)とEvent.date
(日時)が一致するデータがデータベースにすでにある場合は、データ作成がスキップされます。
参考ページ:Railsガイド
event.category = row['category']
event.name = row['name']
...
データベースにデータが存在しない場合は、この行に従ってデータの作成が行われます。
event.category
の値はcsvのcategory
の列から取ってきて、event.name
の値はcsvのname
の列から…
といった形でデータが作成され、保存されます。
4. 開発環境のデータベースにデータを作成
seeds.rbを記述しただけでは、データベースにデータは保存されません。コンテナ内で、下記コマンドを実行してください。
bin/rails db:seed
このコマンドにより、seeds.rbの記述に沿ってデータがデータベースに保存されます。
5. 本番環境のデータベースにデータを作成
⚠️ 注意
今回はFly.ioでデプロイを行なったため、そのときに行なったデータ作成方法を説明します。その他のデプロイ先でのデータ作成については、各デプロイ先の公式ドキュメント等をご確認ください。
✏️ Fly.ioでのデータ作成方法
本番環境でもseeds.rbに記述した内容をデータベースに保存する際には、同様にbin/rails db:seed
コマンドを実行する必要があります。
Fly.ioでは、開発環境と同じように、ご自身のPCのターミナルからコマンドを実行することができます。デプロイ後、下記コマンドを実行してコンソール画面に入ってください。
flyctl console
その後、下記コマンドを実行してください。
bin/rails db:seed
これで、本番環境のデータベースにcsvに記述したデータが保存されます!