Need help with multiverse?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

ankane
443 Stars 21 Forks MIT License 119 Commits 0 Opened issues

Description

Multiple databases for Rails :tada:

Services available

!
?

Need anything else?

Contributors list

# 3,301
Ruby
Rails
chartjs
highcha...
114 commits
# 119,514
Ruby
content...
Shell
Rails
1 commit
# 44,835
Rails
xslt
Bash
wip
1 commit

Multiverse

:fire: Multiple databases for Rails

ActiveRecord supports multiple databases, but Rails < 6 doesn’t provide a way to manage them. Multiverse changes this.

Plus, it’s easy to upgrade to Rails 6 when you get there.

Works with Rails 4.2+

Build Status

Installation

Add this line to your application’s Gemfile:

gem 'multiverse'

Getting Started

In this example, we’ll have a separate database for our e-commerce catalog that we’ll call

catalog
.

The first step is to generate the necessary files.

rails generate multiverse:db catalog

This creates a

CatalogRecord
class for models to inherit from and adds configuration to
config/database.yml
. It also creates a
db/catalog
directory for migrations and
schema.rb
to live.

rails
and
rake
commands run for the original database by default. To run commands for the new database, use the
DB
environment variable. For instance:

Create the database

DB=catalog rails db:create

Create a migration

DB=catalog rails generate migration add_name_to_products

Run migrations

DB=catalog rails db:migrate

Rollback

DB=catalog rails db:rollback

Models

Also works for models

DB=catalog rails generate model Product

This generates

class Product < CatalogRecord
end

Web Servers

Only necessary in Rails < 5.2

For web servers that fork, be sure to reconnect after forking (just like you do with

ActiveRecord::Base
)

Puma

In

config/puma.rb
, add inside the
on_worker_boot
block
CatalogRecord.establish_connection :"catalog_#{Rails.env}"

Unicorn

In

config/unicorn.rb
, add inside the
before_fork
block
CatalogRecord.connection.disconnect!

And inside the

after_fork
block
CatalogRecord.establish_connection :"catalog_#{Rails.env}"

Testing

Fixtures

Rails fixtures work automatically.

Note: Referential integrity is not disabled on additional databases when fixtures are loaded, so you may run into issues if you use foreign keys. Also, you may run into errors with fixtures if the additional databases aren’t the same type as the primary.

RSpec

After running migrations for additional databases, run:

DB=catalog rails db:test:prepare

Database Cleaner

Database Cleaner supports multiple connections out of the box.

cleaner = DatabaseCleaner[:active_record, {model: CatalogRecord}]
cleaner.strategy = :transaction
cleaner.cleaning do
  # code
end

Read more here

Limitations

There are a few features that aren’t supported on additional databases.

  • Pending migration check
  • schema_cache.yml

Also note that

ActiveRecord::Migration.maintain_test_schema!
doesn’t affect additional databases.

Upgrading to Rails 6

Rails 6 provides a way to manage multiple databases :tada:

To upgrade from Multiverse, nest your database configuration in

config/database.yml
:
# this should be similar to default, but with migrations_paths
catalog_default: &catalog_default
  adapter: ...
  pool: 
  migrations_paths: db/catalog_migrate

development: primary: <<: database: ... catalog: test: primary: production:>

Then change

establish_connection
in
app/models/catalog_record.rb
to:
class CatalogRecord < ActiveRecord::Base
  establish_connection :catalog
end

And move:

  • db/catalog/migrate
    to
    db/catalog_migrate
  • db/catalog/schema.rb
    to
    db/catalog_schema.rb
    (or
    db/catalog/structure.sql
    to
    db/catalog_structure.sql
    ).

Then remove

multiverse
from your Gemfile. :tada:

Now you can use the updated commands:

rails db:migrate          # run all
rails db:migrate:catalog  # runs catalog only

Generate migrations with:

rails generate migration add_name_to_products --database=catalog

And models with:

rails generate model Product --database=catalog --parent=CatalogRecord

Happy scaling!

History

View the changelog

Contributing

Everyone is encouraged to help improve this project. Here are a few ways you can help:

To get started with development and testing:

git clone https://github.com/ankane/multiverse.git
cd multiverse
bundle install
bundle exec rake test

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.