今回達成すること
今回は、開発環境、テスト環境、本番環境それぞれにseedデータを投入します。
seedデータとは
seedデータとは、データベースに投入する初期データのことです。
この初期データの投入は、db/seeds.rb から操作します。
seeds.rbの設計
今回のアプリでは、環境ごとに参照するディレクトリを変更し、seedデータを切り替える設計となります。
- 開発環境、テスト環境 => db/seeds/development 以下のseedファイルを読み込む
- 本番環境 => db/seeds/production 以下のseedファイルを読み込む
開発、テスト環境と本番環境で投入するデータを切り替えることができるので実務での活用にオススメです。
db/seedsのディレクトリ構造
db/seeds
├── csv_files
├── development
└── production
db/seeds.rb
table_names = %w()
table_names.each do |table_name|
environment = (Rails.env == "test") ? "development" : Rails.env
path = Rails.root.join("db/seeds", environment, table_name + ".rb")
if File.exist?(path)
puts "#{table_name}..."
require path
end
end
-
table_names = %w()
Rubyの
%w()
を使い、配列を作成しています。ここには、seedファイル名と一致する文字列を入れます。
users.rbファイルの場合 =>
users
と入れる。 -
(Rails.env == "test") ? "development" : Rails.env
Rails.env
には、- 開発環境の場合「development」
- テスト環境の場合「test」
- 本番環境の場合「production」
の文字列が格納されています。
この文字列と一致するディレクトリ名をファイルパスとして渡し、seedファイルを読み込みます。
なお、テスト環境の場合は「development」を参照するように設定しています。
開発環境にユーザーseedデータを投入する
開発環境にユーザーseedデータを投入します。
db/seeds/developmentディレクトリに
ターミナルでコマンドを実行します。
myapp $ touch db/seeds/development/users.rb
users.rbにユーザーデータ作成のコードを書く
作成された
この書き方は、ユーザーEmailの重複を禁止しているときに役立ちます。
既にユーザーが存在すれば何もせず、新規ユーザーの場合のみseedデータに保存するため重複エラーを吐き出しません。
db/seeds/development/users.rb
10.times do |n|
user = User.find_or_initialize_by(
email: "user#{n+1}@example.com",
activated: true
)
if user.new_record?
user.password = "password"
user.save!
end
end
puts "users = #{User.count}"
-
10.times do |n|
Rubyの
times
は、先頭に渡した整数の数だけループを行います。n
には0から1ずつ増えていく数値が渡されます。 -
find_or_initialize_by
渡された引数でユーザーを検索し、取得します。
上記の場合
email
が同じ、かつactivated: true
のユーザーを取得しています。もしユーザーが見つからなければ、
User.new
を実行します。 -
user.new_record?
上記で
User.new
されたユーザー、つまり新規ユーザーのみにpasswordを設定し、save!
で保存しています。
seeds.rbにusers.rbを読み込むように設定する
users.rbを読み込むように
作成したファイル名から .rb
を削除した名前をtable_namesに追加します。
db/seeds.rb
table_names = %w(
users
)
...
seedデータを投入するコマンドを実行する
ターミナルから下記コマンドを実行してください。
myapp $ rails db:seed
データベースに保存されたデータを全て削除して、もう一度入れ直す場合は reset
コマンドを実行してください。
myapp $ rails db:reset
ターミナルにこのように出てこれば成功です。OK!
users...
users = 10
開発環境のユーザーデータを確認する
確認はrails consoleから行います。
myapp $ rails c
ログインできたら、consoleの表示を見やすくHirbコマンドを実行します。
gem 'hirb'とgem 'hirb-unicode'を使っています
irb(main):001:0> Hirb.enable
=> true
ユーザー一覧を表示してみましょう
irb(main):002:0> User.all
作成した10人のユーザーデータが表示されました。
+----+----------------+----------------+-----------+-------+----------------+---------------
| id | email | password_di... | activated | admin | created_at | updated_at
+----+----------------+----------------+-----------+-------+----------------+---------------
| 1 | user1@examp... | $2a$12$ZKJq... | true | false | 2019-11-16 ... | 2019-11-16 ...
| 2 | user2@examp... | $2a$12$hmUu... | true | false | 2019-11-16 ... | 2019-11-16 ...
| 3 | user3@examp... | $2a$12$cChn... | true | false | 2019-11-16 ... | 2019-11-16 ...
| 4 | user4@examp... | $2a$12$zhNB... | true | false | 2019-11-16 ... | 2019-11-16 ...
| 5 | user5@examp... | $2a$12$4bvY... | true | false | 2019-11-16 ... | 2019-11-16 ...
| 6 | user6@examp... | $2a$12$SvAl... | true | false | 2019-11-16 ... | 2019-11-16 ...
| 7 | user7@examp... | $2a$12$ciqk... | true | false | 2019-11-16 ... | 2019-11-16 ...
| 8 | user8@examp... | $2a$12$PaQm... | true | false | 2019-11-16 ... | 2019-11-16 ...
| 9 | user9@examp... | $2a$12$GVK2... | true | false | 2019-11-16 ... | 2019-11-16 ...
| 10 | user10@exam... | $2a$12$pDRY... | true | false | 2019-11-16 ... | 2019-11-16 ...
+----+----------------+----------------+-----------+-------+----------------+---------------
consoleから抜けましょう。
irb(main):003:0> exit
以上で開発環境のユーザーseedデータの投入は完了です。
本番環境用のseedファイルをコピーしとく
本番環境のseedデータはdb/seeds/productionディレクトリ内で管理します。
先ほど作成した
productionディレクトリにコピーしましょう。
myapp $ cp db/seeds/development/users.rb db/seeds/production
-
cp
コマンドcp コピー元のファイル名 コピー先のディレクトリ名
コピー先のファイル名を書き換えない場合は、上記のようにディレクトリを指定するだけでコピーできます。
最終的なseedsディレクトリはこのような構造になりました。
db/seeds
├── csv_files
├── development
│ └── users.rb
└── production
└── users.rb
テスト環境を整える
テストには結果をいい感じに表示してくれるGem minitest-reporters を利用します。
セッティングの前に最新のv1.4.2にバージョンアップしておきましょう。
Gemfile
group :test do
# gem 'minitest-reporters', '~> 1.1.9' # 削除
gem 'minitest-reporters', '~> 1.4.2' # 書き換え
end
バージョンアップのコマンドを実行します。
myapp $ bundle update
minitest-reportersがバージョンアップできたか確認してみましょう。
myapp $ bundle list minitest-reporters
/Users/ユーザー名/rails/アプリ名/vendor/bundle/gems/minitest-reporters-1.4.2
v1.4.2。OKですね。
gem list とbundle list の違いってなんだろなと思って調べたら、この人が分かりやすく解説してくれていました。
bundle install --path vendor/bundleと、bundle listとgem listの違いについて - Qiita
gem list => グローバルにインストールされたgemの一覧
bundle list => プロジェクトで管理されているgemの一覧
だそうです!
minitest-reportersのセットアップ
minitest-reportersを利用するために、
test/test_helper.rb
# 追記
# gem 'minitest-reporters' setup
require "minitest/reporters"
Minitest::Reporters.use!
class ActiveSupport::TestCase
有効になったか確認してみましょう。
rails testを実行してみます。
myapp $ rails t
rails t は rails testコマンドの省略形です。
いい感じにテスト結果を表示してくれました!
テスト環境にユーザーseedデータを投入する
テストに使うseedデータは、test/fixtures ディレクトリ内にあるymlファイルで作成することができますが、このymlファイルで一つ一つテストデータを作成するのは非常に非効率です。
そこで、テスト環境で使用するデータベース「test.sqlite3」にseedデータを投入します。
test/test_helper.rb
# 追記
# seed data loading
load "#{Rails.root}/db/seeds.rb"
class ActiveSupport::TestCase
# fixtures :all コメントアウト、もしくは削除する
end
追記が完了したら、testコマンドを実行してみましょう。
myapp $ rails t
users...
users = 10
「users = 10」が表示されれば、seeds.rb が呼び出されている証拠です。
test.sqlite3にログインし、テストデータを確認する
test.sqlite3にログインするには、sqlite3コマンドを使用します。
myapp $ sqlite3 db/test.sqlite3
usersテーブルの中身を確認するには、select文を使います。
sqlite> select * from users;
1|user1@example.com|$2a$04$jPUtoXtle6b8G4swk65yOuogj9cTRNt6DVdRskKEhz0aTdm7ctTqS|1|0|2019-11-16 16:55:35.512812|2019-11-16 16:55:35.512812
2|user2@example.com|$2a$04$cMpovm1e7GINBdjQ9T688.r7cwyOsYq3rhjVZ42tBpvodRBRtWqxq|1|0|2019-11-16 16:55:35.522510|2019-11-16 16:55:35.522510
...
つらつらとユーザーが10人表示されました。
これでtest.sqlite3にユーザーデータが投入できました。
sqlite3から抜けます。
sqlite> .q
test.sqlite3からユーザーデータを呼び出すには?
通常のRailsとなんら変わりありません。
例えばアクティブなユーザーを1人取得してみましょう。
test/test_helper.rb
class ActiveSupport::TestCase
def init
@user = User.find_by(activated: true)
end
end
この init
メソッドを
test/models/user_test.rb
class UserTest < ActiveSupport::TestCase
def setup
init
end
end
test_helper.rbのinit
を呼び出すことによって、@user
で定義したインスタンス変数が利用できるようになります。
試しにテストを書いてみましょう。
test/models/user_test.rb
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
init
end
test "sqlite3_test" do
assert_not_nil @user
end
end
-
assert_not_nil
引数に渡されたオブジェクトが存在する(nilでない)場合にテスト成功となります。
テストコマンドを実行します。
myapp $ rails t
...
1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
ちゃんと通りましたね。@user
はnilでないということが証明されました。
本番環境にユーザーseedデータを投入する
本番環境にseedデータを投入するには、現在のコードをHerokuにアップし、Heroku側でrails db:seed
コマンドを実行すればOKです。
ここまでの変更をHerokuにpushする
コミットして、ブランチを作成している方はマージしましょう。
myapp $ git add -A
myapp $ git commit -m "set_user_seed_data"
myapp $ git checkout master
myapp $ git merge user_modeling (ここはご自身のブランチ名)
BitbucketとHerokuにpushしましょう。
myapp $ git push
myapp $ git push heroku
Herokuデータベースの初期化
Herokuのデータベースをリセットしてまっさらな状態にします。
myapp $ heroku pg:reset DATABASE
▸ WARNING: Destructive action
▸ postgresql-parallel-50057 will lose all of its data
▸
▸ To proceed, type spa-myapp8 or re-run this command with
▸ --confirm spa-myapp8
> spa-myapp8 (ここにご自身のアプリ名を入れてEnterします)
Herokuデータベースの作成とseedデータの投入
続いてマイグレーションを実行してユーザーテーブルを作成します。
myapp $ heroku run rails db:migrate
最後はseedデータを入れます。
myapp $ heroku run rails db:seed
Herokuのデータベースを確認する
Herokuのデータベースにユーザーが作成されたか確認してみましょう。
Heroku consoleにログインし、User.all
でユーザーデータを確認します。
myapp $ heroku run rails c
irb(main):001:0> Hirb.enable
=> true
irb(main):002:0> User.all
開発環境と同じようにユーザーが表示されましたね。これで本番環境にもユーザーが作成されました。
Heroku consoleから抜けましょう。
irb(main):003:0> exit
もう一度、ブランチに入っとく
次回はユーザーモデルのテストを書いていきます。
ブランチを作成していた方は、先ほどマージしたブランチにもう一度移動しておきましょう。
myapp $ git checkout user_modeling
myapp $ git branch
...
* user_modeling
まとめ
今回は以下のことを実装しました。
- 開発環境にユーザーseedデータの投入
- gem 'minitest-reporters'のセッティング
- テスト環境のデータベース「test.sqlite3」にseedデータの投入
- Herokuの本番環境にseedデータの投入
サクッと進みましたか?
今回は以上で。
さて、次回は?
次回はユーザーモデルのテストを書いていきます。
バリデーションが正しく実装されているかチェックしましょう。
ユーザーモデル開発完了まであと少し!