はじめに
今まで初期データ(ダミーデータ)を投入するとき、とりあえずrails db:seed
コマンドを実行していました。
rakeタスクでも同様のことができると知ったので、こちらにまとめます。
Rakeタスクとは
Rakeは、Rubyで書かれた特定の処理をタスクとして、まとめて実行するための仕組みです。
このRakeが実行する処理をRakeタスクと呼びます。
Rubyで書かれた、タスクを定義・管理するためのビルドツールです。
C言語やUnixでいうところのmakeみたいなものらしいです。
Rakeタスクのメリット
- 作業の自動化: 手作業で行っていた面倒な作業を自動化できます
- 再利用性: 一度定義したタスクは、何度でも実行できます
- 可読性: Rubyのコードで記述するため、他の開発者でも理解しやすくなります
RakeタスクとSeedの違い
Seedの特徴
- 目的: データベースの初期化
- 機能: 特定のテーブルに初期データを挿入する
- 実行方法: rake db:seedコマンドで実行
- ファイル: db/seeds.rbファイルにRubyのコードで記述
-
特徴:
- データベースの初期状態を設定するためのシンプルな仕組み
- 具体的なデータの挿入に特化している
- 比較的簡単な構造で記述できる
Rakeタスクの特徴
- 目的: 様々な処理の自動化
- 機能: データベースのマイグレーション、テストの実行、データの生成など、幅広い処理が可能
-
実行方法:
rake <タスク名>
コマンドで実行 -
ファイル:
lib/tasks
ディレクトリに作成したRakeファイルにRubyのコードで記述 -
特徴:
- 柔軟性が高く、複雑な処理も実装できる
- 独自のタスクを定義できる
- seed機能もRakeタスクの一種と考えることができる
上記のようにseedを実行するだけではなく、データベースのマイグレーションなど幅広い処理が実行可能です。
例えば、rails db:migrate:reset
→rails db:seed
とコマンドを一個ずつ実行していた作業がrakeタスクで1回にまとめられます。
タスクファイル
ファイル作成方法
$ rails g task タスク名
今回作成したファイル
namespace :dummy do
desc "ダミーデータの投入"
task all_data: :environment do
ActiveRecord::Base.transaction do
puts '--- start ---'
puts '--- DB migrate reset ---'
Rake::Task['db:migrate:reset'].invoke
puts '--- dummy:userinfo ----'
Rake::Task['dummy:user_info'].invoke
puts '--- end ---'
end
end
end
補足
-
namespace
: タスクを整理するための名前空間を定義しています -
desc
: タスクの説明文です。コマンドラインでrake -T
を実行すると、この説明文が表示されます -
:environment
: 、このタスクを実行する前にRailsの環境が設定されます。どうやらrakeタスクを実行する時にrails内部でこのenvironment
を実行しているみたいです -
Rake::Task
: 上記ではdb:migrate:reset
というタスクで全てのマイグレーションを取り消してDBを再構築。その後にdummy:user_info
というタスクでユーザーデータを作成します
今回作成する初期データ
seedファイルではなく、タスクファイル上で以下のテストユーザーを作成してみます。
seedファイル
namespace :dummy do
task user_info: :environment do
begin
users = [
{ name: 'test1', email: 'test1@example.com', password: 'password1', auth0_id: ENV['AUTH_ID1'], is_admin: false },
{ name: 'administrator', email: 'admin@example.com', password: 'password2', auth0_id: ENV['ADMIN_AUTH_ID'], is_admin: true }
]
users.each do |user|
User.create!(user)
end
rescue StandardError => e
puts "--- ユーザー作成中のエラー ---"
puts e.class, e.message
end
end
end
マイグレーションファイル
class CreateUsers < ActiveRecord::Migration[7.2]
def change
create_table :users do |t|
t.string :auth0_id
t.string :name
t.string :email
t.string :password_digest
t.boolean :is_admin
t.datetime :discarded_at
t.timestamps
end
add_index :users, [:auth0_id, :email], unique: true
end
end
マイグレーションの補足
今回の主旨ではないですが、
add_index
(ユニークなインデックス)を追加しているのは、モデルのバリデーションを通過しても、DBレベルでのユニーク制約によって重複するレコードの挿入を防ぐためです。
タスク実行結果
$ rake dummy_all_data
--- start ---
--- DB migrate reset ---
Dropped database 'my_app_development'
Dropped database 'my_app_test'
Created database 'my_app_development'
Created database 'my_app_test'
== 20241129232933 CreateUsers: migrating ======================================
-- create_table(:users)
-> 0.0177s
-- add_index(:users, [:auth0_id, :email], {:unique=>true})
-> 0.0151s
== 20241129232933 CreateUsers: migrated (0.0330s) =============================
--- dummy:userinfo ----
--- end ---
DBに登録されたユーザー
[1] pry(main)> User.all
=> User Load (4.5ms) SELECT `users`.* FROM `users` /* loading for pp */ LIMIT 11
[#<User:0x0000ffff9a1d8a40
id: 1,
auth0_id: "auth0|***************",
name: "test1",
email: [FILTERED],
password_digest: [FILTERED],
is_admin: false,
discarded_at: nil,
created_at: "2024-12-01 18:36:51.412288000 +0900",
updated_at: "2024-12-01 18:36:51.412288000 +0900">,
#<User:0x0000ffff9bd7adc0
id: 2,
auth0_id: "auth0|***************",
name: "administrator",
email: [FILTERED],
password_digest: [FILTERED],
is_admin: true,
discarded_at: nil,
created_at: "2024-12-01 18:36:51.791835000 +0900",
updated_at: "2024-12-01 18:36:51.791835000 +0900">]
ユーザーが作成されました!
ユーザー作成失敗時
例えば、ユーザーのメールアドレスの@を省いてrakeタスク実行してみます。
email: 'test1@example.com'
→email: 'test1example.com'
(バリデーションは別途で実装しています)
$ rake dummy_all_data
--- start ---
--- DB migrate reset ---
Dropped database 'my_app_development'
Dropped database 'my_app_test'
Created database 'my_app_development'
Created database 'my_app_test'
--- dummy:userinfo ----
--- ユーザー作成中のエラー ---
ActiveRecord::RecordInvalid
バリデーションに失敗しました: メールアドレス は正しい形式で入力してください。
--- end ---
例外処理でバリデーションのエラーメッセージが表示されました。
タスク一覧
rake -T
: Railsアプリケーションで定義されているすべてのRakeタスクとその簡単な説明を一覧表示するコマンドです。
$ rake -T
(一部省略)
rake db:create # Create the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create...
rake db:drop # Drop the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all d...
rake db:encryption:init # Generate a set of keys for configuring Active Record encryption in a given environment
rake db:environment:set # Set the environment value for the database
rake db:fixtures:load # Load fixtures into the current environment's database
rake db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
rake db:migrate:down # Run the "down" for a given migration VERSION
rake db:migrate:redo # Roll back the database one migration and re-migrate up (options: STEP=x, VERSION=x)
rake db:migrate:status # Display status of migrations
rake db:migrate:up # Run the "up" for a given migration VERSION
rake db:prepare # Run setup if database does not exist, or run migrations if it does
rake db:reset # Drop and recreate all databases from their schema for the current environment and load the seeds
rake db:rollback # Roll the schema back to the previous version (specify steps w/ STEP=n)
rake db:schema:cache:clear # Clear a db/schema_cache.yml file
rake db:schema:cache:dump # Create a db/schema_cache.yml file
rake db:schema:dump # Create a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `con...
rake db:schema:load # Load a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `confi...
rake db:seed # Load the seed data from db/seeds.rb
rake db:seed:replant # Truncate tables of each database for current environment and load the seeds
rake db:setup # Create all databases, load all schemas, and initialize with the seed data (use db:reset to also drop all databases ...
rake db:version # Retrieve the current schema version number
rake dummy:all_data # Create dummy data
rake dummy:user_info # Create new users
...
よく見ると、自分が作成したタスクも一覧に表示されています。
rake dummy:all_data # Create dummy data
rake dummy:user_info # Create new users
まとめ
seedとRakeタスクは、どちらもRailsアプリ開発においての目的や機能が異なります。seedはデータベースの初期化に特化しており、Rakeタスクはより柔軟に処理を自動化するための仕組みです。
シンプルなデータの挿入であればseed、より複雑な処理や独自の処理が必要な場合はRakeタスクが適しています。
参考記事
RailsでRakeタスクの作成
Ruby 3.3 リファレンスマニュアル library rake
Railsガイド rake