はじめに
Rails 6 に追加されそうな新機能を試す第82段。 今回は、 db:seed:replant
編です。
Rails 6 では、 データをすべて削除する db:truncate_all
, 全部データを削除してから、 seed データを投入する db:seed:replant
の2つのタスクが追加されました。
マルチデータベースにも対応しています。
Ruby 2.6.4, Rails 6.0.0, PostgreSQL 10.7, MySQL 8.0.17 で確認しました。
$ rails --version
Rails 6.0.0
今回は、 マルチデータベースを使います。 Backbone データベースは、 PostgreSQLを Library データベースは、 MySQL を使います。
Backbone に User テーブルを作ります。
Library に Book テーブルを作ります。
User と Book の seed データを作成し、タスクを実行して動作を確認します。
プロジェクトを作る
rails new rails_sandbox
cd rails_sandbox
Gemfile に pg と mysql2 を追加する
PostgreSQL と MySQL の両方のデータベースを扱うので、 pg
と mysql2
gem をGemfile に追加します。
...
# Use mysql as the library database for Active Record
gem 'mysql2', '>= 0.4.4'
# Use postgresql as the backbone database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
...
bundle install します。
$ bundle install
config/database.yml を編集する
config/database.yml を編集して、 backbone と library の2つの接続情報を設定します。
データベースサーバの host名は、わかりやすいように postgres と mysql にしました。
default_postgresql: &default_postgresql
adapter: postgresql
encoding: unicode
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: postgres
user: <%= ENV.fetch("POSTGRES_USER") %>
password: <%= ENV.fetch("POSTGRES_PASSWORD") %>
default_mysql: &default_mysql
adapter: mysql2
encoding: utf8mb4
username: root
password:
host: mysql
development:
backbone:
<<: *default_postgresql
database: backbone_development
library:
<<: *default_mysql
database: library_development
migrations_paths: db/library_migrate
...
User モデルを作る
name の属性をもつ User モデルを作ります。
bin/rails g model User name
Book モデルを作る
title 属性をもつ Book モデルを作ります。
このとき --db
オプションで library
を指定します。
bin/rails g model Book title -db library
Book モデルを編集する
connects_to
を使って、Book モデルの接続先を library 側に変更します。
class Book < ApplicationRecord
connects_to database: { writing: :library, reading: :library }
end
seed データを作る
users と books の2つの seed データを作ります。
User.create(
[
{ name: 'Taro' },
{ name: 'Hanako' }
]
)
Book.create(
[
{ title: 'Programming Ruby' },
{ title: 'Agile Web Development with Rails' }
]
)
マイグレーションを実行し seed データを登録する
bin/rails db:create db:migrate db:seed
rails console で確認する
rails console
で User と Book の件数を調べてみます。
irb(main):001:0> User.count
(0.5ms) SELECT COUNT(*) FROM "users"
=> 2
irb(main):002:0> Book.count
(0.2ms) SET NAMES utf8mb4, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
(6.3ms) SELECT COUNT(*) FROM `books`
=> 2
psql と mysql で確認する
psql で users テーブルのデータを確認します。
backbone_development=# select * from users;
id | name | created_at | updated_at
----+--------+----------------------------+----------------------------
1 | Taro | 2019-09-06 22:45:38.356429 | 2019-09-06 22:45:38.356429
2 | Hanako | 2019-09-06 22:45:38.361014 | 2019-09-06 22:45:38.361014
(2 rows)
mysql で books テーブルのデータを確認します。
mysql> select * from books;
+----+----------------------------------+----------------------------+----------------------------+
| id | title | created_at | updated_at |
+----+----------------------------------+----------------------------+----------------------------+
| 1 | Programming Ruby | 2019-09-06 22:45:38.378629 | 2019-09-06 22:45:38.378629 |
| 2 | Agile Web Development with Rails | 2019-09-06 22:45:38.395576 | 2019-09-06 22:45:38.395576 |
+----+----------------------------------+----------------------------+----------------------------+
2 rows in set (0.00 sec)
もう一度 db:seed を実行する
ここで、もう一度 db:seed を実行します。
$ bin/rails db:seed
User と Book の件数は増えます。
irb(main):003:0> User.count
(0.8ms) SELECT COUNT(*) FROM "users"
=> 4
irb(main):004:0> Book.count
(3.1ms) SELECT COUNT(*) FROM `books`
=> 4
psql と mysql で確認しても同様に件数が増えています。
psql:
backbone_development=# select * from users;
id | name | created_at | updated_at
----+--------+----------------------------+----------------------------
1 | Taro | 2019-09-06 22:45:38.356429 | 2019-09-06 22:45:38.356429
2 | Hanako | 2019-09-06 22:45:38.361014 | 2019-09-06 22:45:38.361014
3 | Taro | 2019-09-06 22:58:19.359173 | 2019-09-06 22:58:19.359173
4 | Hanako | 2019-09-06 22:58:19.365323 | 2019-09-06 22:58:19.365323
(4 rows)
mysql:
mysql> select * from books;
+----+----------------------------------+----------------------------+----------------------------+
| id | title | created_at | updated_at |
+----+----------------------------------+----------------------------+----------------------------+
| 1 | Programming Ruby | 2019-09-06 22:45:38.378629 | 2019-09-06 22:45:38.378629 |
| 2 | Agile Web Development with Rails | 2019-09-06 22:45:38.395576 | 2019-09-06 22:45:38.395576 |
| 3 | Programming Ruby | 2019-09-06 22:58:19.382802 | 2019-09-06 22:58:19.382802 |
| 4 | Agile Web Development with Rails | 2019-09-06 22:58:19.397899 | 2019-09-06 22:58:19.397899 |
+----+----------------------------------+----------------------------+----------------------------+
4 rows in set (0.00 sec)
db:seed:replant を試す
db:seed:replant
を試してみましょう。
$ bin/rails db:seed:replant
rails console で確認するとデータは増えずに2件ずつとなっています。
irb(main):005:0> User.count
(1.0ms) SELECT COUNT(*) FROM "users"
=> 2
irb(main):006:0> Book.count
(5.0ms) SELECT COUNT(*) FROM `books`
=> 2
psql と mysql でも確認します。
psql:
backbone_development=# select * from users;
id | name | created_at | updated_at
----+--------+----------------------------+----------------------------
5 | Taro | 2019-09-06 23:05:17.516149 | 2019-09-06 23:05:17.516149
6 | Hanako | 2019-09-06 23:05:17.524706 | 2019-09-06 23:05:17.524706
(2 rows)
mysql:
mysql> select * from books;
+----+----------------------------------+----------------------------+----------------------------+
| id | title | created_at | updated_at |
+----+----------------------------------+----------------------------+----------------------------+
| 1 | Programming Ruby | 2019-09-06 23:05:17.573838 | 2019-09-06 23:05:17.573838 |
| 2 | Agile Web Development with Rails | 2019-09-06 23:05:17.585832 | 2019-09-06 23:05:17.585832 |
+----+----------------------------------+----------------------------+----------------------------+
2 rows in set (0.00 sec)
db:truncate_all を実行する
最後に db:truncate_all を実行してみます。
$ bin/rails db:truncate_all
rails console で確認すると、データが削除されていることがわかります。
irb(main):007:0> User.count
(1.1ms) SELECT COUNT(*) FROM "users"
=> 0
irb(main):008:0> Book.count
(2.4ms) SELECT COUNT(*) FROM `books`
=> 0
sqlite3
sqlite3 には、 truncate が存在しないため、代わりに、 DELETE FROM (テーブル名)
を使っています。
試したソース
試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try082_db_seed_replant