Skip to content


Subversion checkout URL

You can clone with
Download ZIP
ActiveRecord Connections Magic (slaves, multiple connections, sharding, etc)
Fetching latest commit...
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


DB Charmer - ActiveRecord Connection Magic Plugin

DbCharmer is a simple yet powerful plugin for ActiveRecord that does a few things:

  1. Allows you to easily manage AR models' connections (switch_connection_to method)

  2. Allows you to switch AR models' default connections to a separate servers/databases

  3. Allows you to easily choose where your query should go (Model.on_db methods)

  4. Allows you to automatically send read queries to your slaves while masters would handle all the updates.

  5. Adds multiple databases migrations to ActiveRecord

Installation ==

There are two options when approaching db-charmer installation:

  • using gem (recommended)

  • install as a Rails plugin

To install as a gem, add this to your environment.rb:

config.gem 'kovyrin-db-charmer', :lib => 'db_charmer',
  :source => ''

And then run the command:

sudo rake gems:install

To install db-charmer as a Rails plugin use this:

script/plugin install git://

Easy ActiveRecord Connection Management

As a part of this plugin we've added switch_connection_to method that accepts many different kinds of db connections and uses them on a model. We support:

  1. Strings and symbols as the names of connection configuration blocks in database.yml.

  2. ActiveRecord models (we'd use connection currently set up on a model).

  3. Database connections (Model.connection)

  4. Nil values to reset model to default connection.

Sample code:

class Foo < ActiveRecord::Model; end


The switch_connection_to method has an optional second parameter should_exist which is true by default. This parameter is used when the method is called with a string or a symbol connection name and there is no such connection configuration in the database.yml file. If this parameter is true, an exception would be raised, if it is false, the error would be ignored and no connection change would happen. This is really useful when in development mode or in tests you do not want to create many different databases on your local machine and just want to put all your tables in one database.

Multiple DB Migrations

In every application that works with many databases, there is need in convenient schema migrations mechanism.

All Rails users already have this mechanism - rails migrations. So in DbCharmer, we've made it possible to seamlessly use multiple databases in Rails migrations.

There are two methods available in migrations to operate on more than one database:

  1. Global connection change method - used to switch whole migration to a non-default database.

  2. Block-level connection change method - could be used to do only a part of a migration on a non-default db.

Migration class example (global connection rewrite):

class MultiDbTest < ActiveRecord::Migration
   db_magic :connection => :second_db

   def self.up
     create_table :test_table, :force => true do |t|
       t.string :test_string

   def self.down
     drop_table :test_table

Migration class example (block-level connection rewrite):

class MultiDbTest < ActiveRecord::Migration
  def self.up
    on_db :second_db do
      create_table :test_table, :force => true do |t|
        t.string :test_string

  def self.down
    on_db :second_db { drop_table :test_table }

By default in development and test environments you could skip this :second_db connection from your database.yml files, but in production you'd specify it and get the table created on a separate server and/or in a separate database.

This behaviour is controlled by the DbCharmer.migration_connections_should_exist configuration attribute which could be set from a rails initializer.

Using Models in Master-Slave Environments

Master-slave replication is the most popular scale-out technique in medium and large database applications today. There are some rails plugins out there that help rails developers to use slave servers in their models but none of there were flexible enough for us to start using them in a huge application we work on.

So, we've been using ActsAsReadonlyable plugin for a long time and have developed a lots of additions to its code over that time. Since that plugin has been abandoned by its authors, we've decided to collect all of our master-slave code in one plugin and release it for rails 2.2+. DbCharmer adds the following features to Rails models:

Auto-Switching all Reads to Slave(s)

When you create a model, you could use db_magic :slave => :blah or db_magic :slaves => [ :foo, :bar ] commands in your model to set up reads redirection mode when all your find/count/exist/etc methods will be reading data from your slave (or a bunch of slaves in a round-robin manner). Here is an example:

class Foo < ActiveRecord::Base
  db_magic :slave => :slave01

class Bar < ActiveRecord::Base
  db_magic :slaves => [ :slave01, :slave02 ]

Default Connection Switching

If you have more than one master-slave cluster (or simply more than one database) in your database environment, then you might want to change the default database connection of some of your models. You could do that by using db_magic :connection => :foo call from your models. Example:

class Foo < ActiveRecord::Base
  db_magic :connection => :foo

Sample model on a separate master-slave cluster (so, separate main connection + a slave connection):

class Bar < ActiveRecord::Base
  db_magic :connection => :bar, :slave => :bar_slave

Per-Query Connection Management

Sometimes you have some select queries that you know you want to run on the master. This could happen for example when you have just added some data and need to read it back and not sure if it made it all the way to the slave yet or no. For this situation an few others there are a few methods we've added to ActiveRecord models:

1) on_master - this method could be used in two forms: block form and proxy form. In the block form you could force connection switch for a block of code:

User.on_master do
  user = User.find_by_login('foo')
  user.update_attributes!(:activated => true)

In the proxy form this method could be used to force one query to be performed on the master database server:

Comment.on_master.last(:limit => 5)
User.on_master.exists?(:login => login, :password => password)

2) on_slave - this method is used to force a query to be run on a slave even in situations when it's been previously forced to use the master. If there is more than one slave, one would be selected randomly. Tis method has two forms as well: block and proxy.

3) on_db(connection) - this method is what makes two previous methods possible. It is used to switch a model's connection to some db for a short block of code or even for one statement (two forms). It accepts the same range of values as the switch_connection_to method does.


For more information on the plugin internals, please check out the source code. All the plugin's code is covered with tests that were placed in a separate staging rails project located at The project has unit tests for all or at least the most of the parts of plugin's code.

What Ruby and Rails implementations does it work for?

We've tested the plugin on MRI 1.8.6 with Rails 2.3.3. After the initial testing phase we're going to deploy this code in production.

Who are the authors?

This plugin has been created in for our internal use and then the sources were opened for other people to use. All the code in this package has been developed by Alexey Kovyrin for and is released under the GPLv2 license. For more details, see the LICENSE file.

Something went wrong with that request. Please try again.