Full Code of kovyrin/db-charmer for AI

master 0c71563472ed cached
160 files
297.8 KB
84.1k tokens
437 symbols
1 requests
Download .txt
Showing preview only (338K chars total). Download the full file or copy to clipboard to get everything.
Repository: kovyrin/db-charmer
Branch: master
Commit: 0c71563472ed
Files: 160
Total size: 297.8 KB

Directory structure:
gitextract_9iqagwm9/

├── .gitignore
├── .travis.yml
├── CHANGES
├── LICENSE
├── Makefile
├── README.rdoc
├── Rakefile
├── ci_build
├── db-charmer.gemspec
├── init.rb
├── issues/
│   └── issues-as-of-2014-11-14.json
├── lib/
│   ├── db_charmer/
│   │   ├── action_controller/
│   │   │   └── force_slave_reads.rb
│   │   ├── active_record/
│   │   │   ├── association_preload.rb
│   │   │   ├── class_attributes.rb
│   │   │   ├── connection_switching.rb
│   │   │   ├── db_magic.rb
│   │   │   ├── migration/
│   │   │   │   └── multi_db_migrations.rb
│   │   │   ├── multi_db_proxy.rb
│   │   │   └── sharding.rb
│   │   ├── connection_factory.rb
│   │   ├── connection_proxy.rb
│   │   ├── core_extensions.rb
│   │   ├── force_slave_reads.rb
│   │   ├── rails2/
│   │   │   ├── abstract_adapter/
│   │   │   │   └── log_formatting.rb
│   │   │   └── active_record/
│   │   │       ├── master_slave_routing.rb
│   │   │       └── named_scope/
│   │   │           └── scope_proxy.rb
│   │   ├── rails3/
│   │   │   ├── abstract_adapter/
│   │   │   │   └── connection_name.rb
│   │   │   └── active_record/
│   │   │       ├── log_subscriber.rb
│   │   │       ├── master_slave_routing.rb
│   │   │       ├── relation/
│   │   │       │   └── connection_routing.rb
│   │   │       └── relation_method.rb
│   │   ├── rails31/
│   │   │   └── active_record/
│   │   │       ├── migration/
│   │   │       │   └── command_recorder.rb
│   │   │       └── preloader/
│   │   │           ├── association.rb
│   │   │           └── has_and_belongs_to_many.rb
│   │   ├── railtie.rb
│   │   ├── sharding/
│   │   │   ├── connection.rb
│   │   │   ├── method/
│   │   │   │   ├── db_block_group_map.rb
│   │   │   │   ├── db_block_map.rb
│   │   │   │   ├── hash_map.rb
│   │   │   │   └── range.rb
│   │   │   ├── method.rb
│   │   │   └── stub_connection.rb
│   │   ├── sharding.rb
│   │   ├── tasks/
│   │   │   └── databases.rake
│   │   ├── version.rb
│   │   └── with_remapped_databases.rb
│   └── db_charmer.rb
├── test-project/
│   ├── .gitignore
│   ├── .rspec
│   ├── Gemfile
│   ├── Rakefile
│   ├── TODO
│   ├── app/
│   │   ├── controllers/
│   │   │   ├── application_controller.rb
│   │   │   └── posts_controller.rb
│   │   ├── helpers/
│   │   │   └── application_helper.rb
│   │   ├── models/
│   │   │   ├── avatar.rb
│   │   │   ├── car.rb
│   │   │   ├── categories_posts.rb
│   │   │   ├── category.rb
│   │   │   ├── comment.rb
│   │   │   ├── event.rb
│   │   │   ├── ford.rb
│   │   │   ├── house.rb
│   │   │   ├── log_record.rb
│   │   │   ├── post.rb
│   │   │   ├── range_sharded_model.rb
│   │   │   ├── toyota.rb
│   │   │   └── user.rb
│   │   └── views/
│   │       ├── layouts/
│   │       │   └── application.html.erb
│   │       └── posts/
│   │           ├── index.html.erb
│   │           ├── new.html.erb
│   │           └── show.html.erb
│   ├── config/
│   │   ├── application.rb
│   │   ├── boot.rb
│   │   ├── database.yml.example
│   │   ├── environment.rb
│   │   ├── environments/
│   │   │   └── test.rb
│   │   ├── initializers/
│   │   │   ├── backtrace_silencers.rb
│   │   │   ├── db_charmer.rb
│   │   │   ├── secret_token.rb
│   │   │   ├── session_store.rb
│   │   │   └── sharding.rb
│   │   ├── locales/
│   │   │   └── en.yml
│   │   └── routes.rb
│   ├── db/
│   │   ├── create_databases.sql
│   │   ├── migrate/
│   │   │   ├── 20090810013829_create_log_records.rb
│   │   │   ├── 20090810013922_create_posts.rb
│   │   │   ├── 20090810221944_create_users.rb
│   │   │   ├── 20100305234245_create_categories.rb
│   │   │   ├── 20100305234340_create_categories_posts.rb
│   │   │   ├── 20100305235831_create_avatars.rb
│   │   │   ├── 20100328201317_create_sharding_map_tables.rb
│   │   │   ├── 20100330180517_create_event_tables.rb
│   │   │   ├── 20100817191548_create_cars.rb
│   │   │   └── 20111005193941_create_comments.rb
│   │   ├── seeds.rb
│   │   └── sharding.sql
│   └── spec/
│       ├── controllers/
│       │   └── posts_controller_spec.rb
│       ├── fixtures/
│       │   ├── avatars.yml
│       │   ├── categories.yml
│       │   ├── categories_posts.yml
│       │   ├── comments.yml
│       │   ├── event_shards_info.yml
│       │   ├── event_shards_map.yml
│       │   ├── log_records.yml
│       │   ├── posts.yml
│       │   └── users.yml
│       ├── integration/
│       │   └── multi_threading_spec.rb
│       ├── models/
│       │   ├── avatar_spec.rb
│       │   ├── cars_spec.rb
│       │   ├── categories_posts_spec.rb
│       │   ├── category_spec.rb
│       │   ├── comment_spec.rb
│       │   ├── event_spec.rb
│       │   ├── log_record_spec.rb
│       │   ├── post_spec.rb
│       │   ├── range_sharded_model_spec.rb
│       │   └── user_spec.rb
│       ├── sharding/
│       │   ├── connection_spec.rb
│       │   ├── method/
│       │   │   ├── db_block_map_spec.rb
│       │   │   ├── hash_map_spec.rb
│       │   │   └── range_spec.rb
│       │   └── sharding_spec.rb
│       ├── spec_helper.rb
│       ├── support/
│       │   └── rails31_stub_connection.rb
│       └── unit/
│           ├── abstract_adapter/
│           │   └── log_formatting_spec.rb
│           ├── action_controller/
│           │   └── force_slave_reads_spec.rb
│           ├── active_record/
│           │   ├── association_preload_spec.rb
│           │   ├── association_proxy_spec.rb
│           │   ├── class_attributes_spec.rb
│           │   ├── connection_switching_spec.rb
│           │   ├── db_magic_spec.rb
│           │   ├── master_slave_routing_spec.rb
│           │   ├── migration/
│           │   │   └── multi_db_migrations_spec.rb
│           │   ├── named_scope/
│           │   │   └── named_scope_spec.rb
│           │   └── relation_spec.rb
│           ├── connection_factory_spec.rb
│           ├── connection_proxy_spec.rb
│           ├── db_charmer_spec.rb
│           ├── multi_db_proxy_spec.rb
│           └── with_remapped_databases_spec.rb
└── test-project-2.x/
    ├── Gemfile
    ├── Rakefile
    ├── config/
    │   ├── boot.rb
    │   ├── database.yml.example
    │   ├── environment.rb
    │   ├── environments/
    │   │   └── test.rb
    │   ├── initializers/
    │   │   ├── backtrace_silencers.rb
    │   │   ├── db_charmer.rb
    │   │   ├── inflections.rb
    │   │   ├── mime_types.rb
    │   │   ├── new_rails_defaults.rb
    │   │   ├── session_store.rb
    │   │   └── sharding.rb
    │   ├── locales/
    │   │   └── en.yml
    │   ├── preinitializer.rb
    │   └── routes.rb
    ├── script/
    │   └── console
    └── spec/
        ├── spec.opts
        └── spec_helper.rb

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
doc
pkg
.DS_Store
_site
.idea



================================================
FILE: .travis.yml
================================================
language: ruby
rvm:
  - 1.8.7
  - 1.9.3
  - 2.0.0

env:
  - RAILS_VERSION=2.x
  - RAILS_VERSION=3.0.20
  - RAILS_VERSION=3.1.12
  - RAILS_VERSION=3.2.3
  - RAILS_VERSION=3.2.15
  - RAILS_VERSION=3.2.15 DB_CHARMER_GEM=1.9.0

notifications:
  recipients:
    - alexey@kovyrin.net

script: ./ci_build

# Whitelist branches to test
branches:
  only:
    - master
    - rails4

# Build matrix configuration
matrix:
  exclude:
    # Do not run Rails 2.x tests on ruby 1.9
    - rvm: 1.9.3
      env: RAILS_VERSION=2.x

    # Do not run Rails 2.x tests on ruby 2.0
    - rvm: 2.0.0
      env: RAILS_VERSION=2.x

    # Do not run Rails 3.0 tests on ruby 2.0
    - rvm: 2.0.0
      env: RAILS_VERSION=3.0.20

    # Do not run Rails 3.1 tests on ruby 2.0
    - rvm: 2.0.0
      env: RAILS_VERSION=3.1.12

    # Do not run early Rails 3.2 tests on ruby 2.0
    - rvm: 2.0.0
      env: RAILS_VERSION=3.2.3


================================================
FILE: CHANGES
================================================
1.9.1 (2014-11-14):

The project has been suspended. No updates will be provided and no Rails versions
beyond 3.2.x will be supported.

For more information please check out this blog post: http://kovyrin.net/2014/11/14/dbcharmer-suspended/

----------------------------------------------------------------------------------------
1.9.0 (2013-10-09):

Most of the major changes in this version are related to our initial push towards making
DbCharmer thread-safe and making sure it works correctly in multi-threaded environments.

Please note, that even though we now test DbCharmer in multi-threaded environments, we still
consider multi-threaded support experimental.

Bug fix: Improved Rails environment detection (sometimes DbCharmer would use
Rails-specific code while running in non-rails projects).

Bug fix: Make sure on_db() method could restore original connection after an exception is
raised from a DB driver during connection switching (Thanks to Dmytro Shteflyuk for finding
the issue and helping with debugging).

This is the first release that does not have a really strict constraint for point-releases
within the Rails 3.2.x branch.

----------------------------------------------------------------------------------------
1.8.4 (2013-03-18):

Bumped up rails dependencies up to 3.2.13.

----------------------------------------------------------------------------------------
1.8.3 (2013-02-11):

Bumped up rails dependencies up to 3.2.12.

----------------------------------------------------------------------------------------
1.8.2 (2013-01-11):

Bumped up rails dependencies up to 3.2.11.

----------------------------------------------------------------------------------------
1.8.1 (2013-01-02):

Bumped up rails dependencies up to 3.2.10.

----------------------------------------------------------------------------------------
1.8.0 (2012-11-12):

Added support for Rails versions up to 3.2.9. Please note, that Rails 3.2.4 is not officially
supported. Your code may work on that version, but no bug reports will be accepted about this
version.

Tests for DbCharmer have been moved to the gem repository to make Travis-CI integration more
stable. We do not put test files into the gem inself so it should not be a problem for most
of the users. If you still use db-charmer as a plugin, please switch to gem mode.

----------------------------------------------------------------------------------------
1.7.1 (2012-04-22):

Beta feature: Rails 3.1 and 3.2 support

Thanks to the community (and Eugene Pimenov aka @libc in particular) we now have support
for Rails versions up to 3.2.1, including new migrations classes.

----------------------------------------------------------------------------------------
1.7.0 (2011-08-29):

Beta feature: Rails 3 support

Beta feature: Added force_slave_reads functionality. Now we could have models with slaves
that are not used by default, but could be turned on globally (per-controller or per-action).

Heavily reorganized the source code to match Rails code structure (class names, etc). This should
make it much easier for other contributors to work with the code.
Added smarter environment detection (using Rails.env, RAILS_ENV or RACK_ENV).

Changed dependencies a bit: instead of depending on rails, we now require specific components
(ActiveRecord, ActiveSupport, etc) + we do not require blankslate gem anymore.

Bugfixes: Fix for N+1 queries when accessing shard_info for db_block_group_map sharding method.

----------------------------------------------------------------------------------------
1.6.17-19 (2011-04-25):

Bugfixes: Do not touch database for sharded models until we really need to. Before 1.6.17
if a database server was dead and there were any other connection issues, class loading
in Ruby would be broken and sharded model class would not be initialized.

----------------------------------------------------------------------------------------
1.6.14 (2011-01-09):

Bugfixes: We do not support Rails 3, and now we prohibit any versions but 2.2 and 2.3 from
being used with db-charmer gem.

----------------------------------------------------------------------------------------
1.6.13 (2010-08-17):

Starting with this version we use Rails.env instead of RAILS_ENV to auto-detect rails
environment. If you use DbCharmer in non-rails project, please set DbCharmer.env manually.

Bugfixes: Thanks to Eric Lindvall we now allow connection names that have symbols ruby
wouldn't like for class names.

----------------------------------------------------------------------------------------
1.6.12 (2010-05-09):

Starting with this version we use Rails.cache (memcache or whatever you use in your project)
to cache sharding blocks information.

Bugfixes: Thanks to Allen Madsen (github user blatyo) we've fixed a few minor issues in
database connections handling.

----------------------------------------------------------------------------------------
1.6.11 (2010-04-16):

Bugfix: Change the way we allocate sharding blocks in block map sharding method to
prevent race-conditions from happening on block to shard assignments.
Breaking change: We require connections to exist by default in all connection factory
methods. If you need old behavior, pass should_exist=false explicitly.

----------------------------------------------------------------------------------------
1.6.10 (2010-04-09):

Multi-Db migrations changed. Now it is possible to call ActiveRecord::Migration.db_magic
and specify default migration connection that would be used by all migrations without
excplicitly switched connections.

----------------------------------------------------------------------------------------
1.6.9 (2010-04-08):

Bugfix release: now DbCharmer works without Rails.

----------------------------------------------------------------------------------------
1.6.7 (2010-04-07):

Changed the way we handle associations in on_db(:foo).find(:include) calls. Now we
switch association's connection only if its default connection is the same as the
master model's connection (not more "table does not exist" problems I hope).

----------------------------------------------------------------------------------------
1.6.5 (2010-04-05):

Bugfix release: Fixed :connection vs :slave in db_magic behaviour. Model.on_master should
run queries on the master, not on AR's default connection.

----------------------------------------------------------------------------------------
1.6.4 (2010-04-05):

Default behaviour changed: DbCharmer.connections_should_exist is true in all environments
by default. Old default behaviour was too misleading for many developers.

----------------------------------------------------------------------------------------
1.6.3 (2010-04-03):

Bugfix release: Modified stub connection initialization code to set default connections
for sharded models using shards enumeration or default shard features of sharding methods.

----------------------------------------------------------------------------------------
1.6.2 (2010-04-03):

Bugfix release: Modified our stub connection used on sharded models to fail on db-calling
methods only. Proxy the rest to a real shard connection. Another bug fixed in db_block_map
sharding method: we didn't increment block counters when assigning blocks to shards.

----------------------------------------------------------------------------------------
1.6.1 (2010-03-31):

Breaking change from now on all connection-switching methods (both in migrations and in
models) are controlled by a single option DbCharmer.connections_should_exist. This
option is false by default in all non-production environments. Check out README for
more details.

----------------------------------------------------------------------------------------
1.6.0 (2010-03-31):

The major (and arguably the only noticeable) change in this version is our simple database
sharding support. The feature is still in alpha stage and should not be used in production
without complete understanding of the principles of its work.

----------------------------------------------------------------------------------------
1.5.5 (2010-03-15):

Thanks to ngmoco.com (http://github.com/ngmoco) now DbCharmer supports one more use-case
for multi-db migrations. Now you can run the same migration on many databases at once.
For example, the following migration would create test_table on all three shard databases:

    class MultiDbTest < ActiveRecord::Migration
      db_magic :connections => [ :shard01, :shard02, :shard03 ]

      def self.up
        create_table :test_table do |t|
          t.string :test_string
          t.timestamps
        end
      end

      def self.down
        drop_table :test_table
      end
    end

----------------------------------------------------------------------------------------
1.5.4 (2010-03-12):

Added DbCharmer.with_remapped_databases, so that you can change the connection for
many models simultaneously, and implicitly. Very useful for work where you want to use
a particular slave for a whole range of database access.

----------------------------------------------------------------------------------------
1.5.3 (2010-03-10):

Few changes:
 * Colorized connection names in the logs for development mode
 * We do not log connection names when connection does not exist

----------------------------------------------------------------------------------------
1.5.1 (2010-03-06):

In this version we've added support for connection names logging in Rails queries log.
New log records have [connection_name] prefix for all queries that are executed on
non-standard connections:

[logs]   LogRecord Columns (1.1ms)   SHOW FIELDS FROM `log_records`
[logs]   User Delete all (0.1ms)   DELETE FROM `users`
[slave01]   User Load (0.2ms)   SELECT * FROM `users` WHERE (`users`.`login` = 'foo')

----------------------------------------------------------------------------------------
1.4.6 -> 1.5.0 (2010-03-05):

Major change in this version of DbCharmer is association preload support. For example,
let's say we have a schema:

    class Post < ActiveRecord::Base
      belongs_to :user
    end

    class User < ActiveRecord::Base
      has_many :posts
    end

Now, if we have the following call in our code:

    User.on_db(:foo).all(:include => :posts)

In 1.4.6 it would load the users from connection :foo and posts from the
default connection, which is not what we would expect from this line of code.
So, starting 1.5.0 all finder calls on models having :include parameter would
switch associated models' connections to the same connection as the main model
in the call.


================================================
FILE: LICENSE
================================================
The MIT License

Copyright (c) 2011, Oleksiy Kovyrin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: Makefile
================================================
doc/files/README_rdoc.html:	README.rdoc
	rdoc README.rdoc

================================================
FILE: README.rdoc
================================================
= WARNING: The Project Has Been Suspended

Please note, that this project has been suspended. No updates will be provided and no Rails versions
beyond 3.2.x will be supported. For more information please check out this blog post: http://kovyrin.net/2014/11/14/dbcharmer-suspended/

= DB Charmer - ActiveRecord Connection Magic Plugin

+DbCharmer+ is a simple yet powerful plugin for ActiveRecord that significantly extends its ability to work with
multiple databases and/or database servers. The major features we add to ActiveRecord are:

1. Simple management for AR model connections (+switch_connection_to+ method)
2. Switching of default AR model connections to separate servers/databases
3. Ability to easily choose where your query should go (<tt>Model.on_*</tt> methods family)
4. Automated master/slave queries routing (selects go to a slave, updates handled by the master).
5. Multiple database migrations with very flexible query routing controls.
6. Simple database sharding functionality with multiple sharding methods (value, range, mapping table).

For more information on the project, you can check out our web site at http://kovyrin.github.io/db-charmer/.

== Installation

There are two options when approaching +DbCharmer+ installation:
* using the gem (recommended and the only way of using it with Rails 3.2+)
* install as a Rails plugin (works in Rails 2.x only)

To install as a gem, add this to your Gemfile:

  gem 'db-charmer', :require => 'db_charmer'

To install +DbCharmer+ as a Rails plugin use the following command:

  ./script/plugin install git://github.com/kovyrin/db-charmer.git

_Notice_: If you use +DbCharmer+ in a non-rails project, you may need to set <tt>DbCharmer.env</tt> to a correct value
before using any of its connection management methods. Correct value here is a valid <tt>database.yml</tt>
first-level section name.


== Documentation/Questions

For more information about the library, please visit our site at http://dbcharmer.net.
If you need more defails on DbCharmer internals, please check out the source code. All the plugin's
code is ~100% covered with tests. The project located in <tt>test-project</tt> directory has unit
tests for all or, at least, the most actively used code paths.

If you have any questions regarding this project, you could contact the author using
the DbCharmer Users Group mailing list:

- Group Info: http://groups.google.com/group/db-charmer
- Subscribe using the info page or by sending an email to mailto:db-charmer-subscribe@googlegroups.com


== What Ruby and Rails implementations does it work for?

We have a continuous integration setup for this gem on with Rails 2.3, 3.0, 3.1 and 3.2 using a few
different versions of Ruby.

CI is running on TravisCI.org: https://travis-ci.org/kovyrin/db-charmer
Build status is: {<img src="https://secure.travis-ci.org/kovyrin/db-charmer.png?branch=master" alt="Build Status: Rails 3.x" />}[https://travis-ci.org/kovyrin/db-charmer]

At the moment we have the following build matrix:
* Rails versions:
  - 2.3
  - 3.0
  - 3.1
  - 3.2
* Ruby versions:
  - 1.8.7
  - 1.9.3 (Rails 3.0+ only)
  - 2.0.0 (Rails 3.2+ only)
* Databases:
  - MySQL

In addition to CI testing, this gem is used in production on Scribd.com (one of the largest RoR
sites in the world) with Ruby Enterprise Edition and Rails 2.2, Rails 2.3, Sinatra and plain
Rack applications.

Starting with version 1.8.0 we support Rails versions 3.2.8 and higher. Please note, that Rails 3.2.4
is not officially supported. Your code may work on that version, but no bug reports will be
accepted about this version.


== Is it Thread-Safe?

Starting with version 1.9.0 we have started working on making the code thread-safe and making sure
DbCharmer works correctly in multi-threaded environments. At this moment we consider multi-threaded
mode experimental. If you use it and it works for you - please let us know, if it does not - please
make sure to file a ticket so that we could improve the code and make it work in your situation.


== Who are the authors?

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

Other contributors who have helped with the development of this library are (alphabetically ordered):
* Allen Madsen
* Andrew Geweke
* Ashley Martens
* Cauê Guerra
* David Dai
* Dmytro Shteflyuk
* Eric Lindvall
* Eugene Pimenov
* Jonathan Viney
* Gregory Man
* Michael Birk
* Tyler McMullen


================================================
FILE: Rakefile
================================================
require 'rake'
require 'bundler'

Bundler::GemHelper.install_tasks


================================================
FILE: ci_build
================================================
#!/bin/bash

# Making the script more robust
set -e # Exit on errors
set -u # Exit on uninitialized variables

RAILS_VERSION=${RAILS_VERSION:-}
if [ "$RAILS_VERSION" == "" ]; then
  echo "Please specify rails version using RAILS_VERSION environment variable!"
  exit 1
fi

# Change directory according to the rails version
if [ "$RAILS_VERSION" == "2.x" ]; then
  # Downgrade rubygems because rails 2.3 does not work on 2.0+
  gem update --system 1.8.25
  cd test-project-2.x
else
  cd test-project
fi

# Print version info
echo "-----------------------------------------------------------------------------------------------------------------"
echo " * Running specs for Rails version $RAILS_VERSION..."
echo " * Ruby version: `ruby --version`"
echo " * Rubygems version: `gem --version`"
echo " * DbCharmer gem version: '${DB_CHARMER_GEM:-trunk}'"
echo "-----------------------------------------------------------------------------------------------------------------"

# Test environment
export RAILS_ENV=test

# Configure database access
cp -f config/database.yml.example config/database.yml

# Create databases and sharding tables
mysql -u root < db/create_databases.sql
mysql -u root db_charmer_sandbox_test < db/sharding.sql

# Install gems
rm -f Gemfile.lock
bundle install

# Run migrations
bundle exec rake --trace db:migrate

# Run the build and return its exit code
if [ "$RAILS_VERSION" == "2.x" ]; then
  exec bundle exec spec -p '/*/**/*_spec.rb' -cbfs spec
else
  exec bundle exec rspec -cbfs spec
fi


================================================
FILE: db-charmer.gemspec
================================================
# -*- encoding: utf-8 -*-
$:.push File.expand_path('../lib', __FILE__)
require 'db_charmer/version'

Gem::Specification.new do |s|
  s.name          = 'db-charmer'
  s.version       = DbCharmer::Version::STRING
  s.platform      = Gem::Platform::RUBY

  s.authors       = [ 'Oleksiy Kovyrin' ]
  s.email         = 'alexey@kovyrin.net'
  s.homepage      = 'http://kovyrin.github.io/db-charmer/'
  s.summary       = 'ActiveRecord Connections Magic (slaves, multiple connections, etc)'
  s.description   = 'DbCharmer is a Rails plugin (and gem) that could be used to manage AR model connections, implement master/slave query schemes, sharding and other magic features many high-scale applications need.'
  s.license       = 'MIT'

  s.rdoc_options = [ '--charset=UTF-8' ]

  s.files         = Dir['lib/**/*'] + Dir['*.rb']
  s.files        += %w[ README.rdoc LICENSE CHANGES ]

  s.require_paths    = [ 'lib' ]
  s.extra_rdoc_files = [ 'LICENSE', 'README.rdoc' ]

  # Dependencies
  s.add_dependency 'activesupport', '< 4.0.0'
  s.add_dependency 'activerecord', '< 4.0.0'

  s.add_development_dependency 'rspec'
  s.add_development_dependency 'yard'
  s.add_development_dependency 'actionpack'
end


================================================
FILE: init.rb
================================================
require 'db_charmer'


================================================
FILE: issues/issues-as-of-2014-11-14.json
================================================
[
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/98",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/98/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/98/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/98/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/98",
    "id": 45164122,
    "number": 98,
    "title": "Rails 4 blocker update_all may ignore condition with db_charmer !!",
    "user": {
      "login": "AvnerCohen",
      "id": 1297254,
      "avatar_url": "https://avatars.githubusercontent.com/u/1297254?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/AvnerCohen",
      "html_url": "https://github.com/AvnerCohen",
      "followers_url": "https://api.github.com/users/AvnerCohen/followers",
      "following_url": "https://api.github.com/users/AvnerCohen/following{/other_user}",
      "gists_url": "https://api.github.com/users/AvnerCohen/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/AvnerCohen/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/AvnerCohen/subscriptions",
      "organizations_url": "https://api.github.com/users/AvnerCohen/orgs",
      "repos_url": "https://api.github.com/users/AvnerCohen/repos",
      "events_url": "https://api.github.com/users/AvnerCohen/events{/privacy}",
      "received_events_url": "https://api.github.com/users/AvnerCohen/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2014-10-07T20:42:29Z",
    "updated_at": "2014-10-07T20:42:29Z",
    "closed_at": null,
    "body": "First thing first, thanks for making this gem and putting the effort into it! :bow: \r\n...\r\n\r\nTo the issue, it might just be that this is a combination of an old code being upgraded from Rails 3 to Rails 4, But it is extremely dangerous.\r\n\r\nConsider the following console code:\r\n\r\n````ruby\r\n› rails c\r\nLoading development environment (Rails 4.1.6)\r\n2.1.2 :001 > Test.update_all({updated_at: Time.now}, {somevalue: 123})\r\nArgumentError: wrong number of arguments (2 for 1)\r\n    from ./gems/activerecord-4.1.6/lib/active_record/relation.rb:316:in `update_all'\r\n    from ./bundler/gems/db-charmer-cb40007c36e2/lib/db_charmer/rails3/active_record/relation/connection_routing.rb:128:in `block in update_all_with_db_charmer'\r\n    from ./bundler/gems/db-charmer-cb40007c36e2/lib/db_charmer/rails3/active_record/relation/connection_routing.rb:103:in `block in switch_connection_for_method'\r\n    from ./bundler/gems/db-charmer-cb40007c36e2/lib/db_charmer/active_record/multi_db_proxy.rb:37:in `on_db'\r\n    from ./bundler/gems/db-charmer-cb40007c36e2/lib/db_charmer/rails3/active_record/relation/connection_routing.rb:102:in `switch_connection_for_method'\r\n    from ./bundler/gems/db-charmer-cb40007c36e2/lib/db_charmer/rails3/active_record/relation/connection_routing.rb:127:in `update_all_with_db_charmer'\r\n    from ./gems/activerecord-4.1.6/lib/active_record/querying.rb:8:in `update_all'\r\n    from (irb):1\r\n    from ./gems/railties-4.1.6/lib/rails/commands/console.rb:90:in `start'\r\n    from ./gems/railties-4.1.6/lib/rails/commands/console.rb:9:in `start'\r\n    from ./gems/railties-4.1.6/lib/rails/commands/commands_tasks.rb:69:in `console'\r\n    from ./gems/railties-4.1.6/lib/rails/commands/commands_tasks.rb:40:in `run_command!'\r\n    from ./gems/railties-4.1.6/lib/rails/commands.rb:17:in `<top (required)>'\r\n    from bin/rails:8:in `require'\r\n    from bin/rails:8:in `<main>'\r\n2.1.2 :002 > Test.update_all({updated_at: Time.now})\r\n  SQL (0.5ms)  UPDATE \"tests\" SET \"updated_at\" = '2014-10-07 20:34:07.694313'\r\n => 0\r\n2.1.2 :003 > Test.update_all({updated_at: Time.now}, {somevalue: 123})\r\n  SQL (0.2ms)  UPDATE \"tests\" SET \"updated_at\" = '2014-10-07 20:34:12.975116'\r\n => 0\r\n\r\n````\r\nGemfile is simply:\r\n\r\n`````ruby\r\nsource 'https://rubygems.org'\r\n\r\ngem 'rails', '4.1.6'\r\n\r\ngem 'sqlite3'\r\n\r\ngem 'db-charmer',\r\n  :git => 'git@github.com:kovyrin/db-charmer.git',\r\n  :branch => 'rails4', :ref => 'cb40007c36e2847850a37a490850cfd822016c5f', :require => 'db_charmer'\r\n````\r\n\r\n\r\n\r\nDescribing the issue:\r\n\r\n1. Calling update_all with wrong params (arity changed to 1 on rails 4) failes as expected.\r\n2. Enough to have a single update_all that passed succesfully.\r\n3. Next execution of wrong params (as [1] above) passes succesfully and arity check is ignored + conditions are totally ignored."
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/97",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/97/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/97/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/97/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/97",
    "id": 38187982,
    "number": 97,
    "title": "DB connections not closing properly",
    "user": {
      "login": "nchafai",
      "id": 436617,
      "avatar_url": "https://avatars.githubusercontent.com/u/436617?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/nchafai",
      "html_url": "https://github.com/nchafai",
      "followers_url": "https://api.github.com/users/nchafai/followers",
      "following_url": "https://api.github.com/users/nchafai/following{/other_user}",
      "gists_url": "https://api.github.com/users/nchafai/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/nchafai/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/nchafai/subscriptions",
      "organizations_url": "https://api.github.com/users/nchafai/orgs",
      "repos_url": "https://api.github.com/users/nchafai/repos",
      "events_url": "https://api.github.com/users/nchafai/events{/privacy}",
      "received_events_url": "https://api.github.com/users/nchafai/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 2,
    "created_at": "2014-07-18T15:47:56Z",
    "updated_at": "2014-07-21T07:17:26Z",
    "closed_at": "2014-07-21T07:16:55Z",
    "body": "Hi,\r\n\r\nWe are using db-charmer to handle distributed data accross multiple databases. However, connections are not closing properly when requests are made on a sharded database : hundreds of connections remain opened. \r\n\r\nAfter investigations, this situation is due to `abstract_connection_class_name` used to reference connections in `ConnectionPool` list : as long as different threads occur, a new connection is added in the pool list since `abstract_connection_class_name` is using the Thread id : \r\n```ruby\r\ndef self.abstract_connection_class_name(connection_name)\r\n  conn_name_klass = connection_name.to_s.gsub(/\\W+/, '_').camelize\r\n  thread = Thread.current.object_id.abs # need to make sure it is non-negative\r\n  \"::AutoGeneratedAbstractConnectionClass#{conn_name_klass}ForThread#{thread}\"\r\nend\r\n```\r\n\r\nIf we just use ` \"::AutoGeneratedAbstractConnectionClass#{conn_name_klass}ForThread\"` without the `#{thread}` suffix part, everything looks fine, and connections are properly closed. \r\n\r\nSo, what is the exact purpose of having introduce this `#{thread}` suffix ? (this suffix is not present in the previous versions of db-charmer)"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/96",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/96/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/96/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/96/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/96",
    "id": 35993889,
    "number": 96,
    "title": "[Rails 4] rake db:migrate:redo doesn't redo all migrations",
    "user": {
      "login": "akshetpandey",
      "id": 1213060,
      "avatar_url": "https://avatars.githubusercontent.com/u/1213060?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/akshetpandey",
      "html_url": "https://github.com/akshetpandey",
      "followers_url": "https://api.github.com/users/akshetpandey/followers",
      "following_url": "https://api.github.com/users/akshetpandey/following{/other_user}",
      "gists_url": "https://api.github.com/users/akshetpandey/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/akshetpandey/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/akshetpandey/subscriptions",
      "organizations_url": "https://api.github.com/users/akshetpandey/orgs",
      "repos_url": "https://api.github.com/users/akshetpandey/repos",
      "events_url": "https://api.github.com/users/akshetpandey/events{/privacy}",
      "received_events_url": "https://api.github.com/users/akshetpandey/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2014-06-18T14:58:18Z",
    "updated_at": "2014-07-08T00:00:58Z",
    "closed_at": "2014-07-08T00:00:58Z",
    "body": "I am using the rails 4 branch with rails 4. The migrations work fine but when I try to redo the migrations, only the last two migrations are picked for redo."
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/95",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/95/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/95/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/95/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/95",
    "id": 35756037,
    "number": 95,
    "title": "Rails 4.1+",
    "user": {
      "login": "richpeck",
      "id": 1104431,
      "avatar_url": "https://avatars.githubusercontent.com/u/1104431?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/richpeck",
      "html_url": "https://github.com/richpeck",
      "followers_url": "https://api.github.com/users/richpeck/followers",
      "following_url": "https://api.github.com/users/richpeck/following{/other_user}",
      "gists_url": "https://api.github.com/users/richpeck/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/richpeck/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/richpeck/subscriptions",
      "organizations_url": "https://api.github.com/users/richpeck/orgs",
      "repos_url": "https://api.github.com/users/richpeck/repos",
      "events_url": "https://api.github.com/users/richpeck/events{/privacy}",
      "received_events_url": "https://api.github.com/users/richpeck/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 7,
    "created_at": "2014-06-15T19:23:32Z",
    "updated_at": "2014-11-03T15:25:13Z",
    "closed_at": null,
    "body": "Any chance we could get an updated ver to work with ActiveSupport 4.1+? \r\n\r\nIt's not compatible with the latest version of Rails otherwise :("
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/94",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/94/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/94/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/94/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/94",
    "id": 28744882,
    "number": 94,
    "title": "Fix #93 Keep slave connections thread local.",
    "user": {
      "login": "gworley3",
      "id": 809976,
      "avatar_url": "https://avatars.githubusercontent.com/u/809976?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/gworley3",
      "html_url": "https://github.com/gworley3",
      "followers_url": "https://api.github.com/users/gworley3/followers",
      "following_url": "https://api.github.com/users/gworley3/following{/other_user}",
      "gists_url": "https://api.github.com/users/gworley3/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/gworley3/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/gworley3/subscriptions",
      "organizations_url": "https://api.github.com/users/gworley3/orgs",
      "repos_url": "https://api.github.com/users/gworley3/repos",
      "events_url": "https://api.github.com/users/gworley3/events{/privacy}",
      "received_events_url": "https://api.github.com/users/gworley3/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2014-03-04T21:57:32Z",
    "updated_at": "2014-03-04T21:57:32Z",
    "closed_at": null,
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/94",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/94",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/94.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/94.patch"
    },
    "body": "This is probably not an ideal fix for #93 but it seems to work."
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/93",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/93/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/93/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/93/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/93",
    "id": 28739552,
    "number": 93,
    "title": "Multi-threaded race conditions with Postgres",
    "user": {
      "login": "gworley3",
      "id": 809976,
      "avatar_url": "https://avatars.githubusercontent.com/u/809976?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/gworley3",
      "html_url": "https://github.com/gworley3",
      "followers_url": "https://api.github.com/users/gworley3/followers",
      "following_url": "https://api.github.com/users/gworley3/following{/other_user}",
      "gists_url": "https://api.github.com/users/gworley3/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/gworley3/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/gworley3/subscriptions",
      "organizations_url": "https://api.github.com/users/gworley3/orgs",
      "repos_url": "https://api.github.com/users/gworley3/repos",
      "events_url": "https://api.github.com/users/gworley3/events{/privacy}",
      "received_events_url": "https://api.github.com/users/gworley3/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2014-03-04T20:52:19Z",
    "updated_at": "2014-07-09T00:38:31Z",
    "closed_at": null,
    "body": "Trying to use db-charmer 1.9.0 with Postgres and rails 3.2.17. Db-charmer works fine with this setup when single threaded. Running multiple threads via Sidekiq, I get the following error:\r\n\r\n```\r\n2014-03-04T20:28:37Z 40445 TID-ox250opo8 WARN: undefined method `fields' for nil:NilClass\r\n2014-03-04T20:28:37Z 40445 TID-ox250opo8 WARN: /Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/connection_adapters/postgresql_adapter.rb:664:in `block in exec_query'\r\n```\r\n\r\nI believe I have traced this down to the way `PostgresqlAdapter` works in Rails. If you dig around in its code you'll find that it makes async calls to execute queries and expects no other query to execute on the same connection while the current query is executing. If another query comes along they end up in a race condition where one query gets a result (possibly the wrong one!) and the other gets nil.\r\n\r\nThis suggests db-charmer needs to do a better job of locking connections to particular threads so that a connection is not used by more than one thread at a time.\r\n\r\nFull stack trace for the curious:\r\n\r\n```\r\n2014-03-04T20:28:37Z 40445 TID-ox250opo8 WARN: {\"retry\"=>5, \"queue\"=>\"low_linkedin_metrics\", \"failures\"=>\"exhausted\", \"class\"=>\"MetricsWorker::Linkedin::ImportAdMetrics\", \"args\"=>[1, \"2013-02-09..2013-02-09\"], \"jid\"=>\"e968f2b5935d884385911a83\", \"enqueued_at\"=>1393960671.074003, \"error_message\"=>\"undefined method `fields' for nil:NilClass\", \"error_class\"=>\"NoMethodError\", \"failed_at\"=>1393964917.8832488, \"retry_count\"=>0}\r\n2014-03-04T20:28:37Z 40445 TID-ox250opo8 WARN: undefined method `fields' for nil:NilClass\r\n2014-03-04T20:28:37Z 40445 TID-ox250opo8 WARN: /Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/connection_adapters/postgresql_adapter.rb:664:in `block in exec_query'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activesupport-3.2.17/lib/active_support/notifications/instrumenter.rb:20:in `instrument'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/rails3/abstract_adapter/connection_name.rb:14:in `instrument'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/instrumentation/active_record.rb:46:in `block in log_with_newrelic_instrumentation'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/method_tracer.rb:271:in `trace_execution_scoped'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/instrumentation/active_record.rb:43:in `log_with_newrelic_instrumentation'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/connection_adapters/postgresql_adapter.rb:659:in `exec_query'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/connection_adapters/postgresql_adapter.rb:1263:in `select'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/querying.rb:38:in `block in find_by_sql'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/explain.rb:41:in `logging_query_plan'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/querying.rb:37:in `find_by_sql'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/rails3/active_record/master_slave_routing.rb:13:in `block in find_by_sql'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/active_record/multi_db_proxy.rb:71:in `first_level_on_slave'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/rails3/active_record/master_slave_routing.rb:12:in `find_by_sql'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/method_tracer.rb:521:in `block in find_by_sql_with_trace_ActiveRecord_self_name_find_by_sql'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/method_tracer.rb:271:in `trace_execution_scoped'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/method_tracer.rb:516:in `find_by_sql_with_trace_ActiveRecord_self_name_find_by_sql'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation.rb:171:in `exec_queries'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation.rb:160:in `block in to_a'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/explain.rb:34:in `logging_query_plan'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation.rb:159:in `to_a'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/rails3/active_record/relation/connection_routing.rb:123:in `block in to_a_with_db_charmer'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/rails3/active_record/relation/connection_routing.rb:113:in `block in switch_connection_for_method'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/active_record/multi_db_proxy.rb:69:in `block in first_level_on_slave'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/active_record/multi_db_proxy.rb:40:in `on_db'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/active_record/multi_db_proxy.rb:59:in `on_slave'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/active_record/multi_db_proxy.rb:69:in `first_level_on_slave'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/rails3/active_record/relation/connection_routing.rb:112:in `switch_connection_for_method'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/rails3/active_record/relation/connection_routing.rb:122:in `to_a_with_db_charmer'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation/finder_methods.rb:381:in `find_first'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation/finder_methods.rb:122:in `first'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation/finder_methods.rb:267:in `find_by_attributes'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/dynamic_matchers.rb:50:in `method_missing'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation/delegation.rb:14:in `block in find_by_id'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation.rb:241:in `block in scoping'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/scoping.rb:98:in `with_scope'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation.rb:241:in `scoping'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/activerecord-3.2.17/lib/active_record/relation/delegation.rb:14:in `find_by_id'\r\n/Users/gworley3/github/adstage/adstage-platform-v2/app/workers/metrics_worker/linkedin/import_ad_metrics.rb:9:in `block in perform'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/db-charmer-1.9.0/lib/db_charmer/force_slave_reads.rb:50:in `force_slave_reads'\r\n/Users/gworley3/github/adstage/adstage-platform-v2/app/workers/metrics_worker/linkedin/import_ad_metrics.rb:8:in `perform'\r\n(eval):3:in `block in perform_with_newrelic_transaction_trace'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:318:in `perform_action_with_newrelic_trace'\r\n(eval):2:in `perform_with_newrelic_transaction_trace'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/processor.rb:49:in `block (3 levels) in process'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:122:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:122:in `block in invoke'\r\n/Users/gworley3/github/adstage/adstage-platform-v2/config/initializers/sidekiq.rb:9:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:124:in `block in invoke'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/instrumentation/sidekiq.rb:25:in `block in call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:318:in `perform_action_with_newrelic_trace'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/newrelic_rpm-3.6.4.122/lib/new_relic/agent/instrumentation/sidekiq.rb:21:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:124:in `block in invoke'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-unique-jobs-2.7.1/lib/sidekiq-unique-jobs/middleware/server/unique_jobs.rb:14:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:124:in `block in invoke'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-failures-0.3.0/lib/sidekiq/failures/middleware.rb:10:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:124:in `block in invoke'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-pro-1.4.3/lib/sidekiq/batch/middleware.rb:26:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:124:in `block in invoke'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/server/active_record.rb:6:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:124:in `block in invoke'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/server/retry_jobs.rb:62:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:124:in `block in invoke'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/server/logging.rb:11:in `block in call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/logging.rb:22:in `with_context'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/server/logging.rb:7:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:124:in `block in invoke'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:127:in `call'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/middleware/chain.rb:127:in `invoke'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/processor.rb:48:in `block (2 levels) in process'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/processor.rb:105:in `stats'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/processor.rb:47:in `block in process'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/processor.rb:86:in `do_defer'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/sidekiq-2.17.6/lib/sidekiq/processor.rb:37:in `process'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/celluloid-0.15.2/lib/celluloid/calls.rb:25:in `public_send'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/celluloid-0.15.2/lib/celluloid/calls.rb:25:in `dispatch'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/celluloid-0.15.2/lib/celluloid/calls.rb:122:in `dispatch'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/celluloid-0.15.2/lib/celluloid/actor.rb:322:in `block in handle_message'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/celluloid-0.15.2/lib/celluloid/actor.rb:416:in `block in task'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/celluloid-0.15.2/lib/celluloid/tasks.rb:55:in `block in initialize'\r\n/Users/gworley3/.rvm/gems/ruby-2.0.0-p247@platform-v2/gems/celluloid-0.15.2/lib/celluloid/tasks/task_fiber.rb:13:in `block in create'\r\n```"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/92",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/92/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/92/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/92/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/92",
    "id": 28669704,
    "number": 92,
    "title": "habtm associations support  broken in rails 4 branch.",
    "user": {
      "login": "bobbarjung",
      "id": 1243200,
      "avatar_url": "https://avatars.githubusercontent.com/u/1243200?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/bobbarjung",
      "html_url": "https://github.com/bobbarjung",
      "followers_url": "https://api.github.com/users/bobbarjung/followers",
      "following_url": "https://api.github.com/users/bobbarjung/following{/other_user}",
      "gists_url": "https://api.github.com/users/bobbarjung/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/bobbarjung/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/bobbarjung/subscriptions",
      "organizations_url": "https://api.github.com/users/bobbarjung/orgs",
      "repos_url": "https://api.github.com/users/bobbarjung/repos",
      "events_url": "https://api.github.com/users/bobbarjung/events{/privacy}",
      "received_events_url": "https://api.github.com/users/bobbarjung/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 6,
    "created_at": "2014-03-04T00:18:47Z",
    "updated_at": "2014-07-29T14:40:22Z",
    "closed_at": null,
    "body": "Hi I have a connection to a recovery database and a habtm relationship between two models.\r\n\r\n```ruby\r\nclass Line\r\n  has_and_belongs_to_many: nodes\r\nend\r\n\r\nclass Node\r\n  has_and_belongs_to_many :lines\r\nend\r\n```\r\n\r\nI could access these relationships on the secondary database through db_charmer magic.\r\n\r\n```ruby\r\na = Node.on_db(:recovery).first\r\na.on_db(:recovery).lines.each {|b| < do stuff with b> }\r\n```\r\n\r\nBut with rails 4 branch of db_charmer gem (2.0.0.dev1)\r\n\r\nI simply get the following \r\n\r\n```\r\nirb(main):034:0> a.on_db(:recovery).lines\r\nirb(main):034:0># ActiveRecord::Associations::CollectionProxy []\r\n```\r\n\r\nAny interim way to get around this issue will also be appreciated."
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/91",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/91/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/91/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/91/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/91",
    "id": 28574942,
    "number": 91,
    "title": "can't query against the default db on_db(:default)",
    "user": {
      "login": "ohadpartuck",
      "id": 2236337,
      "avatar_url": "https://avatars.githubusercontent.com/u/2236337?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/ohadpartuck",
      "html_url": "https://github.com/ohadpartuck",
      "followers_url": "https://api.github.com/users/ohadpartuck/followers",
      "following_url": "https://api.github.com/users/ohadpartuck/following{/other_user}",
      "gists_url": "https://api.github.com/users/ohadpartuck/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/ohadpartuck/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/ohadpartuck/subscriptions",
      "organizations_url": "https://api.github.com/users/ohadpartuck/orgs",
      "repos_url": "https://api.github.com/users/ohadpartuck/repos",
      "events_url": "https://api.github.com/users/ohadpartuck/events{/privacy}",
      "received_events_url": "https://api.github.com/users/ohadpartuck/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 1,
    "created_at": "2014-03-02T07:33:20Z",
    "updated_at": "2014-03-02T09:53:04Z",
    "closed_at": "2014-03-02T09:52:28Z",
    "body": "```ruby \r\ndevelopment: &development\r\n  database: app_dev\r\n  host: masterdb\r\n  <<: *defaults\r\n\r\n  slave:\r\n    <<: *defaults\r\n    host: slavedb01\r\n```\r\n\r\nthen trying to force a query against master\r\n``` MyModel.on_db(:default) ```\r\neven tried \r\n``` MyModel.on_master ```\r\n\r\nBut there is no specific querying against any db.\r\n"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/90",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/90/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/90/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/90/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/90",
    "id": 28014934,
    "number": 90,
    "title": "RuntimeError: can't add a new key into hash during iteration",
    "user": {
      "login": "mhfs",
      "id": 78422,
      "avatar_url": "https://avatars.githubusercontent.com/u/78422?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/mhfs",
      "html_url": "https://github.com/mhfs",
      "followers_url": "https://api.github.com/users/mhfs/followers",
      "following_url": "https://api.github.com/users/mhfs/following{/other_user}",
      "gists_url": "https://api.github.com/users/mhfs/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/mhfs/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/mhfs/subscriptions",
      "organizations_url": "https://api.github.com/users/mhfs/orgs",
      "repos_url": "https://api.github.com/users/mhfs/repos",
      "events_url": "https://api.github.com/users/mhfs/events{/privacy}",
      "received_events_url": "https://api.github.com/users/mhfs/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 12,
    "created_at": "2014-02-21T02:38:17Z",
    "updated_at": "2014-06-03T23:26:05Z",
    "closed_at": null,
    "body": "Hey @kovyrin ,\r\n\r\nI think I might have found a multi-threading bug. Throwing it here to see it rings any bells.\r\n\r\nI'm processing a high volume of quick sidekiq jobs and part of it is performing a query like this:\r\n\r\n```ruby\r\nUser.on_db(:bbdb).find(user_id)\r\n```\r\n\r\nIm' seeing lot's of errors like this:\r\n\r\n```\r\nRuntimeError: can't add a new key into hash during iteration\r\n```\r\nI'm using ruby 2.0.0p353, rails 3.217 and db-charmer 1.9.0 as you can see in the full backtrace below.\r\n\r\nDoes that rings any bells for you?\r\n\r\nThanks in advance.\r\n\r\n```\r\n/vendor/ruby/2.0.0/gems/activerecord-3.2.17/lib/active_record/connection_adapters/abstract/connection_pool.rb:375 in \"[]=\"\r\n/vendor/ruby/2.0.0/gems/activerecord-3.2.17/lib/active_record/connection_adapters/abstract/connection_pool.rb:375 in \"establish_connection\"\r\n/vendor/ruby/2.0.0/gems/activerecord-3.2.17/lib/active_record/connection_adapters/abstract/connection_specification.rb:137 in \"establish_connection\"\r\n/vendor/ruby/2.0.0/gems/db-charmer-1.9.0/lib/db_charmer/active_record/connection_switching.rb:25 in \"establish_real_connection_if_exists\"\r\n/vendor/ruby/2.0.0/gems/db-charmer-1.9.0/lib/db_charmer/connection_factory.rb:51 in \"generate_abstract_class\"\r\n/vendor/ruby/2.0.0/gems/db-charmer-1.9.0/lib/db_charmer/connection_factory.rb:35 in \"establish_connection\"\r\n/vendor/ruby/2.0.0/gems/db-charmer-1.9.0/lib/db_charmer/connection_factory.rb:24 in \"connect\"\r\n/vendor/ruby/2.0.0/gems/db-charmer-1.9.0/lib/db_charmer/active_record/connection_switching.rb:66 in \"coerce_to_connection_proxy\"\r\n/vendor/ruby/2.0.0/gems/db-charmer-1.9.0/lib/db_charmer/active_record/connection_switching.rb:82 in \"switch_connection_to\"\r\n/vendor/ruby/2.0.0/gems/db-charmer-1.9.0/lib/db_charmer/active_record/multi_db_proxy.rb:39 in \"on_db\"\r\n/vendor/ruby/2.0.0/gems/db-charmer-1.9.0/lib/db_charmer/active_record/multi_db_proxy.rb:19 in \"method_missing\"\r\n/app/jobs/backfill_stats_job.rb:7 in \"perform\"\r\n```"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/89",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/89/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/89/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/89/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/89",
    "id": 27979122,
    "number": 89,
    "title": "force_slave_reads option ignored",
    "user": {
      "login": "gworley3",
      "id": 809976,
      "avatar_url": "https://avatars.githubusercontent.com/u/809976?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/gworley3",
      "html_url": "https://github.com/gworley3",
      "followers_url": "https://api.github.com/users/gworley3/followers",
      "following_url": "https://api.github.com/users/gworley3/following{/other_user}",
      "gists_url": "https://api.github.com/users/gworley3/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/gworley3/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/gworley3/subscriptions",
      "organizations_url": "https://api.github.com/users/gworley3/orgs",
      "repos_url": "https://api.github.com/users/gworley3/repos",
      "events_url": "https://api.github.com/users/gworley3/events{/privacy}",
      "received_events_url": "https://api.github.com/users/gworley3/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 1,
    "created_at": "2014-02-20T17:19:06Z",
    "updated_at": "2014-02-20T17:41:46Z",
    "closed_at": "2014-02-20T17:41:46Z",
    "body": "I set `:force_slave_reads => false` in the `db_magic` opts but still reads from slaves by default."
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/88",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/88/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/88/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/88/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/88",
    "id": 24576212,
    "number": 88,
    "title": "Skip HasAndBelongsToMany preloader for Rails 4.1",
    "user": {
      "login": "kmcbride",
      "id": 597435,
      "avatar_url": "https://avatars.githubusercontent.com/u/597435?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/kmcbride",
      "html_url": "https://github.com/kmcbride",
      "followers_url": "https://api.github.com/users/kmcbride/followers",
      "following_url": "https://api.github.com/users/kmcbride/following{/other_user}",
      "gists_url": "https://api.github.com/users/kmcbride/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/kmcbride/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/kmcbride/subscriptions",
      "organizations_url": "https://api.github.com/users/kmcbride/orgs",
      "repos_url": "https://api.github.com/users/kmcbride/repos",
      "events_url": "https://api.github.com/users/kmcbride/events{/privacy}",
      "received_events_url": "https://api.github.com/users/kmcbride/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2013-12-19T18:31:26Z",
    "updated_at": "2014-06-11T19:21:31Z",
    "closed_at": "2014-06-11T19:21:31Z",
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/88",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/88",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/88.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/88.patch"
    },
    "body": "See: https://github.com/rails/rails/commit/a03ea3ff97b43340d0904525083bf8bc7a1c6ebc"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/87",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/87/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/87/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/87/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/87",
    "id": 24129460,
    "number": 87,
    "title": "Make database rake auto load on rails",
    "user": {
      "login": "arthurnn",
      "id": 833383,
      "avatar_url": "https://avatars.githubusercontent.com/u/833383?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/arthurnn",
      "html_url": "https://github.com/arthurnn",
      "followers_url": "https://api.github.com/users/arthurnn/followers",
      "following_url": "https://api.github.com/users/arthurnn/following{/other_user}",
      "gists_url": "https://api.github.com/users/arthurnn/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/arthurnn/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/arthurnn/subscriptions",
      "organizations_url": "https://api.github.com/users/arthurnn/orgs",
      "repos_url": "https://api.github.com/users/arthurnn/repos",
      "events_url": "https://api.github.com/users/arthurnn/events{/privacy}",
      "received_events_url": "https://api.github.com/users/arthurnn/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 3,
    "created_at": "2013-12-11T19:02:34Z",
    "updated_at": "2013-12-12T23:09:55Z",
    "closed_at": "2013-12-12T23:08:46Z",
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/87",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/87",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/87.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/87.patch"
    },
    "body": "@kovyrin \r\n\r\nWe need to load the rake task on `Rails::Railtie`, otherwise they wont be available when just adding the Gem.\r\n\r\nlet me know what you think.\r\n\r\ncheers,"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/86",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/86/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/86/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/86/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/86",
    "id": 23877630,
    "number": 86,
    "title": "Allow AR::B.db_magic m/s split to work with abstract AR classes.",
    "user": {
      "login": "perplexes",
      "id": 13812,
      "avatar_url": "https://avatars.githubusercontent.com/u/13812?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/perplexes",
      "html_url": "https://github.com/perplexes",
      "followers_url": "https://api.github.com/users/perplexes/followers",
      "following_url": "https://api.github.com/users/perplexes/following{/other_user}",
      "gists_url": "https://api.github.com/users/perplexes/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/perplexes/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/perplexes/subscriptions",
      "organizations_url": "https://api.github.com/users/perplexes/orgs",
      "repos_url": "https://api.github.com/users/perplexes/repos",
      "events_url": "https://api.github.com/users/perplexes/events{/privacy}",
      "received_events_url": "https://api.github.com/users/perplexes/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2013-12-06T18:56:28Z",
    "updated_at": "2013-12-06T18:56:28Z",
    "closed_at": null,
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/86",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/86",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/86.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/86.patch"
    },
    "body": "Hi, ran into a SystemStackError. We wanted to split all reads in all models to slaves. The easiest way to do this seemed like:\r\n\r\nIn config/initializers/db_charmer.rb:\r\n```ruby\r\nActiveRecord::Base.db_magic(slave: :main_slave)\r\n```\r\n\r\nBut we also have Rails Engines that have their own version of an AR::B-like class with a separate connection, called base:\r\n\r\n```ruby\r\nclass IsbnDb::Base < ActiveRecord::Base\r\n  self.abstract_class = true\r\n  db_magic connection: :isbn_master, slave: :isbn_slave\r\nend\r\n```\r\n\r\nThen models underneath that would inherit this connection:\r\n```ruby\r\nclass Isbn < IsbnDb::Base\r\nend\r\n```\r\n\r\nWhat we were seeing were SystemStackErrors:\r\n\r\n```ruby\r\n[3] pry(main)> Isbn.first\r\nSystemStackError: stack level too deep\r\n```\r\n\r\nAfter a lot of tracing (and set_trace_func), the culprit is that putting db_magic on ActiveRecord::Base overrides the default behavior of the master/slave automatic methods like reload, find_by_sql and count_by_sql. In models that directly inherit from AR::B (like User, say) this behavior is fine - but in level-2 inherited models (AR::B > Base > Isbn), is causes infinite recursion.\r\n\r\nThis pull request fixes this situation, but I don't quite know how to test it."
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/85",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/85/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/85/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/85/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/85",
    "id": 22639819,
    "number": 85,
    "title": "Rails4 Support",
    "user": {
      "login": "kovyrin",
      "id": 3467,
      "avatar_url": "https://avatars.githubusercontent.com/u/3467?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/kovyrin",
      "html_url": "https://github.com/kovyrin",
      "followers_url": "https://api.github.com/users/kovyrin/followers",
      "following_url": "https://api.github.com/users/kovyrin/following{/other_user}",
      "gists_url": "https://api.github.com/users/kovyrin/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/kovyrin/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/kovyrin/subscriptions",
      "organizations_url": "https://api.github.com/users/kovyrin/orgs",
      "repos_url": "https://api.github.com/users/kovyrin/repos",
      "events_url": "https://api.github.com/users/kovyrin/events{/privacy}",
      "received_events_url": "https://api.github.com/users/kovyrin/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 16,
    "created_at": "2013-11-14T02:58:39Z",
    "updated_at": "2014-10-22T09:35:58Z",
    "closed_at": null,
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/85",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/85",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/85.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/85.patch"
    },
    "body": "This PR is used to track the process of adding Rails 4 support to DbCharmer. It is not ready yet, but we are really close."
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/84",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/84/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/84/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/84/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/84",
    "id": 22639397,
    "number": 84,
    "title": "License missing from gemspec",
    "user": {
      "login": "bf4",
      "id": 142914,
      "avatar_url": "https://avatars.githubusercontent.com/u/142914?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/bf4",
      "html_url": "https://github.com/bf4",
      "followers_url": "https://api.github.com/users/bf4/followers",
      "following_url": "https://api.github.com/users/bf4/following{/other_user}",
      "gists_url": "https://api.github.com/users/bf4/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/bf4/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/bf4/subscriptions",
      "organizations_url": "https://api.github.com/users/bf4/orgs",
      "repos_url": "https://api.github.com/users/bf4/repos",
      "events_url": "https://api.github.com/users/bf4/events{/privacy}",
      "received_events_url": "https://api.github.com/users/bf4/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 2,
    "created_at": "2013-11-14T02:46:06Z",
    "updated_at": "2013-11-14T04:18:04Z",
    "closed_at": "2013-11-14T02:57:03Z",
    "body": "  RubyGems.org doesn't report a license for your gem.  This is because it is not specified in the [gemspec](http://docs.rubygems.org/read/chapter/20#license) of your last release.\n\n  via e.g.\n\n      spec.license = 'MIT'\n      # or\n      spec.licenses = ['MIT', 'GPL-2']\n\n  Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed.  As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how [rubygems.org uses the gemspec to  display the rails gem license](https://rubygems.org/gems/rails).\n\n  There is even a [License Finder gem](https://github.com/pivotal/LicenseFinder) to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec.  This is an important enough issue that *even Bundler now generates gems with a default 'MIT' license*.\n\n  I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!\n\n  Appendix:\n\n  If you need help choosing a [license](http://opensource.org/licenses) (sorry, I haven't checked your readme or looked for a license file), GitHub has created a [license picker tool](http://choosealicense.com/).  Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.\n  Here's a [list of the license names I've found and their frequencies](https://github.com/bf4/gemproject/blob/master/license_usage.csv)\n\n  p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and [make issues for gemspecs not specifying a license as a public service :)](https://github.com/bf4/gemproject/issues/1). See the previous link or my [blog post about this project for more information](http://www.benjaminfleischer.com/2013/07/12/make-the-world-a-better-place-put-a-license-in-your-gemspec/).\n"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/83",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/83/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/83/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/83/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/83",
    "id": 22158156,
    "number": 83,
    "title": "Gemspec updates",
    "user": {
      "login": "bradherman",
      "id": 384172,
      "avatar_url": "https://avatars.githubusercontent.com/u/384172?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/bradherman",
      "html_url": "https://github.com/bradherman",
      "followers_url": "https://api.github.com/users/bradherman/followers",
      "following_url": "https://api.github.com/users/bradherman/following{/other_user}",
      "gists_url": "https://api.github.com/users/bradherman/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/bradherman/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/bradherman/subscriptions",
      "organizations_url": "https://api.github.com/users/bradherman/orgs",
      "repos_url": "https://api.github.com/users/bradherman/repos",
      "events_url": "https://api.github.com/users/bradherman/events{/privacy}",
      "received_events_url": "https://api.github.com/users/bradherman/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 1,
    "created_at": "2013-11-05T22:50:37Z",
    "updated_at": "2013-11-10T06:31:59Z",
    "closed_at": "2013-11-10T06:31:59Z",
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/83",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/83",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/83.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/83.patch"
    },
    "body": ""
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/82",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/82/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/82/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/82/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/82",
    "id": 22002182,
    "number": 82,
    "title": "Update db-charmer.gemspec",
    "user": {
      "login": "yhuang",
      "id": 154587,
      "avatar_url": "https://avatars.githubusercontent.com/u/154587?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/yhuang",
      "html_url": "https://github.com/yhuang",
      "followers_url": "https://api.github.com/users/yhuang/followers",
      "following_url": "https://api.github.com/users/yhuang/following{/other_user}",
      "gists_url": "https://api.github.com/users/yhuang/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/yhuang/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/yhuang/subscriptions",
      "organizations_url": "https://api.github.com/users/yhuang/orgs",
      "repos_url": "https://api.github.com/users/yhuang/repos",
      "events_url": "https://api.github.com/users/yhuang/events{/privacy}",
      "received_events_url": "https://api.github.com/users/yhuang/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 1,
    "created_at": "2013-11-02T14:09:36Z",
    "updated_at": "2013-11-10T15:41:32Z",
    "closed_at": "2013-11-10T15:41:32Z",
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/82",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/82",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/82.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/82.patch"
    },
    "body": "Rails 4.0.1 has been released:\r\n\r\nhttp://weblog.rubyonrails.org/2013/11/1/Rails-4-0-1-has-been-released/"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/81",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/81/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/81/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/81/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/81",
    "id": 21460804,
    "number": 81,
    "title": "Sharded connection key parameter meaning?",
    "user": {
      "login": "fabn",
      "id": 324213,
      "avatar_url": "https://avatars.githubusercontent.com/u/324213?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/fabn",
      "html_url": "https://github.com/fabn",
      "followers_url": "https://api.github.com/users/fabn/followers",
      "following_url": "https://api.github.com/users/fabn/following{/other_user}",
      "gists_url": "https://api.github.com/users/fabn/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/fabn/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/fabn/subscriptions",
      "organizations_url": "https://api.github.com/users/fabn/orgs",
      "repos_url": "https://api.github.com/users/fabn/repos",
      "events_url": "https://api.github.com/users/fabn/events{/privacy}",
      "received_events_url": "https://api.github.com/users/fabn/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2013-10-23T15:14:48Z",
    "updated_at": "2013-10-23T15:14:48Z",
    "closed_at": null,
    "body": "In the readme there is this example for sharded connections\r\n\r\n```ruby\r\nclass Text < ActiveRecord::Base\r\n  db_magic :sharded => {\r\n    :key => :id,\r\n    :sharded_connection => :texts\r\n  }\r\nend\r\n```\r\n\r\nWhat is the meaning of `:key` parameter? I saw that it's not used at all in [setup_sharding_magic](https://github.com/kovyrin/db-charmer/blob/master/lib/db_charmer/active_record/db_magic.rb#L53) method\r\n\r\nI assumed that the usage of that field is to compute the shard before saving or when retrieving records, something like \r\n\r\n```ruby\r\nSHARDING_MAP = {\r\n  'US'  => :us_users,\r\n  'CA'  => :ca_users,\r\n  :default  => :other_users\r\n}\r\n\r\nDbCharmer::Sharding.register_connection(\r\n  :name => :users,\r\n  :method => :hash_map,\r\n  :map => SHARDING_MAP\r\n)\r\n\r\nclass User < ActiveRecord::Base\r\n  db_magic :sharded => {\r\n    :key => :locale,\r\n    :sharded_connection => :users\r\n  }\r\nend\r\n```\r\n\r\nAnd then when creating users\r\n\r\n```ruby\r\nUser.new(locale: 'US').save # this goes to us_users shard\r\nUser.new(locale: 'CA').save # this goes to ca_users shard\r\n```\r\n\r\nBut this kind of code is not working at all, shard must be selected manually before any operation. Am I right? \r\n\r\nIn that case what is the meaning of sharding? The same effect can (almost) be achieved with normal `on_db` method calls?"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/80",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/80/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/80/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/80/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/80",
    "id": 21106472,
    "number": 80,
    "title": "Bump rails to 3.2.15",
    "user": {
      "login": "arthurnn",
      "id": 833383,
      "avatar_url": "https://avatars.githubusercontent.com/u/833383?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/arthurnn",
      "html_url": "https://github.com/arthurnn",
      "followers_url": "https://api.github.com/users/arthurnn/followers",
      "following_url": "https://api.github.com/users/arthurnn/following{/other_user}",
      "gists_url": "https://api.github.com/users/arthurnn/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/arthurnn/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/arthurnn/subscriptions",
      "organizations_url": "https://api.github.com/users/arthurnn/orgs",
      "repos_url": "https://api.github.com/users/arthurnn/repos",
      "events_url": "https://api.github.com/users/arthurnn/events{/privacy}",
      "received_events_url": "https://api.github.com/users/arthurnn/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2013-10-16T20:13:02Z",
    "updated_at": "2013-10-16T20:13:33Z",
    "closed_at": "2013-10-16T20:13:33Z",
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/80",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/80",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/80.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/80.patch"
    },
    "body": ""
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/79",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/79/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/79/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/79/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/79",
    "id": 19604764,
    "number": 79,
    "title": "Connection not switching connection consistantly.",
    "user": {
      "login": "tysliu",
      "id": 68217,
      "avatar_url": "https://avatars.githubusercontent.com/u/68217?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/tysliu",
      "html_url": "https://github.com/tysliu",
      "followers_url": "https://api.github.com/users/tysliu/followers",
      "following_url": "https://api.github.com/users/tysliu/following{/other_user}",
      "gists_url": "https://api.github.com/users/tysliu/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/tysliu/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/tysliu/subscriptions",
      "organizations_url": "https://api.github.com/users/tysliu/orgs",
      "repos_url": "https://api.github.com/users/tysliu/repos",
      "events_url": "https://api.github.com/users/tysliu/events{/privacy}",
      "received_events_url": "https://api.github.com/users/tysliu/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 6,
    "created_at": "2013-09-17T09:49:32Z",
    "updated_at": "2013-11-14T03:45:53Z",
    "closed_at": null,
    "body": "Hi,\r\nI'm eager loading an association for a model. for example Model.where('criteria').includes(:some_association)\r\n\r\nThis association is from another database, I'm finding that if the query for Model.where('criteria') takes too long. our view will throw an error telling us ActionView::Template::Error (Mysql2::Error: Table 'database.some_association' doesn't exist.\r\n\r\nIt would be most appreciated if someone can shed some light on this issue!"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/78",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/78/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/78/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/78/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/78",
    "id": 19461002,
    "number": 78,
    "title": "Kill rails 2 support",
    "user": {
      "login": "arthurnn",
      "id": 833383,
      "avatar_url": "https://avatars.githubusercontent.com/u/833383?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/arthurnn",
      "html_url": "https://github.com/arthurnn",
      "followers_url": "https://api.github.com/users/arthurnn/followers",
      "following_url": "https://api.github.com/users/arthurnn/following{/other_user}",
      "gists_url": "https://api.github.com/users/arthurnn/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/arthurnn/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/arthurnn/subscriptions",
      "organizations_url": "https://api.github.com/users/arthurnn/orgs",
      "repos_url": "https://api.github.com/users/arthurnn/repos",
      "events_url": "https://api.github.com/users/arthurnn/events{/privacy}",
      "received_events_url": "https://api.github.com/users/arthurnn/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 1,
    "created_at": "2013-09-13T15:59:17Z",
    "updated_at": "2013-11-10T15:44:43Z",
    "closed_at": "2013-11-10T15:44:43Z",
    "body": "If @kovyrin is ok with this idea, I can submit a PR to cleaning up code that is there only because of rails 2.\r\nThoughts on that?"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/77",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/77/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/77/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/77/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/77",
    "id": 19411140,
    "number": 77,
    "title": "Rescue error on drop database on the main db",
    "user": {
      "login": "arthurnn",
      "id": 833383,
      "avatar_url": "https://avatars.githubusercontent.com/u/833383?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/arthurnn",
      "html_url": "https://github.com/arthurnn",
      "followers_url": "https://api.github.com/users/arthurnn/followers",
      "following_url": "https://api.github.com/users/arthurnn/following{/other_user}",
      "gists_url": "https://api.github.com/users/arthurnn/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/arthurnn/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/arthurnn/subscriptions",
      "organizations_url": "https://api.github.com/users/arthurnn/orgs",
      "repos_url": "https://api.github.com/users/arthurnn/repos",
      "events_url": "https://api.github.com/users/arthurnn/events{/privacy}",
      "received_events_url": "https://api.github.com/users/arthurnn/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 1,
    "created_at": "2013-09-12T20:02:28Z",
    "updated_at": "2013-10-16T20:08:52Z",
    "closed_at": "2013-10-16T20:08:52Z",
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/77",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/77",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/77.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/77.patch"
    },
    "body": "we have this type of config:\r\n\r\n```ruby\r\ndevelopment: &development\r\n  database: foo\r\n\r\nbenchmark: &benchmark\r\n  database: foo\r\n```\r\n\r\nwhen dropping all it throws an exception as foo was dropped already. "
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/76",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/76/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/76/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/76/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/76",
    "id": 19410987,
    "number": 76,
    "title": "Update .travis.yml",
    "user": {
      "login": "arthurnn",
      "id": 833383,
      "avatar_url": "https://avatars.githubusercontent.com/u/833383?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/arthurnn",
      "html_url": "https://github.com/arthurnn",
      "followers_url": "https://api.github.com/users/arthurnn/followers",
      "following_url": "https://api.github.com/users/arthurnn/following{/other_user}",
      "gists_url": "https://api.github.com/users/arthurnn/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/arthurnn/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/arthurnn/subscriptions",
      "organizations_url": "https://api.github.com/users/arthurnn/orgs",
      "repos_url": "https://api.github.com/users/arthurnn/repos",
      "events_url": "https://api.github.com/users/arthurnn/events{/privacy}",
      "received_events_url": "https://api.github.com/users/arthurnn/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2013-09-12T19:59:31Z",
    "updated_at": "2013-09-12T20:23:12Z",
    "closed_at": "2013-09-12T20:22:48Z",
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/76",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/76",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/76.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/76.patch"
    },
    "body": "use RAILS_VERSION=3.2.14 on travis."
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/75",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/75/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/75/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/75/events",
    "html_url": "https://github.com/kovyrin/db-charmer/pull/75",
    "id": 19130612,
    "number": 75,
    "title": "Update rails version limits to 3.2.14",
    "user": {
      "login": "beedub",
      "id": 102646,
      "avatar_url": "https://avatars.githubusercontent.com/u/102646?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/beedub",
      "html_url": "https://github.com/beedub",
      "followers_url": "https://api.github.com/users/beedub/followers",
      "following_url": "https://api.github.com/users/beedub/following{/other_user}",
      "gists_url": "https://api.github.com/users/beedub/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/beedub/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/beedub/subscriptions",
      "organizations_url": "https://api.github.com/users/beedub/orgs",
      "repos_url": "https://api.github.com/users/beedub/repos",
      "events_url": "https://api.github.com/users/beedub/events{/privacy}",
      "received_events_url": "https://api.github.com/users/beedub/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 1,
    "created_at": "2013-09-06T21:56:18Z",
    "updated_at": "2013-09-06T21:58:53Z",
    "closed_at": "2013-09-06T21:58:48Z",
    "pull_request": {
      "url": "https://api.github.com/repos/kovyrin/db-charmer/pulls/75",
      "html_url": "https://github.com/kovyrin/db-charmer/pull/75",
      "diff_url": "https://github.com/kovyrin/db-charmer/pull/75.diff",
      "patch_url": "https://github.com/kovyrin/db-charmer/pull/75.patch"
    },
    "body": ""
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/74",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/74/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/74/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/74/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/74",
    "id": 16779471,
    "number": 74,
    "title": "hasone relationship does not seem to work with db-charmer",
    "user": {
      "login": "bobbarjung",
      "id": 1243200,
      "avatar_url": "https://avatars.githubusercontent.com/u/1243200?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/bobbarjung",
      "html_url": "https://github.com/bobbarjung",
      "followers_url": "https://api.github.com/users/bobbarjung/followers",
      "following_url": "https://api.github.com/users/bobbarjung/following{/other_user}",
      "gists_url": "https://api.github.com/users/bobbarjung/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/bobbarjung/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/bobbarjung/subscriptions",
      "organizations_url": "https://api.github.com/users/bobbarjung/orgs",
      "repos_url": "https://api.github.com/users/bobbarjung/repos",
      "events_url": "https://api.github.com/users/bobbarjung/events{/privacy}",
      "received_events_url": "https://api.github.com/users/bobbarjung/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 0,
    "created_at": "2013-07-15T21:16:41Z",
    "updated_at": "2014-06-11T21:06:07Z",
    "closed_at": null,
    "body": "I have a has_one relationship between A and B\r\n\r\n```ruby\r\nclass A < ActiveRecord::Base\r\n  has_one b\r\nend\r\n\r\nclass B < ActiveRecord::Base\r\n  belongs_to a\r\nend\r\n```\r\n\r\nI want to access the associations on a secondary db. (Called recovery) using db-charmer.\r\n\r\n```ruby\r\nb = B.on_db(:recovery).find(b_id) # works\r\nb.on_db(:recovery).a # works. a is not nil.\r\n\r\na = A.on_db(:recovery).find(a_id) # works.\r\na.on_db(:recovery).b # does not work,\r\n```\r\n...as it tries to lookup the main db and not the recovery database for the reverse lookup. I am guessing has_many also will not work? I am using db-charmer version 1.8.4.\r\n\r\nThank you for your help."
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/73",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/73/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/73/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/73/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/73",
    "id": 16121766,
    "number": 73,
    "title": "Multi-Threading: with_remapped_databases fails to remap classes",
    "user": {
      "login": "chadrem",
      "id": 22150,
      "avatar_url": "https://avatars.githubusercontent.com/u/22150?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/chadrem",
      "html_url": "https://github.com/chadrem",
      "followers_url": "https://api.github.com/users/chadrem/followers",
      "following_url": "https://api.github.com/users/chadrem/following{/other_user}",
      "gists_url": "https://api.github.com/users/chadrem/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/chadrem/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/chadrem/subscriptions",
      "organizations_url": "https://api.github.com/users/chadrem/orgs",
      "repos_url": "https://api.github.com/users/chadrem/repos",
      "events_url": "https://api.github.com/users/chadrem/events{/privacy}",
      "received_events_url": "https://api.github.com/users/chadrem/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [
      {
        "url": "https://api.github.com/repos/kovyrin/db-charmer/labels/reproducible-issue",
        "name": "reproducible-issue",
        "color": "e10c02"
      }
    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 4,
    "created_at": "2013-06-28T00:27:00Z",
    "updated_at": "2014-06-11T21:01:35Z",
    "closed_at": "2014-06-11T21:01:35Z",
    "body": "I started digging into the problem and noticed that new threads are unable to find the map.  Because of this, no classes get re-mapped and thus look for data in the wrong database.\r\n\r\n#### Main thread works correctly (it finds the map).\r\n>> puts ::ActiveRecord::Base.db_charmer_database_remappings.inspect\r\n{:limbo=>:realm_0}\r\n\r\n#### New threads don't work (unable to find the above map).\r\n>> Thread.new { puts ::ActiveRecord::Base.db_charmer_database_remappings.inspect }\r\n{}"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/72",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/72/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/72/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/72/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/72",
    "id": 15789793,
    "number": 72,
    "title": "Difference in schemas between master and slave affects whole app.",
    "user": {
      "login": "andriytyurnikov",
      "id": 3668,
      "avatar_url": "https://avatars.githubusercontent.com/u/3668?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/andriytyurnikov",
      "html_url": "https://github.com/andriytyurnikov",
      "followers_url": "https://api.github.com/users/andriytyurnikov/followers",
      "following_url": "https://api.github.com/users/andriytyurnikov/following{/other_user}",
      "gists_url": "https://api.github.com/users/andriytyurnikov/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/andriytyurnikov/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/andriytyurnikov/subscriptions",
      "organizations_url": "https://api.github.com/users/andriytyurnikov/orgs",
      "repos_url": "https://api.github.com/users/andriytyurnikov/repos",
      "events_url": "https://api.github.com/users/andriytyurnikov/events{/privacy}",
      "received_events_url": "https://api.github.com/users/andriytyurnikov/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 1,
    "created_at": "2013-06-20T09:39:08Z",
    "updated_at": "2013-11-10T15:49:36Z",
    "closed_at": "2013-11-10T15:49:36Z",
    "body": "We had long-running migration on db master (lhm gem), and as one might expect there was some delay between master and slave.\r\nSo when migration finished on master, but was in progress on slave - we had different schemas.\r\nUnexpected surprise is that this difference affected parts of the app which do not use slave connection.\r\n\r\nMysql2::Error: Unknown column 'referrer' in 'field list': INSERT INTO `purchases` (`coupon_code`, `created_at`, `customer_id`, `dont_redeem`, `email`, `encrypted_email`, `ip_address`, `order_date`, `order_number`, `referrer`, `site_id`, `subtotal`, `updated_at`, `visitor_id`) VALUES ('CODE42', '2013-06-19 12:19:51', NULL, 0, 'email@gmail.com', NULL, '127.0.0.1', '2013-06-19 12:19:51', '100379070', NULL, 1887, 123.2, '2013-06-19 12:19:51', 26179393)\r\n\r\nAt the moment of the exception raise referrer column was present on master, but was not present on slave. Unexpected surprise here, is that controller, which raised this exception does not use db-charmer slave. Somehow db-charmer slave connection affects operations on master connection (schema info cached somewhere by activerecord?)"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/71",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/71/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/71/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/71/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/71",
    "id": 15777336,
    "number": 71,
    "title": "Forcing writes to master in bang methods (create!, etc)",
    "user": {
      "login": "kpumuk",
      "id": 10163,
      "avatar_url": "https://avatars.githubusercontent.com/u/10163?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/kpumuk",
      "html_url": "https://github.com/kpumuk",
      "followers_url": "https://api.github.com/users/kpumuk/followers",
      "following_url": "https://api.github.com/users/kpumuk/following{/other_user}",
      "gists_url": "https://api.github.com/users/kpumuk/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/kpumuk/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/kpumuk/subscriptions",
      "organizations_url": "https://api.github.com/users/kpumuk/orgs",
      "repos_url": "https://api.github.com/users/kpumuk/repos",
      "events_url": "https://api.github.com/users/kpumuk/events{/privacy}",
      "received_events_url": "https://api.github.com/users/kpumuk/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [
      {
        "url": "https://api.github.com/repos/kovyrin/db-charmer/labels/reproducible-issue",
        "name": "reproducible-issue",
        "color": "e10c02"
      }
    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 1,
    "created_at": "2013-06-20T01:27:59Z",
    "updated_at": "2013-06-20T01:31:16Z",
    "closed_at": null,
    "body": "Currently db-charmer forces writes to master for `create`, `update`, `delete`, and some other ActiveRecord methods. Unfortunately, `create!` does not get forced to use master:\r\n\r\n    ree-1.8.7-2012.02 >> TestModel.on_db(:slave).create\r\n      SQL (0.2ms)   BEGIN\r\n    \r\n    ree-1.8.7-2012.02 >> TestModel.on_db(:slave).create!\r\n      [slave]   SQL (0.1ms)   BEGIN\r\n\r\nIt seems like problematic code is in `master_slave_routing.rb` for Rails 2.x"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/70",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/70/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/70/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/70/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/70",
    "id": 15004735,
    "number": 70,
    "title": "Support for sharing a connection to same server / switching databases as necessary",
    "user": {
      "login": "boourns",
      "id": 699550,
      "avatar_url": "https://avatars.githubusercontent.com/u/699550?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/boourns",
      "html_url": "https://github.com/boourns",
      "followers_url": "https://api.github.com/users/boourns/followers",
      "following_url": "https://api.github.com/users/boourns/following{/other_user}",
      "gists_url": "https://api.github.com/users/boourns/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/boourns/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/boourns/subscriptions",
      "organizations_url": "https://api.github.com/users/boourns/orgs",
      "repos_url": "https://api.github.com/users/boourns/repos",
      "events_url": "https://api.github.com/users/boourns/events{/privacy}",
      "received_events_url": "https://api.github.com/users/boourns/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "open",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 2,
    "created_at": "2013-05-31T17:41:34Z",
    "updated_at": "2013-05-31T18:48:02Z",
    "closed_at": null,
    "body": "We're considering putting multiple logical databases on the same physical server.  \r\n\r\nIf we do that we will hit an issue where every app worker will have many connections to the same mysql server and reach the point of having context switching issues from the mysql perspective.\r\n\r\nWhat do you think about reusing db_charmer connections when there is multiple logical databases on the same physical server?\r\n\r\nIf this is not something you can add we may be doing it at Shopify and would be interested in your view on this & what you would consider to be the best approach.\r\n\r\nThanks\r\nTom"
  },
  {
    "url": "https://api.github.com/repos/kovyrin/db-charmer/issues/69",
    "labels_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/69/labels{/name}",
    "comments_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/69/comments",
    "events_url": "https://api.github.com/repos/kovyrin/db-charmer/issues/69/events",
    "html_url": "https://github.com/kovyrin/db-charmer/issues/69",
    "id": 14541052,
    "number": 69,
    "title": "execution expired - timing out getting connections - multi-threading issue",
    "user": {
      "login": "dashbitla",
      "id": 114106,
      "avatar_url": "https://avatars.githubusercontent.com/u/114106?v=3",
      "gravatar_id": "",
      "url": "https://api.github.com/users/dashbitla",
      "html_url": "https://github.com/dashbitla",
      "followers_url": "https://api.github.com/users/dashbitla/followers",
      "following_url": "https://api.github.com/users/dashbitla/following{/other_user}",
      "gists_url": "https://api.github.com/users/dashbitla/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/dashbitla/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/dashbitla/subscriptions",
      "organizations_url": "https://api.github.com/users/dashbitla/orgs",
      "repos_url": "https://api.github.com/users/dashbitla/repos",
      "events_url": "https://api.github.com/users/dashbitla/events{/privacy}",
      "received_events_url": "https://api.github.com/users/dashbitla/received_events",
      "type": "User",
      "site_admin": false
    },
    "labels": [

    ],
    "state": "closed",
    "locked": false,
    "assignee": null,
    "milestone": null,
    "comments": 2,
    "created_at": "2013-05-20T21:43:35Z",
    "updated_at": "2013-11-10T15:52:05Z",
    "closed_at": "2013-11-10T15:52:05Z",
    "body": "2013-05-20T21:29:11Z 6058 TID-osusvs4o8 WARN: execution expired\r\n2013-05-20T21:29:11Z 6058 TID-osusvs4o8 WARN: /home/deployer/.rvm/rubies/ruby-1.9.3-p429/lib/ruby/1.9.1/monitor.rb:185:in `lock'\r\n/home/deployer/.rvm/rubies/ruby-1.9.3-p429/lib/ruby/1.9.1/monitor.rb:185:in `mon_enter'\r\n/home/deployer/.rvm/rubies/ruby-1.9.3-p429/lib/ruby/1.9.1/monitor.rb:209:in `mon_synchronize'\r\n/home/deployer/apps/testapp.com/shared/bundle/ruby/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/connection_pool.rb:95:in `connection'\r\n/home/deployer/apps/testapp.com/shared/bundle/ruby/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/connection_pool.rb:404:in `retrieve_connection'\r\n/home/deployer/apps/testapp.com/shared/bundle/ruby/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/connection_specification.rb:170:in `retrieve_connection'\r\n/home/deployer/apps/testapp.com/shared/bundle/ruby/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/connection_specification.rb:144:in `connection'\r\n/home/deployer/apps/testapp.com/releases/20130519223524/vendor/gems/db-charmer-1.9.0/lib/db_charmer/active_record/connection_switching.rb:34:in `connection_with_magic'\r\n/home/deployer/apps/testapp.com/releases/20130519223524/vendor/gems/db-charmer-1.9.0/lib/db_charmer/rails3/active_record/relation_method.rb:15:in `block in relation_with_db_charmer'\r\n/home/deployer/apps/testapp.com/releases/20130519223524/vendor/gems/db-charmer-1.9.0/lib/db_charmer/rails3/active_record/relation_method.rb:14:in `tap'\r\n/home/deployer/apps/testapp.com/releases/20130519223524/vendor/gems/db-charmer-1.9.0/lib/db_charmer/rails3/active_record/relation_method.rb:14:in `relation_with_db_charmer'\r\n/home/deployer/apps/testapp.com/shared/bundle/ruby/1.9.1/gems/activerecord-3.2.8/lib/active_record/scoping/named.rb:37:in `scoped'\r\n/home/deployer/apps/testapp.com/shared/bundle/ruby/1.9.1/gems/activerecord-3.2.8/lib/active_record/querying.rb:9:in `select'\r\n/home/deployer/apps/testapp.com/releases/20130519223524/app/models/api_callback.rb:12:in `push'\r\n/home/deployer/apps/testapp.com/releases/20130519223524/app/workers/kiq_agent_callback.rb:9:in `perform'\r\n/home/deployer/apps/testapp.com/shared/bundle/ruby/1.9.1/gems/sidekiq-2.9.0/lib/sidekiq/processor.rb:49:in `block (3 levels)\r\n\r\n"
  }
]


================================================
FILE: lib/db_charmer/action_controller/force_slave_reads.rb
================================================
module DbCharmer
  module ActionController
    module ForceSlaveReads

      module ClassMethods
        @@db_charmer_force_slave_reads_actions = {}
        def force_slave_reads(params = {})
          @@db_charmer_force_slave_reads_actions[self.name] = {
            :except => params[:except] ? [*params[:except]].map(&:to_s) : [],
            :only => params[:only] ? [*params[:only]].map(&:to_s) : []
          }
        end

        def force_slave_reads_options
          @@db_charmer_force_slave_reads_actions[self.name]
        end

        def force_slave_reads_action?(name = nil)
          name = name.to_s

          options = force_slave_reads_options
          # If no options were defined for this controller, all actions are not forced to use slaves
          return false unless options

          # Actions where force_slave_reads mode was turned off
          return false if options[:except].include?(name)

          # Only for these actions force_slave_reads was turned on
          return options[:only].include?(name) if options[:only].any?

          # If :except is not empty, we're done with the checks and rest of the actions are should force slave reads
          # Otherwise, all the actions are not in force_slave_reads mode
          options[:except].any?
        end
      end

      module InstanceMethods
        DISPATCH_METHOD = (DbCharmer.rails3?) ? :process_action : :perform_action

        def self.included(base)
          base.alias_method_chain DISPATCH_METHOD, :forced_slave_reads
        end

        def force_slave_reads!
          @db_charmer_force_slave_reads = true
        end

        def dont_force_slave_reads!
          @db_charmer_force_slave_reads = false
        end

        def force_slave_reads?
          @db_charmer_force_slave_reads || self.class.force_slave_reads_action?(params[:action])
        end

      protected

        class_eval <<-EOF, __FILE__, __LINE__+1
          def #{DISPATCH_METHOD}_with_forced_slave_reads(*args, &block)
            DbCharmer.with_controller(self) do
              #{DISPATCH_METHOD}_without_forced_slave_reads(*args, &block)
            end
          end
        EOF
      end

    end
  end
end


================================================
FILE: lib/db_charmer/active_record/association_preload.rb
================================================
module DbCharmer
  module ActiveRecord
    module AssociationPreload
      ASSOCIATION_TYPES = [ :has_one, :has_many, :belongs_to, :has_and_belongs_to_many ]

      def self.extended(base)
        ASSOCIATION_TYPES.each do |association_type|
          base.class_eval <<-EOF, __FILE__, __LINE__ + 1
            def self.preload_#{association_type}_association(records, reflection, preload_options = {})
              if self.db_charmer_top_level_connection? || reflection.options[:polymorphic] ||
                    self.db_charmer_default_connection != reflection.klass.db_charmer_default_connection
                return super(records, reflection, preload_options)
              end
              reflection.klass.on_db(self) do
                super(records, reflection, preload_options)
              end
            end
          EOF
        end
      end
    end
  end
end


================================================
FILE: lib/db_charmer/active_record/class_attributes.rb
================================================
module DbCharmer
  module ActiveRecord
    module ClassAttributes
      @@db_charmer_opts = {}
      def db_charmer_opts=(opts)
        @@db_charmer_opts[self.name] = opts
      end

      def db_charmer_opts
        @@db_charmer_opts[self.name] || {}
      end

      #---------------------------------------------------------------------------------------------
      @@db_charmer_default_connections = {}
      def db_charmer_default_connection=(conn)
        @@db_charmer_default_connections[self.name] = conn
      end

      def db_charmer_default_connection
        @@db_charmer_default_connections[self.name]
      end

      #---------------------------------------------------------------------------------------------
      @@db_charmer_slaves = {}
      def db_charmer_slaves=(slaves)
        @@db_charmer_slaves[self.name] = slaves
      end

      def db_charmer_slaves
        @@db_charmer_slaves[self.name] || []
      end

      # Returns a random connection from the list of slaves configured for this AR class
      def db_charmer_random_slave
        return nil unless db_charmer_slaves.any?
        db_charmer_slaves[rand(db_charmer_slaves.size)]
      end

      #---------------------------------------------------------------------------------------------
      def db_charmer_connection_proxies
        Thread.current[:db_charmer_connection_proxies] ||= {}
      end

      def db_charmer_connection_proxy=(proxy)
        db_charmer_connection_proxies[self.name] = proxy
      end

      def db_charmer_connection_proxy
        db_charmer_connection_proxies[self.name]
      end

      #---------------------------------------------------------------------------------------------
      def db_charmer_force_slave_reads_flags
        Thread.current[:db_charmer_force_slave_reads] ||= {}
      end

      def db_charmer_force_slave_reads=(force)
        db_charmer_force_slave_reads_flags[self.name] = force
      end

      def db_charmer_force_slave_reads
        db_charmer_force_slave_reads_flags[self.name]
      end

      # Slave reads are used in two cases:
      #  - per-model slave reads are enabled (see db_magic method for more details)
      #  - global slave reads enforcing is enabled (in a controller action)
      def db_charmer_force_slave_reads?
        db_charmer_force_slave_reads || DbCharmer.force_slave_reads?
      end

      #---------------------------------------------------------------------------------------------
      def db_charmer_connection_levels
        Thread.current[:db_charmer_connection_levels] ||= Hash.new(0)
      end

      def db_charmer_connection_level=(level)
        db_charmer_connection_levels[self.name] = level
      end

      def db_charmer_connection_level
        db_charmer_connection_levels[self.name] || 0
      end

      def db_charmer_top_level_connection?
        db_charmer_connection_level.zero?
      end

      #---------------------------------------------------------------------------------------------
      def db_charmer_remapped_connection
        return nil unless db_charmer_top_level_connection?
        name = :master
        proxy = db_charmer_model_connection_proxy
        name = proxy.db_charmer_connection_name.to_sym if proxy

        remapped = db_charmer_database_remappings[name]
        remapped ? DbCharmer::ConnectionFactory.connect(remapped, true) : nil
      end

      def db_charmer_database_remappings
        Thread.current[:db_charmer_database_remappings] ||= Hash.new
      end

      def db_charmer_database_remappings=(mappings)
        raise "Mappings must be nil or respond to []" if mappings && (! mappings.respond_to?(:[]))
        Thread.current[:db_charmer_database_remappings] = mappings || {}
      end

      #---------------------------------------------------------------------------------------------
      # Returns model-specific connection proxy, ignoring any global connection remappings
      def db_charmer_model_connection_proxy
        db_charmer_connection_proxy || db_charmer_default_connection
      end
    end
  end
end


================================================
FILE: lib/db_charmer/active_record/connection_switching.rb
================================================
module DbCharmer
  module ActiveRecord
    module ConnectionSwitching
      def establish_real_connection_if_exists(name, should_exist = false)
        name = name.to_s

        # Check environment name
        config = configurations[DbCharmer.env]
        unless config
          error = "Invalid environment name (does not exist in database.yml): #{DbCharmer.env}. Please set correct Rails.env or DbCharmer.env."
          raise ArgumentError, error
        end

        # Check connection name
        config = config[name]
        unless config
          if should_exist
            raise ArgumentError, "Invalid connection name (does not exist in database.yml): #{DbCharmer.env}/#{name}"
          end
          return # No need to establish connection - they do not want us to
        end

        # Pass connection name with config
        config[:connection_name] = name
        establish_connection(config)
      end

      #-----------------------------------------------------------------------------------------------------------------
      def hijack_connection!
        return if self.respond_to?(:connection_with_magic)
        class << self
          # Make sure we check our accessors before going to the default connection retrieval method
          def connection_with_magic
            db_charmer_remapped_connection || db_charmer_model_connection_proxy || connection_without_magic
          end
          alias_method_chain :connection, :magic

          def connection_pool_with_magic
            if connection.respond_to?(:abstract_connection_class)
              abstract_connection_class = connection.abstract_connection_class
              connection_handler.retrieve_connection_pool(abstract_connection_class) || connection_pool_without_magic
            else
              connection_pool_without_magic
            end
          end
          alias_method_chain :connection_pool, :magic
        end
      end

      #-----------------------------------------------------------------------------------------------------------------
      def coerce_to_connection_proxy(conn, should_exist = true)
        # Return nil if given no connection specification
        return nil if conn.nil?

        # For sharded proxies just use them as-is
        return conn if conn.respond_to?(:set_real_connection)

        # For connection proxies and objects that could be coerced into a proxy just call the coercion method
        return conn.db_charmer_connection_proxy if conn.respond_to?(:db_charmer_connection_proxy)

        # For plain AR connection adapters, just use them as-is
        return conn if conn.kind_of?(::ActiveRecord::ConnectionAdapters::AbstractAdapter)

        # For connection names, use connection factory to create new connections
        if conn.kind_of?(Symbol) || conn.kind_of?(String)
          return DbCharmer::ConnectionFactory.connect(conn, should_exist)
        end

        # For connection configs (hashes), create connections
        if conn.kind_of?(Hash)
          conn = conn.symbolize_keys
          raise ArgumentError, "Missing required :connection_name parameter" unless conn[:connection_name]
          return DbCharmer::ConnectionFactory.connect_to_db(conn[:connection_name], conn)
        end

        # Fails for unsupported connection types
        raise "Unsupported connection type: #{conn.class}"
      end

      #-----------------------------------------------------------------------------------------------------------------
      def switch_connection_to(conn, should_exist = true)
        new_conn = coerce_to_connection_proxy(conn, should_exist)

        if db_charmer_connection_proxy.respond_to?(:set_real_connection)
          db_charmer_connection_proxy.set_real_connection(new_conn)
        end

        self.db_charmer_connection_proxy = new_conn
        self.hijack_connection!
      end

    end
  end
end


================================================
FILE: lib/db_charmer/active_record/db_magic.rb
================================================
module DbCharmer
  module ActiveRecord
    module DbMagic

      def db_magic(opt = {})
        # Make sure we could use our connections management here
        hijack_connection!

        # Should requested connections exist in the config?
        should_exist = opt.has_key?(:should_exist) ? opt[:should_exist] : DbCharmer.connections_should_exist?

        # Main connection management
        setup_connection_magic(opt[:connection], should_exist)

        # Set up slaves pool
        opt[:slaves] ||= []
        opt[:slaves] = [ opt[:slaves] ].flatten
        opt[:slaves] << opt[:slave] if opt[:slave]

        # Forced reads are enabled for all models by default, could be disabled by the user
        forced_slave_reads = opt.has_key?(:force_slave_reads) ? opt[:force_slave_reads] : true

        # Setup all the slaves related magic if needed
        setup_slaves_magic(opt[:slaves], forced_slave_reads, should_exist)

        # Setup inheritance magic
        setup_children_magic(opt)

        # Setup sharding if needed
        if opt[:sharded]
          raise ArgumentError, "Can't use sharding on a model with slaves!" if opt[:slaves].any?
          setup_sharding_magic(opt[:sharded])
        end
      end

    private

      def setup_children_magic(opt)
        self.db_charmer_opts = opt.clone

        unless self.respond_to?(:inherited_with_db_magic)
          class << self
            def inherited_with_db_magic(child)
              o = inherited_without_db_magic(child)
              child.db_magic(self.db_charmer_opts)
              o
            end
            alias_method_chain :inherited, :db_magic
          end
        end
      end

      def setup_sharding_magic(config)
        # Add sharding-specific methods
        self.extend(DbCharmer::ActiveRecord::Sharding)

        # Get configuration
        name = config[:sharded_connection] or raise ArgumentError, "No :sharded_connection!"
        # Assign sharded connection
        self.sharded_connection = DbCharmer::Sharding.sharded_connection(name)

        # Setup model default connection
        setup_connection_magic(sharded_connection.default_connection)
      end

      def setup_connection_magic(conn, should_exist = true)
        conn_proxy = coerce_to_connection_proxy(conn, should_exist)
        self.db_charmer_default_connection = conn_proxy
        switch_connection_to(conn_proxy, should_exist)
      end

      def setup_slaves_magic(slaves, force_slave_reads, should_exist = true)
        self.db_charmer_force_slave_reads = force_slave_reads

        # Initialize the slave connections list
        self.db_charmer_slaves = slaves.collect do |slave|
          coerce_to_connection_proxy(slave, should_exist)
        end
        return if db_charmer_slaves.empty?

        # Enable on_slave/on_master methods
        self.extend(DbCharmer::ActiveRecord::MultiDbProxy::MasterSlaveClassMethods)

        # Enable automatic master/slave queries routing (we have specialized versions on those modules for rails2/3)
        self.extend(DbCharmer::ActiveRecord::MasterSlaveRouting::ClassMethods)
        self.send(:include, DbCharmer::ActiveRecord::MasterSlaveRouting::InstanceMethods)
      end

    end
  end
end


================================================
FILE: lib/db_charmer/active_record/migration/multi_db_migrations.rb
================================================
module DbCharmer
  module ActiveRecord
    module Migration
      module MultiDbMigrations

        def self.append_features(base)
          return false if base < self
          super
          base.extend const_get("ClassMethods") if const_defined?("ClassMethods")

          base.class_eval do
            if DbCharmer.rails31?
              alias_method_chain :migrate, :db_wrapper
            else
              class << self
                alias_method_chain :migrate, :db_wrapper
              end
            end
          end
        end

        module ClassMethods
          @@multi_db_names = {}
          def multi_db_names
            @@multi_db_names[self.name] || @@multi_db_names['ActiveRecord::Migration']
          end

          def multi_db_names=(names)
            @@multi_db_names[self.name] = names
          end

          unless DbCharmer.rails31?
            def migrate_with_db_wrapper(direction)
              if names = multi_db_names
                names.each do |multi_db_name|
                  on_db(multi_db_name) do
                    migrate_without_db_wrapper(direction)
                  end
                end
              else
                migrate_without_db_wrapper(direction)
              end
            end

            def on_db(db_name)
              name = db_name.is_a?(Hash) ? db_name[:connection_name] : db_name.inspect
              announce "Switching connection to #{name}"
              # Switch connection
              old_proxy = ::ActiveRecord::Base.db_charmer_connection_proxy
              db_name = nil if db_name == :default
              ::ActiveRecord::Base.switch_connection_to(db_name, DbCharmer.connections_should_exist?)
              # Yield the block
              yield
            ensure
              # Switch it back
              ::ActiveRecord::Base.verify_active_connections!
              announce "Switching connection back"
              ::ActiveRecord::Base.switch_connection_to(old_proxy)
            end
          end

          def db_magic(opts = {})
            # Collect connections from all possible options
            conns = [ opts[:connection], opts[:connections] ]
            conns << shard_connections(opts[:sharded_connection]) if opts[:sharded_connection]

            # Get a unique set of connections
            conns = conns.flatten.compact.uniq
            raise ArgumentError, "No connection name - no magic!" unless conns.any?

            # Save connections
            self.multi_db_names = conns
          end

          # Return a list of connections to shards in a sharded connection
          def shard_connections(conn_name)
            conn = DbCharmer::Sharding.sharded_connection(conn_name)
            conn.shard_connections
          end
        end

        def migrate_with_db_wrapper(direction)
          if names = self.class.multi_db_names
            names.each do |multi_db_name|
              on_db(multi_db_name) do
                migrate_without_db_wrapper(direction)
              end
            end
          else
            migrate_without_db_wrapper(direction)
          end
        end

        def record_on_db(db_name, block)
          recorder = ::ActiveRecord::Migration::CommandRecorder.new(DbCharmer::ConnectionFactory.connect(db_name))
          old_recorder, @connection = @connection, recorder
          block.call
          old_recorder.record :on_db, [db_name, @connection]
          @connection = old_recorder
        end

        def replay_commands_on_db(name, commands)
          on_db(name) do
            commands.each do |cmd, args|
              send(cmd, *args)
            end
          end
        end

        def on_db(db_name, &block)
          if @connection.is_a?(::ActiveRecord::Migration::CommandRecorder)
            record_on_db(db_name, block)
            return
          end

          name = db_name.is_a?(Hash) ? db_name[:connection_name] : db_name.inspect
          announce "Switching connection to #{name}"
          # Switch connection
          old_connection, old_proxy = @connection, ::ActiveRecord::Base.db_charmer_connection_proxy
          db_name = nil if db_name == :default
          ::ActiveRecord::Base.switch_connection_to(db_name, DbCharmer.connections_should_exist?)
          # Yield the block
          ::ActiveRecord::Base.connection_pool.with_connection do |conn|
            @connection = conn
            yield
          end
        ensure
          @connection = old_connection
          # Switch it back
          ::ActiveRecord::Base.verify_active_connections!
          announce "Switching connection back"
          ::ActiveRecord::Base.switch_connection_to(old_proxy)
        end
      end
    end
  end
end


================================================
FILE: lib/db_charmer/active_record/multi_db_proxy.rb
================================================
module DbCharmer
  module ActiveRecord
    module MultiDbProxy
      # Simple proxy class that switches connections and then proxies all the calls
      # This class is used to implement chained on_db calls
      class OnDbProxy < ActiveSupport::BasicObject
        # We need to do this because in Rails 2.3 BasicObject does not remove object_id method, which is stupid
        undef_method(:object_id) if instance_methods.member?('object_id')

        def initialize(proxy_target, slave)
          @proxy_target = proxy_target
          @slave = slave
        end

      private

        def method_missing(meth, *args, &block)
          # Switch connection and proxy the method call
          @proxy_target.on_db(@slave) do |proxy_target|
            res = proxy_target.__send__(meth, *args, &block)

            # If result is a scope/association, return a new proxy for it, otherwise return the result itself
            (res.proxy?) ? OnDbProxy.new(res, @slave) : res
          end
        end
      end

      module ClassMethods
        def on_db(con, proxy_target = nil)
          proxy_target ||= self

          # Chain call
          return OnDbProxy.new(proxy_target, con) unless block_given?

          # Block call
          begin
            self.db_charmer_connection_level += 1
            old_proxy = db_charmer_connection_proxy
            switch_connection_to(con, DbCharmer.connections_should_exist?)
            yield(proxy_target)
          ensure
            switch_connection_to(old_proxy)
            self.db_charmer_connection_level -= 1
          end
        end
      end

      module InstanceMethods
        def on_db(con, proxy_target = nil, &block)
          proxy_target ||= self
          self.class.on_db(con, proxy_target, &block)
        end
      end

      module MasterSlaveClassMethods
        def on_slave(con = nil, proxy_target = nil, &block)
          con ||= db_charmer_random_slave
          raise ArgumentError, "No slaves found in the class and no slave connection given" unless con
          on_db(con, proxy_target, &block)
        end

        def on_master(proxy_target = nil, &block)
          on_db(db_charmer_default_connection, proxy_target, &block)
        end

        def first_level_on_slave
          first_level = db_charmer_top_level_connection? && on_master.connection.open_transactions.zero?
          if first_level && db_charmer_force_slave_reads? && db_charmer_slaves.any?
            on_slave { yield }
          else
            yield
          end
        end
      end
    end
  end
end


================================================
FILE: lib/db_charmer/active_record/sharding.rb
================================================
module DbCharmer
  module ActiveRecord
    module Sharding

      def self.extended(model)
        model.cattr_accessor(:sharded_connection)
      end

      def shard_for(key, proxy_target = nil, &block)
        raise ArgumentError, "No sharded connection configured!" unless sharded_connection
        conn = sharded_connection.sharder.shard_for_key(key)
        on_db(conn, proxy_target, &block)
      end

      # Run on default shard (if supported by the sharding method)
      def on_default_shard(proxy_target = nil, &block)
        raise ArgumentError, "No sharded connection configured!" unless sharded_connection

        if sharded_connection.support_default_shard?
          shard_for(:default, proxy_target, &block)
        else
          raise ArgumentError, "This model's sharding method does not support default shard"
        end
      end

      # Enumerate shards
      def on_each_shard(proxy_target = nil, &block)
        raise ArgumentError, "No sharded connection configured!" unless sharded_connection

        conns = sharded_connection.shard_connections
        raise ArgumentError, "This model's sharding method does not support shards enumeration" unless conns

        conns.each do |conn|
          on_db(conn, proxy_target, &block)
        end
      end

    end
  end
end


================================================
FILE: lib/db_charmer/connection_factory.rb
================================================
#
# This class is used to automatically generate small abstract ActiveRecord classes
# that would then be used as a source of database connections for DbCharmer magic.
# This way we do not need to re-implement all the connection establishing code
# that ActiveRecord already has and we make our code less dependant on Rails versions.
#
module DbCharmer
  module ConnectionFactory
    def self.connection_classes
      Thread.current[:db_charmer_generated_connection_classes] ||= {}
    end

    def self.connection_classes=(val)
      Thread.current[:db_charmer_generated_connection_classes] = val
    end

    def self.reset!
      self.connection_classes = {}
    end

    # Establishes connection or return an existing one from cache
    def self.connect(connection_name, should_exist = true)
      connection_name = connection_name.to_s
      connection_classes[connection_name] ||= establish_connection(connection_name, should_exist)
    end

    # Establishes connection or return an existing one from cache (not using AR database configs)
    def self.connect_to_db(connection_name, config)
      connection_name = connection_name.to_s
      connection_classes[connection_name] ||= establish_connection_to_db(connection_name, config)
    end

    # Establish connection with a specified name
    def self.establish_connection(connection_name, should_exist = true)
      abstract_class = generate_abstract_class(connection_name, should_exist)
      DbCharmer::ConnectionProxy.new(abstract_class, connection_name)
    end

    # Establish connection with a specified name (not using AR database configs)
    def self.establish_connection_to_db(connection_name, config)
      abstract_class = generate_abstract_class_for_db(connection_name, config)
      DbCharmer::ConnectionProxy.new(abstract_class, connection_name)
    end

    # Generate an abstract AR class with specified connection established
    def self.generate_abstract_class(connection_name, should_exist = true)
      # Generate class
      klass = generate_empty_abstract_ar_class(abstract_connection_class_name(connection_name))

      # Establish connection
      klass.establish_real_connection_if_exists(connection_name.to_sym, !!should_exist)

      # Return the class
      return klass
    end

    # Generate an abstract AR class with specified connection established (not using AR database configs)
    def self.generate_abstract_class_for_db(connection_name, config)
      # Generate class
      klass = generate_empty_abstract_ar_class(abstract_connection_class_name(connection_name))

      # Establish connection
      klass.establish_connection(config)

      # Return the class
      return klass
    end

    def self.generate_empty_abstract_ar_class(klass)
      # Define class
      module_eval "class #{klass} < ::ActiveRecord::Base; self.abstract_class = true; end"

      # Return class
      klass.constantize
    end

    # Generates unique names for our abstract AR classes
    def self.abstract_connection_class_name(connection_name)
      conn_name_klass = connection_name.to_s.gsub(/\W+/, '_').camelize
      thread = Thread.current.object_id.abs # need to make sure it is non-negative
      "::AutoGeneratedAbstractConnectionClass#{conn_name_klass}ForThread#{thread}"
    end
  end
end


================================================
FILE: lib/db_charmer/connection_proxy.rb
================================================
# Simple proxy that sends all method calls to a real database connection
module DbCharmer
  class ConnectionProxy < ActiveSupport::BasicObject
    # We need to do this because in Rails 2.3 BasicObject does not remove object_id method, which is stupid
    undef_method(:object_id) if instance_methods.member?('object_id')

    # We use this to get a connection class from the proxy
    attr_accessor :abstract_connection_class

    def initialize(abstract_class, db_name)
      @abstract_connection_class = abstract_class
      @db_name = db_name
    end

    def db_charmer_connection_name
      @db_name
    end

    def db_charmer_connection_proxy
      self
    end

    def db_charmer_retrieve_connection
      @abstract_connection_class.retrieve_connection
    end

    def nil?
      false
    end

    #-----------------------------------------------------------------------------------------------
    RESPOND_TO_METHODS = [
      :abstract_connection_class,
      :db_charmer_connection_name,
      :db_charmer_connection_proxy,
      :db_charmer_retrieve_connection,
      :nil?
    ].freeze

    # Short-circuit some of the methods for which we know there is a separate check in coercion code
    DOESNT_RESPOND_TO_METHODS = [
      :set_real_connection
    ].freeze

    def respond_to?(method_name, include_all = false)
      return true if RESPOND_TO_METHODS.include?(method_name)
      return false if DOESNT_RESPOND_TO_METHODS.include?(method_name)
      db_charmer_retrieve_connection.respond_to?(method_name, include_all)
    end

    #-----------------------------------------------------------------------------------------------
    def method_missing(meth, *args, &block)
      db_charmer_retrieve_connection.send(meth, *args, &block)
    end
  end
end


================================================
FILE: lib/db_charmer/core_extensions.rb
================================================
class Object
  unless defined?(try)
    def try(method, *options, &block)
      send(method, *options, &block)
    end
  end

  # These methods are added to all objects so we could call proxy? on anything
  # and figure if an object is a proxy w/o hitting method_missing or respond_to?
  def self.proxy?
    false
  end

  def proxy?
    false
  end
end

class NilClass
  def try(*args)
    nil
  end
end


================================================
FILE: lib/db_charmer/force_slave_reads.rb
================================================
module DbCharmer
  def self.current_controller
    Thread.current[:db_charmer_current_controller]
  end

  def self.current_controller=(val)
    Thread.current[:db_charmer_current_controller] = val
  end

  #-------------------------------------------------------------------------------------------------
  def self.forced_slave_reads_setting
    Thread.current[:db_charmer_forced_slave_reads]
  end

  def self.forced_slave_reads_setting=(val)
    Thread.current[:db_charmer_forced_slave_reads] = val
  end

  #-------------------------------------------------------------------------------------------------
  def self.force_slave_reads?
    # If global force slave reads is requested, do it
    return true if Thread.current[:db_charmer_forced_slave_reads]

    # If not, try to use current controller to decide on this
    return false unless current_controller.respond_to?(:force_slave_reads?)

    slave_reads = current_controller.force_slave_reads?
    logger.debug("Using controller to figure out if slave reads should be forced: #{slave_reads}")
    return slave_reads
  end

  #-------------------------------------------------------------------------------------------------
  def self.with_controller(controller)
    raise ArgumentError, "No block given" unless block_given?
    logger.debug("Setting current controller for db_charmer: #{controller.class.name}")
    self.current_controller = controller
    yield
  ensure
    logger.debug('Clearing current controller for db_charmer')
    self.current_controller = nil
  end

  #-------------------------------------------------------------------------------------------------
  # Force all reads in a block of code to go to a slave
  def self.force_slave_reads
    raise ArgumentError, "No block given" unless block_given?
    old_forced_slave_reads = self.forced_slave_reads_setting
    begin
      self.forced_slave_reads_setting = true
      yield
    ensure
      self.forced_slave_reads_setting = old_forced_slave_reads
    end
  end
end


================================================
FILE: lib/db_charmer/rails2/abstract_adapter/log_formatting.rb
================================================
module DbCharmer
  module AbstractAdapter
    module LogFormatting

      def self.included(base)
        base.alias_method_chain :format_log_entry, :connection_name
      end

      def connection_name
        raise "Can't find connection configuration!" unless @config
        @config[:connection_name]
      end

      # Rails 2.X specific logging method
      def format_log_entry_with_connection_name(message, dump = nil)
        msg = connection_name ? "[#{connection_name}] " : ''
        msg = "  \e[0;34;1m#{msg}\e[0m" if connection_name && ::ActiveRecord::Base.colorize_logging
        msg << format_log_entry_without_connection_name(message, dump)
      end

    end
  end
end


================================================
FILE: lib/db_charmer/rails2/active_record/master_slave_routing.rb
================================================
module DbCharmer
  module ActiveRecord
    module MasterSlaveRouting

      module ClassMethods
        SLAVE_METHODS = [ :find_by_sql, :count_by_sql, :calculate ]
        MASTER_METHODS = [ :update, :create, :delete, :destroy, :delete_all, :destroy_all, :update_all, :update_counters ]

        SLAVE_METHODS.each do |slave_method|
          class_eval <<-EOF, __FILE__, __LINE__ + 1
            def #{slave_method}(*args, &block)
              first_level_on_slave do
                super(*args, &block)
              end
            end
          EOF
        end

        MASTER_METHODS.each do |master_method|
          class_eval <<-EOF, __FILE__, __LINE__ + 1
            def #{master_method}(*args, &block)
              on_master do
                super(*args, &block)
              end
            end
          EOF
        end

        def find(*args, &block)
          options = args.last
          if options.is_a?(Hash) && options[:lock]
            on_master { super(*args, &block) }
          else
            super(*args, &block)
          end
        end
      end

      module InstanceMethods
        def reload(*args, &block)
          self.class.on_master do
            super(*args, &block)
          end
        end
      end

    end
  end
end


================================================
FILE: lib/db_charmer/rails2/active_record/named_scope/scope_proxy.rb
================================================
module DbCharmer
  module ActiveRecord
    module NamedScope
      module ScopeProxy

        def proxy?
          true
        end

        def on_db(con, proxy_target = nil, &block)
          proxy_target ||= self
          proxy_scope.on_db(con, proxy_target, &block)
        end

        def on_slave(con = nil, &block)
          proxy_scope.on_slave(con, self, &block)
        end

        def on_master(&block)
          proxy_scope.on_master(self, &block)
        end

      end
    end
  end
end


================================================
FILE: lib/db_charmer/rails3/abstract_adapter/connection_name.rb
================================================
module DbCharmer
  module AbstractAdapter
    module ConnectionName

      # We use this proxy to push connection name down to instrumenters w/o monkey-patching the log method itself
      class InstrumenterDecorator < ActiveSupport::BasicObject
        def initialize(adapter, instrumenter)
          @adapter = adapter
          @instrumenter = instrumenter
        end

        def instrument(name, payload = {}, &block)
          payload[:connection_name] ||= @adapter.connection_name
          @instrumenter.instrument(name, payload, &block)
        end

        def method_missing(meth, *args, &block)
          @instrumenter.send(meth, *args, &block)
        end
      end

      def self.included(base)
        base.alias_method_chain :initialize, :connection_name
      end

      def connection_name
        raise "Can't find connection configuration!" unless @config
        @config[:connection_name]
      end

      def initialize_with_connection_name(*args)
        initialize_without_connection_name(*args)
        @instrumenter = InstrumenterDecorator.new(self, @instrumenter)
      end

    end
  end
end


================================================
FILE: lib/db_charmer/rails3/active_record/log_subscriber.rb
================================================
module DbCharmer
  module ActiveRecord
    module LogSubscriber

      def self.included(base)
        base.send(:attr_accessor, :connection_name)
        base.alias_method_chain :sql, :connection_name
        base.alias_method_chain :debug, :connection_name
      end

      def sql_with_connection_name(event)
        self.connection_name = event.payload[:connection_name]
        sql_without_connection_name(event)
      end

      def debug_with_connection_name(msg)
        conn = connection_name ? color("  [#{connection_name}]", ActiveSupport::LogSubscriber::BLUE, true) : ''
        debug_without_connection_name(conn + msg)
      end

    end
  end
end


================================================
FILE: lib/db_charmer/rails3/active_record/master_slave_routing.rb
================================================
module DbCharmer
  module ActiveRecord
    module MasterSlaveRouting

      module ClassMethods
        SLAVE_METHODS = [ :find_by_sql, :count_by_sql ]
        MASTER_METHODS = [ ] # I don't know any methods in AR::Base that change data directly w/o going to the relation object

        SLAVE_METHODS.each do |slave_method|
          class_eval <<-EOF, __FILE__, __LINE__ + 1
            def #{slave_method}(*args, &block)
              first_level_on_slave do
                super(*args, &block)
              end
            end
          EOF
        end

        MASTER_METHODS.each do |master_method|
          class_eval <<-EOF, __FILE__, __LINE__ + 1
            def #{master_method}(*args, &block)
              on_master do
                super(*args, &block)
              end
            end
          EOF
        end
      end

      module InstanceMethods
        MASTER_METHODS = [ :reload ]

        MASTER_METHODS.each do |master_method|
          class_eval <<-EOF, __FILE__, __LINE__ + 1
            def #{master_method}(*args, &block)
              self.class.on_master do
                super(*args, &block)
              end
            end
          EOF
        end
      end

    end
  end
end


================================================
FILE: lib/db_charmer/rails3/active_record/relation/connection_routing.rb
================================================
module DbCharmer
  module ActiveRecord
    module Relation
      module ConnectionRouting

        # All the methods that could be querying the database
        SLAVE_METHODS = [ :calculate, :exists? ]
        MASTER_METHODS = [ :delete, :delete_all, :destroy, :destroy_all, :reload, :update, :update_all ]
        ALL_METHODS = SLAVE_METHODS + MASTER_METHODS

        DB_CHARMER_ATTRIBUTES = [ :db_charmer_connection, :db_charmer_connection_is_forced, :db_charmer_enable_slaves ]

        # Define the default relation connection + override all the query methods here
        def self.included(base)
          init_attributes(base)
          init_routing(base)
        end

        # Define our attributes + spawn methods shit needs to be changed to make sure our accessors are copied over to the new instances
        def self.init_attributes(base)
          DB_CHARMER_ATTRIBUTES.each do |attr|
            base.send(:attr_accessor, attr)
          end

          # Override spawn methods
          base.alias_method_chain :except, :db_charmer
          base.alias_method_chain :only, :db_charmer
        end

        # Override all query methods
        def self.init_routing(base)
          ALL_METHODS.each do |meth|
            base.alias_method_chain meth, :db_charmer
          end

          # Special case: for normal selects we go to the slave, but for selects with a lock we should use master
          base.alias_method_chain :to_a, :db_charmer
        end

        # Copy db_charmer attributes in addition to what they're copying
        def except_with_db_charmer(*args)
          except_without_db_charmer(*args).tap do |result|
            copy_db_charmer_options(self, result)
          end
        end

        # Copy db_charmer attributes in addition to what they're copying
        def only_with_db_charmer(*args)
          only_without_db_charmer(*args).tap do |result|
            copy_db_charmer_options(self, result)
          end
        end

        # Copy our accessors from one instance to another
        def copy_db_charmer_options(src, dst)
          DB_CHARMER_ATTRIBUTES.each do |attr|
            dst.send("#{attr}=".to_sym, src.send(attr))
          end
        end

        # Connection switching (changes the default relation connection)
        def on_db(con, &block)
          if block_given?
            @klass.on_db(con, &block)
          else
            clone.tap do |result|
              result.db_charmer_connection = con
              result.db_charmer_connection_is_forced = true
            end
          end
        end

        # Make sure we get the right connection here
        def connection
          @klass.on_db(db_charmer_connection).connection
        end

        # Selects preferred destination (master/slave/default) for a query
        def select_destination(method, recommendation = :default)
          # If this relation was created within a forced connection block (e.g Model.on_db(:foo).relation)
          # Then we should use that connection everywhere except cases when a model is slave-enabled
          # in those cases DML queries go to the master
          if db_charmer_connection_is_forced
            return :master if db_charmer_enable_slaves && MASTER_METHODS.member?(method)
            return :default
          end

          # If this relation is created from a slave-enabled model, let's do the routing if possible
          if db_charmer_enable_slaves
            return :slave if SLAVE_METHODS.member?(method)
            return :master if MASTER_METHODS.member?(method)
          else
            # Make sure we do not use recommended destination
            recommendation = :default
          end

          # If nothing else came up, let's use the default or recommended connection
          return recommendation
        end

        # Switch the model to default relation connection
        def switch_connection_for_method(method, recommendation = nil)
          # Choose where to send the query
          destination ||= select_destination(method, recommendation)

          # What method to use
          on_db_method = [ :on_db, db_charmer_connection ]
          on_db_method = :on_master if destination == :master
          on_db_method = :first_level_on_slave if destination == :slave

          # Perform the query
          @klass.send(*on_db_method) do
            yield
          end
        end

        # For normal selects we go to the slave, but for selects with a lock we should use master
        def to_a_with_db_charmer(*args, &block)
          preferred_destination = :slave
          preferred_destination = :master if lock_value

          switch_connection_for_method(:to_a, preferred_destination) do
            to_a_without_db_charmer(*args, &block)
          end
        end

        # Need this to mimick alias_method_chain name generation (exists? => exists_with_db_charmer?)
        def self.aliased_method_name(target, with)
          aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
          "#{aliased_target}_#{with}_db_charmer#{punctuation}"
        end

        # Override all the query methods here
        ALL_METHODS.each do |method|
          class_eval <<-EOF, __FILE__, __LINE__ + 1
            def #{aliased_method_name method, :with}(*args, &block)
              switch_connection_for_method(:#{method.to_s}) do
                #{aliased_method_name method, :without}(*args, &block)
              end
            end
          EOF
        end

      end
    end
  end
end


================================================
FILE: lib/db_charmer/rails3/active_record/relation_method.rb
================================================
module DbCharmer
  module ActiveRecord
    module RelationMethod

      def self.extended(base)
        class << base
          alias_method_chain :relation, :db_charmer
          alias_method_chain :arel_engine, :db_charmer
        end
      end

      # Create a relation object and initialize its default connection
      def relation_with_db_charmer(*args, &block)
        relation_without_db_charmer(*args, &block).tap do |rel|
          rel.db_charmer_connection = self.connection
          rel.db_charmer_enable_slaves = self.db_charmer_slaves.any?
          rel.db_charmer_connection_is_forced = !db_charmer_top_level_connection?
        end
      end

      # Use the model itself an engine for Arel, do not fall back to AR::Base
      def arel_engine_with_db_charmer(*)
        self
      end

    end
  end
end


================================================
FILE: lib/db_charmer/rails31/active_record/migration/command_recorder.rb
================================================
module DbCharmer
  module ActiveRecord
    module Migration
      module CommandRecorder
        def invert_on_db(args)
          [:replay_commands_on_db, [args.first, args[1].inverse]]
        end
      end
    end
  end
end

================================================
FILE: lib/db_charmer/rails31/active_record/preloader/association.rb
================================================
module DbCharmer
  module ActiveRecord
    module Preloader
      module Association
        extend ActiveSupport::Concern
        included do
          alias_method_chain :build_scope, :db_magic
        end

        def build_scope_with_db_magic
          if model.db_charmer_top_level_connection? || reflection.options[:polymorphic] ||
              model.db_charmer_default_connection != klass.db_charmer_default_connection
            build_scope_without_db_magic
          else
            build_scope_without_db_magic.on_db(model)
          end
        end
      end
    end
  end
end


================================================
FILE: lib/db_charmer/rails31/active_record/preloader/has_and_belongs_to_many.rb
================================================
module DbCharmer
  module ActiveRecord
    module Preloader
      module HasAndBelongsToMany
        extend ActiveSupport::Concern
        included do
          alias_method_chain :records_for, :db_magic
        end

        def records_for_with_db_magic(ids)
          if model.db_charmer_top_level_connection? || reflection.options[:polymorphic] ||
              model.db_charmer_default_connection != klass.db_charmer_default_connection
            records_for_without_db_magic(ids)
          else
            klass.on_db(model) do
              records_for_without_db_magic(ids)
            end
          end
        end
      end
    end
  end
end


================================================
FILE: lib/db_charmer/railtie.rb
================================================
module DbCharmer
  class Railtie < Rails::Railtie

    rake_tasks do
      load "db_charmer/tasks/databases.rake"
    end

  end
end


================================================
FILE: lib/db_charmer/sharding/connection.rb
================================================
module DbCharmer
  module Sharding
    class Connection
      attr_accessor :config, :sharder

      def initialize(config)
        @config = config
        @sharder = self.instantiate_sharder
      end

      def instantiate_sharder
        raise ArgumentError, "No :method passed!" unless config[:method]
        sharder_class_name = "DbCharmer::Sharding::Method::#{config[:method].to_s.classify}"
        sharder_class = sharder_class_name.constantize
        sharder_class.new(config)
      end

      def shard_connections
        sharder.respond_to?(:shard_connections) ? sharder.shard_connections : nil
      end

      def support_default_shard?
        sharder.respond_to?(:support_default_shard?) && sharder.support_default_shard?
      end

      def default_connection
        @default_connection ||= DbCharmer::Sharding::StubConnection.new(self)
      end
    end
  end
end


================================================
FILE: lib/db_charmer/sharding/method/db_block_group_map.rb
================================================
# This is a more sophisticated sharding method based on a two layer database-backed
# blocks map that holds block-shard associations. Record blocks are mapped to tablegroups
# and groups are mapped to shards.
#
# It automatically creates new blocks for new keys and assigns them to existing groups.
# Warning: make sure to create at least one shard and one group before inserting any records.
#
module DbCharmer
  module Sharding
    module Method
      class DbBlockGroupMap
        # Shard connection info model
        class Shard < ::ActiveRecord::Base
          validates_presence_of :db_host
          validates_presence_of :db_port
          validates_presence_of :db_user
          validates_presence_of :db_pass
          validates_presence_of :db_name_prefix

          has_many :groups, :class_name => 'DbCharmer::Sharding::Method::DbBlockGroupMap::Group'
        end

        # Table group info model
        class Group < ::ActiveRecord::Base
          validates_presence_of :shard_id
          belongs_to :shard, :class_name => 'DbCharmer::Sharding::Method::DbBlockGroupMap::Shard'
        end

        #---------------------------------------------------------------------------------------------------------------
        # Sharder name
        attr_accessor :name

        # Mapping db connection
        attr_accessor :connection, :connection_name

        # Mapping table name
        attr_accessor :map_table

        # Tablegroups table name
        attr_accessor :groups_table

        # Shards table name
        attr_accessor :shards_table

        # Sharding keys block size
        attr_accessor :block_size

        def initialize(config)
          @name = config[:name] or raise(ArgumentError, "Missing required :name parameter!")
          @connection = DbCharmer::ConnectionFactory.connect(config[:connection], true)
          @block_size = (config[:block_size] || 10000).to_i

          @map_table = config[:map_table] or raise(ArgumentError, "Missing required :map_table parameter!")
          @groups_table = config[:groups_table] or raise(ArgumentError, "Missing required :groups_table parameter!")
          @shards_table = config[:shards_table] or raise(ArgumentError, "Missing required :shards_table parameter!")

          # Local caches
          @shard_info_cache = {}
          @group_info_cache = {}

          @blocks_cache = Rails.cache
          @blocks_cache_prefix = config[:blocks_cache_prefix] || "#{@name}_block:"
        end

        #---------------------------------------------------------------------------------------------------------------
        def shard_for_key(key)
          block = block_for_key(key)

          # Auto-allocate new blocks
          block ||= allocate_new_block_for_key(key)
          raise ArgumentError, "Invalid key value, no shards found for this key and could not create a new block!" unless block

          # Load shard
          group_id = block['group_id'].to_i
          shard_info = shard_info_by_group_id(group_id)

          # Get config
          shard_connection_config(shard_info, group_id)
        end

        #---------------------------------------------------------------------------------------------------------------
        # Returns a block for a key
        def block_for_key(key, cache = true)
          # Cleanup the cache if asked to
          key_range = [ block_start_for_key(key), block_end_for_key(key) ]
          block_cache_key = "%d-%d" % key_range

          if cache
            cached_block = get_cached_block(block_cache_key)
            return cached_block if cached_block
          end

          # Fetch cached value or load from db
          block = begin
            sql = "SELECT * FROM #{map_table} WHERE start_id = #{key_range.first} AND end_id = #{key_range.last} LIMIT 1"
            connection.select_one(sql, 'Find a shard block')
          end

          set_cached_block(block_cache_key, block)

          return block
        end

        #---------------------------------------------------------------------------------------------------------------
        def get_cached_block(block_cache_key)
          @blocks_cache.read("#{@blocks_cache_prefix}#{block_cache_key}")
        end

        def set_cached_block(block_cache_key, block)
          @blocks_cache.write("#{@blocks_cache_prefix}#{block_cache_key}", block)
        end

        #---------------------------------------------------------------------------------------------------------------
        # Load group info
        def group_info_by_id(group_id, cache = true)
          # Cleanup the cache if asked to
          @group_info_cache[group_id] = nil unless cache

          # Either load from cache or from db
          @group_info_cache[group_id] ||= begin
            prepare_shard_models
            Group.find_by_id(group_id)
          end
        end

        # Load shard info
        def shard_info_by_id(shard_id, cache = true)
          # Cleanup the cache if asked to
          @shard_info_cache[shard_id] = nil unless cache

          # Either load from cache or from db
          @shard_info_cache[shard_id] ||= begin
            prepare_shard_models
            Shard.find_by_id(shard_id)
          end
        end

        # Load shard info using mapping info for a group
        def shard_info_by_group_id(group_id)
          # Load group
          group_info = group_info_by_id(group_id)
          raise ArgumentError, "Invalid group_id: #{group_id}" unless group_info

          shard_info = shard_info_by_id(group_info.shard_id)
          raise ArgumentError, "Invalid shard_id: #{group_info.shard_id}" unless shard_info

          return shard_info
        end

        #---------------------------------------------------------------------------------------------------------------
        def allocate_new_block_for_key(key)
          # Can't find any groups to use for blocks allocation!
          return nil unless group = least_loaded_group

          # Figure out block limits
          start_id = block_start_for_key(key)
          end_id = block_end_for_key(key)

          # Try to insert a new mapping (ignore duplicate key errors)
          sql = <<-SQL
            INSERT IGNORE INTO #{map_table}
                           SET start_id = #{start_id},
                               end_id = #{end_id},
                               group_id = #{group.id},
                               block_size = #{block_size},
                               created_at = NOW(),
                               updated_at = NOW()
          SQL
          connection.execute(sql, "Allocate new block")

          # Increment the blocks counter on the shard
          Group.update_counters(group.id, :blocks_count => +1)

          # Retry block search after creation
          block_for_key(key)
        end

        def least_loaded_group
          prepare_shard_models

          # Select group
          group = Group.first(:conditions => { :enabled => true, :open => true }, :order => 'blocks_count ASC')
          raise "Can't find any tablegroups to use for blocks allocation!" unless group
          return group
        end

        #---------------------------------------------------------------------------------------------------------------
        def block_start_for_key(key)
          block_size.to_i * (key.to_i / block_size.to_i)
        end

        def block_end_for_key(key)
          block_size.to_i + block_start_for_key(key)
        end

        #---------------------------------------------------------------------------------------------------------------
        # Create configuration (use mapping connection as a template)
        def shard_connection_config(shard, group_id)
          # Format connection name
          shard_name = "db_charmer_db_block_group_map_#{name}_s%d_g%d" % [ shard.id, group_id]

          # Here we get the mapping connection's configuration
          # They do not expose configs so we hack in and get the instance var
          # FIXME: Find a better way, maybe move config method to our ar extenstions
          connection.instance_variable_get(:@config).clone.merge(
            # Name for the connection factory
            :connection_name => shard_name,
            # Connection params
            :host => shard.db_host,
            :port => shard.db_port,
            :username => shard.db_user,
            :password => shard.db_pass,
            :database => group_database_name(shard, group_id)
          )
        end

        def group_database_name(shard, group_id)
          "%s_%05d" % [ shard.db_name_prefix, group_id ]
        end

        #---------------------------------------------------------------------------------------------------------------
        def create_shard(params)
          params = params.symbolize_keys
          [ :db_host, :db_port, :db_user, :db_pass, :db_name_prefix ].each do |arg|
            raise ArgumentError, "Missing required parameter: #{arg}" unless params[arg]
          end

          # Prepare model
          prepare_shard_models

          # Create the record
          Shard.create! do |shard|
            shard.db_host = params[:db_host]
            shard.db_port = params[:db_port]
            shard.db_user = params[:db_user]
            shard.db_pass = params[:db_pass]
            shard.db_name_prefix = params[:db_name_prefix]
          end
        end

        def shard_connections
          # Find all groups
          prepare_shard_models
          groups = Group.all(:conditions => { :enabled => true }, :include => :shard)
          # Map them to shards
          groups.map { |group| shard_connection_config(group.shard, group.id) }
        end

        # Prepare model for working with our shards table
        def prepare_shard_models
          Shard.set_table_name(shards_table)
          Shard.switch_connection_to(connection)

          Group.set_table_name(groups_table)
          Group.switch_connection_to(connection)
        end

      end
    end
  end
end


================================================
FILE: lib/db_charmer/sharding/method/db_block_map.rb
================================================
# This is a more sophisticated sharding method based on a database-backed
# blocks map that holds block-shard associations. It automatically
# creates new blocks for new keys and assigns them to shards.
#
module DbCharmer
  module Sharding
    module Method
      class DbBlockMap
        # Sharder name
        attr_accessor :name

        # Mapping db connection
        attr_accessor :connection, :connection_name

        # Mapping table name
        attr_accessor :map_table

        # Shards table name
        attr_accessor :shards_table

        # Sharding keys block size
        attr_accessor :block_size

        def initialize(config)
          @name = config[:name] or raise(ArgumentError, "Missing required :name parameter!")
          @connection = DbCharmer::ConnectionFactory.connect(config[:connection], true)
          @block_size = (config[:block_size] || 10000).to_i

          @map_table = config[:map_table] or raise(ArgumentError, "Missing required :map_table parameter!")
          @shards_table = config[:shards_table] or raise(ArgumentError, "Missing required :shards_table parameter!")

          # Local caches
          @shard_info_cache = {}

          @blocks_cache = Rails.cache
          @blocks_cache_prefix = config[:blocks_cache_prefix] || "#{@name}_block:"
        end

        def shard_for_key(key)
          block = block_for_key(key)

          begin
            # Auto-allocate new blocks
            block ||= allocate_new_block_for_key(key)
          rescue ::ActiveRecord::StatementInvalid => e
            raise unless e.message.include?('Duplicate entry')
            block = block_for_key(key)
          end

          raise ArgumentError, "Invalid key value, no shards found for this key and could not create a new block!" unless block

          # Bail if no shard found
          shard_id = block['shard_id'].to_i
          shard_info = shard_info_by_id(shard_id)
          raise ArgumentError, "Invalid shard_id: #{shard_id}" unless shard_info

          # Get config
          shard_connection_config(shard_info)
        end

        class ShardInfo < ::ActiveRecord::Base
          validates_presence_of :db_host
          validates_presence_of :db_port
          validates_presence_of :db_user
          validates_presence_of :db_pass
          validates_presence_of :db_name
        end

        # Returns a block for a key
        def block_for_key(key, cache = true)
          # Cleanup the cache if asked to
          key_range = [ block_start_for_key(key), block_end_for_key(key) ]
          block_cache_key = "%d-%d" % key_range

          if cache
            cached_block = get_cached_block(block_cache_key)
            return cached_block if cached_block
          end

          # Fetch cached value or load from db
          block = begin
            sql = "SELECT * FROM #{map_table} WHERE start_id = #{key_range.first} AND end_id = #{key_range.last} LIMIT 1"
            connection.select_one(sql, 'Find a shard block')
          end

          set_cached_block(block_cache_key, block)

          return block
        end

        def get_cached_block(block_cache_key)
          @blocks_cache.read("#{@blocks_cache_prefix}#{block_cache_key}")
        end

        def set_cached_block(block_cache_key, block)
          @blocks_cache.write("#{@blocks_cache_prefix}#{block_cache_key}", block)
        end

        # Load shard info
        def shard_info_by_id(shard_id, cache = true)
          # Cleanup the cache if asked to
          @shard_info_cache[shard_id] = nil unless cache

          # Either load from cache or from db
          @shard_info_cache[shard_id] ||= begin
            prepare_shard_model
            ShardInfo.find_by_id(shard_id)
          end
        end

        def allocate_new_block_for_key(key)
          # Can't find any shards to use for blocks allocation!
          return nil unless shard = least_loaded_shard

          # Figure out block limits
          start_id = block_start_for_key(key)
          end_id = block_end_for_key(key)

          # Try to insert a new mapping (ignore duplicate key errors)
          sql = <<-SQL
            INSERT INTO #{map_table}
                   SET start_id = #{start_id},
                       end_id = #{end_id},
                       shard_id = #{shard.id},
                       block_size = #{block_size},
                       created_at = NOW(),
                       updated_at = NOW()
          SQL
          connection.execute(sql, "Allocate new block")

          # Increment the blocks counter on the shard
          ShardInfo.update_counters(shard.id, :blocks_count => +1)

          # Retry block search after creation
          block_for_key(key)
        end

        def least_loaded_shard
          prepare_shard_model

          # Select shard
          shard = ShardInfo.all(:conditions => { :enabled => true, :open => true }, :order => 'blocks_count ASC', :limit => 1).first
          raise "Can't find any shards to use for blocks allocation!" unless shard
          return shard
        end

        def block_start_for_key(key)
          block_size.to_i * (key.to_i / block_size.to_i)
        end

        def block_end_for_key(key)
          block_size.to_i + block_start_for_key(key)
        end

        # Create configuration (use mapping connection as a template)
        def shard_connection_config(shard)
          # Format connection name
          shard_name = "db_charmer_db_block_map_#{name}_shard_%05d" % shard.id

          # Here we get the mapping connection's configuration
          # They do not expose configs so we hack in and get the instance var
          # FIXME: Find a better way, maybe move config method to our ar extenstions
          connection.instance_variable_get(:@config).clone.merge(
            # Name for the connection factory
            :connection_name => shard_name,
            # Connection params
            :host => shard.db_host,
            :port => shard.db_port,
            :username => shard.db_user,
            :password => shard.db_pass,
            :database => shard.db_name
          )
        end

        def create_shard(params)
          params = params.symbolize_keys
          [ :db_host, :db_port, :db_user, :db_pass, :db_name ].each do |arg|
            raise ArgumentError, "Missing required parameter: #{arg}" unless params[arg]
          end

          # Prepare model
          prepare_shard_model

          # Create the record
          ShardInfo.create! do |shard|
            shard.db_host = params[:db_host]
            shard.db_port = params[:db_port]
            shard.db_user = params[:db_user]
            shard.db_pass = params[:db_pass]
            shard.db_name = params[:db_name]
          end
        end

        def shard_connections
          # Find all shards
          prepare_shard_model
          shards = ShardInfo.all(:conditions => { :enabled => true })
          # Map them to connections
          shards.map { |shard| shard_connection_config(shard) }
        end

        # Prepare model for working with our shards table
        def prepare_shard_model
          ShardInfo.table_name = shards_table
          ShardInfo.switch_connection_to(connection)
        end

      end
    end
  end
end


================================================
FILE: lib/db_charmer/sharding/method/hash_map.rb
================================================
module DbCharmer
  module Sharding
    module Method
      class HashMap
        attr_accessor :map

        def initialize(config)
          @map = config[:map].clone or raise ArgumentError, "No :map defined!"
        end

        def shard_for_key(key)
          res = map[key] || map[:default]
          raise ArgumentError, "Invalid key value, no shards found for this key!" unless res
          return res
        end

        def support_default_shard?
          map.has_key?(:default)
        end
      end
    end
  end
end


================================================
FILE: lib/db_charmer/sharding/method/range.rb
================================================
module DbCharmer
  module Sharding
    module Method
      class Range
        attr_accessor :ranges

        def initialize(config)
          @ranges = config[:ranges] ? config[:ranges].clone : raise(ArgumentError, "No :ranges defined!")
        end

        def shard_for_key(key)
          return ranges[:default] if key == :default

          ranges.each do |range, shard|
            next if range == :default
            return shard if range.member?(key.to_i)
          end

          return ranges[:default] if ranges[:default]
          raise ArgumentError, "Invalid key value, no shards found for this key!"
        end

        def support_default_shard?
          ranges.has_key?(:default)
        end

        def shard_connections
          ranges.values.uniq
        end
      end
    end
  end
end


================================================
FILE: lib/db_charmer/sharding/method.rb
================================================
module DbCharmer
  module Sharding
    module Method
      autoload :Range, 'db_charmer/sharding/method/range'
      autoload :HashMap, 'db_charmer/sharding/method/hash_map'
      autoload :DbBlockMap, 'db_charmer/sharding/method/db_block_map'
      autoload :DbBlockGroupMap, 'db_charmer/sharding/method/db_block_group_map'
    end
  end
end

================================================
FILE: lib/db_charmer/sharding/stub_connection.rb
================================================
# This is a simple proxy class used as a default connection on sharded models
#
# The idea is to proxy all utility method calls to a real connection (set by
# the +set_real_connection+ method when we switch shards) and fail on real
# database querying calls forcing users to switch shard connections.
#
module DbCharmer
  module Sharding
    class StubConnection
      attr_accessor :sharded_connection

      def initialize(sharded_connection)
        @sharded_connection = sharded_connection
        @real_conn = nil
      end

      def set_real_connection(real_conn)
        @real_conn = real_conn
      end

      def db_charmer_connection_name
        "StubConnection"
      end

      def real_connection
        # Return memoized real connection
        return @real_conn if @real_conn

        # If sharded connection supports shards enumeration, get the first shard
        conn = sharded_connection.shard_connections.try(:first)

        # If we do not have real connection yet, try to use the default one (if it is supported by the sharder)
        conn ||= sharded_connection.sharder.shard_for_key(:default) if sharded_connection.support_default_shard?

        # Get connection proxy for our real connection
        return nil unless conn
        @real_conn = ::ActiveRecord::Base.coerce_to_connection_proxy(conn, DbCharmer.connections_should_exist?)
      end

      def respond_to?(method_name, include_all = false)
        return true if super
        return false if real_connection.object_id == self.object_id
        real_connection.respond_to?(method_name, include_all)
      end

      def method_missing(meth, *args, &block)
        # Fail on database statements
        if ::ActiveRecord::ConnectionAdapters::DatabaseStatements.instance_methods.member?(meth.to_s)
          raise ::ActiveRecord::ConnectionNotEstablished, "You have to switch connection on your model before using it!"
        end

        # Fail if no connection has been established yet
        unless real_connection
          raise ::ActiveRecord::ConnectionNotEstablished, "No real connection to proxy this method to!"
        end

        if real_connection.kind_of?(DbCharmer::Sharding::StubConnection)
          raise ::ActiveRecord::ConnectionNotEstablished, "You have to switch connection on your model before using it!"
        end

        # Proxy the call to our real connection target
        real_connection.__send__(meth, *args, &block)
      end
    end
  end
end


================================================
FILE: lib/db_charmer/sharding.rb
================================================
module DbCharmer
  module Sharding
    autoload :Connection, 'db_charmer/sharding/connection'
    autoload :StubConnection, 'db_charmer/sharding/stub_connection'
    autoload :Method, 'db_charmer/sharding/method'

    @@sharded_connections = {}

    def self.register_connection(config)
      name = config[:name] or raise ArgumentError, "No :name in connection!"
      @@sharded_connections[name] = DbCharmer::Sharding::Connection.new(config)
    end

    def self.sharded_connection(name)
      @@sharded_connections[name] or raise ArgumentError, "Invalid sharded connection name!"
    end
  end
end


================================================
FILE: lib/db_charmer/tasks/databases.rake
================================================
namespace :db_charmer do
  namespace :create do
    desc 'Create all the local databases defined in config/database.yml'
    task :all => "db:load_config" do
      ::ActiveRecord::Base.configurations.each_value do |config|
        # Skip entries that don't have a database key, such as the first entry here:
        #
        #  defaults: &defaults
        #    adapter: mysql
        #    username: root
        #    password:
        #    host: localhost
        #
        #  development:
        #    database: blog_development
        #    <<: *defaults
        next unless config['database']
        # Only connect to local databases
        local_database?(config) { create_core_and_sub_database(config) }
      end
    end
  end

  desc 'Create the databases defined in config/database.yml for the current RAILS_ENV'
  task :create => "db:load_config" do
    create_core_and_sub_database(ActiveRecord::Base.configurations[RAILS_ENV])
  end

  def create_core_and_sub_database(config)
    create_database(config)
    config.each_value do | sub_config |
      next unless sub_config.is_a?(Hash)
      next unless sub_config['database']
      create_database(sub_config)
    end
  end

  namespace :drop do
    desc 'Drops all the local databases defined in config/database.yml'
    task :all => "db:load_config" do
      ::ActiveRecord::Base.configurations.each_value do |config|
        # Skip entries that don't have a database key
        next unless config['database']
        # Only connect to local databases
        local_database?(config) { drop_core_and_sub_database(config) }
      end
    end
  end

  desc 'Drops the database for the current RAILS_ENV'
  task :drop => "db:load_config" do
    config = ::ActiveRecord::Base.configurations[RAILS_ENV || 'development']
    begin
      drop_core_and_sub_database(config)
    rescue Exception => e
      puts "Couldn't drop #{config['database']} : #{e.inspect}"
    end
  end


  def local_database?(config, &block)
    if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank?
      yield
    else
      puts "This task only modifies local databases. #{config['database']} is on a remote host."
    end
  end
end

def drop_core_and_sub_database(config)
  begin
    drop_database(config)
  rescue
    $stderr.puts "#{config['database']} not exists"
  end  
  config.each_value do | sub_config |
    next unless sub_config.is_a?(Hash)
    next unless sub_config['database']
    begin
      drop_database(sub_config)
    rescue
      $stderr.puts "#{config['database']} not exists"
    end
  end
end



================================================
FILE: lib/db_charmer/version.rb
================================================
module DbCharmer
  module Version
    MAJOR = 1
    MINOR = 9
    PATCH = 1
    BUILD = nil

    STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
  end
end


================================================
FILE: lib/db_charmer/with_remapped_databases.rb
================================================
module DbCharmer
  def self.with_remapped_databases(mappings, &proc)
    old_mappings = ::ActiveRecord::Base.db_charmer_database_remappings
    begin
      ::ActiveRecord::Base.db_charmer_database_remappings = mappings
      if mappings[:master] || mappings['master']
        with_all_hijacked(&proc)
      else
        proc.call
      end
    ensure
      ::ActiveRecord::Base.db_charmer_database_remappings = old_mappings
    end
  end

  def self.hijack_new_classes?
    !! Thread.current[:db_charmer_hijack_new_classes]
  end

private

  def self.with_all_hijacked
    old_hijack_new_classes = Thread.current[:db_charmer_hijack_new_classes]
    begin
      Thread.current[:db_charmer_hijack_new_classes] = true
      subclasses_method = DbCharmer.rails3? ? :descendants : :subclasses
      ::ActiveRecord::Base.send(subclasses_method).each do |subclass|
        subclass.hijack_connection!
      end
      yield
    ensure
      Thread.current[:db_charmer_hijack_new_classes] = old_hijack_new_classes
    end
  end
end

#---------------------------------------------------------------------------------------------------
# Hijack connection on all new AR classes when we're in a block with main AR connection remapped
class ActiveRecord::Base
  class << self
    def inherited_with_hijacking(subclass)
      out = inherited_without_hijacking(subclass)
      hijack_connection! if DbCharmer.hijack_new_classes?
      out
    end

    alias_method_chain :inherited, :hijacking
  end
end


================================================
FILE: lib/db_charmer.rb
================================================
# In Rails 2.2 they did not add it to the autoload so it won't work w/o this require
require 'active_record/version' unless defined?(::ActiveRecord::VERSION::MAJOR)
require 'active_support/core_ext'

#---------------------------------------------------------------------------------------------------
module DbCharmer
  # Configure autoload
  autoload :Sharding, 'db_charmer/sharding'
  autoload :Version,  'db_charmer/version'
  module ActionController
    autoload :ForceSlaveReads, 'db_charmer/action_controller/force_slave_reads'
  end

  #-------------------------------------------------------------------------------------------------
  # Used in all Rails3-specific places
  def self.rails3?
    ::ActiveRecord::VERSION::MAJOR > 2
  end

  # Used in all Rails3.1-specific places
  def self.rails31?
    rails3? && ::ActiveRecord::VERSION::MINOR >= 1
  end

  # Used in all Rails2-specific places
  def self.rails2?
    ::ActiveRecord::VERSION::MAJOR == 2
  end

  # Detect broken Rails version
  def self.rails324?
    ActiveRecord::VERSION::STRING == '3.2.4'
  end

  #-------------------------------------------------------------------------------------------------
  # Returns true if we're running within a Rails project
  def self.running_with_rails?
    defined?(Rails) && Rails.respond_to?(:env)
  end

  # Returns current environment name based on Rails or Rack environment variables
  def self.detect_environment
    return Rails.env if running_with_rails?
    ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'
  end

  # Try to detect current environment or use development by default
  @@env = DbCharmer.detect_environment
  mattr_accessor :env

  #-------------------------------------------------------------------------------------------------
  # Accessors
  @@connections_should_exist = true
  mattr_accessor :connections_should_exist

  def self.connections_should_exist?
    !! connections_should_exist
  end

  #-------------------------------------------------------------------------------------------------
  def self.logger
    return Rails.logger if running_with_rails?
    @@logger ||= Logger.new(STDERR)
  end

  #-------------------------------------------------------------------------------------------------
  # Extend ActionController to support forcing slave reads
  def self.enable_controller_magic!
    ::ActionController::Base.extend(DbCharmer::ActionController::ForceSlaveReads::ClassMethods)
    ::ActionController::Base.send(:include, DbCharmer::ActionController::ForceSlaveReads::InstanceMethods)
  end
end

#---------------------------------------------------------------------------------------------------
# Print warning about the broken Rails 2.3.4
puts "WARNING: Rails 3.2.4 is not officially supported by DbCharmer. Please upgrade." if DbCharmer.rails324?

#---------------------------------------------------------------------------------------------------
# Add useful methods to global object
require 'db_charmer/core_extensions'

require 'db_charmer/connection_factory'
require 'db_charmer/connection_proxy'
require 'db_charmer/force_slave_reads'
require 'db_charmer/with_remapped_databases'

if DbCharmer.rails3?
  require "db_charmer/railtie"
end

#---------------------------------------------------------------------------------------------------
# Add our custom class-level attributes to AR models
require 'db_charmer/active_record/class_attributes'
require 'active_record'
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::ClassAttributes)

#---------------------------------------------------------------------------------------------------
# Enable connections switching in AR
require 'db_charmer/active_record/connection_switching'
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::ConnectionSwitching)

#---------------------------------------------------------------------------------------------------
# Enable AR logging extensions
if DbCharmer.rails3?
  require 'db_charmer/rails3/abstract_adapter/connection_name'
  require 'db_charmer/rails3/active_record/log_subscriber'
  ActiveRecord::LogSubscriber.send(:include, DbCharmer::ActiveRecord::LogSubscriber)
  ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, DbCharmer::AbstractAdapter::ConnectionName)
else
  require 'db_charmer/rails2/abstract_adapter/log_formatting'
  ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, DbCharmer::AbstractAdapter::LogFormatting)
end

#---------------------------------------------------------------------------------------------------
# Enable connection proxy in AR
require 'db_charmer/active_record/multi_db_proxy'
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::MultiDbProxy::ClassMethods)
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::MultiDbProxy::MasterSlaveClassMethods)
ActiveRecord::Base.send(:include, DbCharmer::ActiveRecord::MultiDbProxy::InstanceMethods)

#---------------------------------------------------------------------------------------------------
# Enable connection proxy for relations
if DbCharmer.rails3?
  require 'db_charmer/rails3/active_record/relation_method'
  require 'db_charmer/rails3/active_record/relation/connection_routing'
  ActiveRecord::Base.extend(DbCharmer::ActiveRecord::RelationMethod)
  ActiveRecord::Relation.send(:include, DbCharmer::ActiveRecord::Relation::ConnectionRouting)
end

#---------------------------------------------------------------------------------------------------
# Enable connection proxy for scopes (rails 2.x only)
if DbCharmer.rails2?
  require 'db_charmer/rails2/active_record/named_scope/scope_proxy'
  ActiveRecord::NamedScope::Scope.send(:include, DbCharmer::ActiveRecord::NamedScope::ScopeProxy)
end

#---------------------------------------------------------------------------------------------------
# Enable connection proxy for associations
# WARNING: Inject methods to association class right here because they proxy +include+ calls
#          somewhere else, which means we could not use +include+ method here
association_proxy_class = DbCharmer.rails31? ? ActiveRecord::Associations::CollectionProxy :
                                               ActiveRecord::Associations::AssociationProxy
association_proxy_class.class_eval do
  def proxy?
    true
  end

  if DbCharmer.rails31?
    def on_db(con, proxy_target = nil, &block)
      proxy_target ||= self
      @association.klass.on_db(con, proxy_target, &block)
    end

    def on_slave(con = nil, &block)
      @association.klass.on_slave(con, self, &block)
    end

    def on_master(&block)
      @association.klass.on_master(self, &block)
    end
  else
    def on_db(con, proxy_target = nil, &block)
      proxy_target ||= self
      @reflection.klass.on_db(con, proxy_target, &block)
    end

    def on_slave(con = nil, &block)
      @reflection.klass.on_slave(con, self, &block)
    end

    def on_master(&block)
      @reflection.klass.on_master(self, &block)
    end
  end
end

#---------------------------------------------------------------------------------------------------
# Enable multi-db migrations
require 'db_charmer/active_record/migration/multi_db_migrations'
ActiveRecord::Migration.send(:include, DbCharmer::ActiveRecord::Migration::MultiDbMigrations)

if DbCharmer.rails31?
  require 'db_charmer/rails31/active_record/migration/command_recorder'
  ActiveRecord::Migration::CommandRecorder.send(:include, DbCharmer::ActiveRecord::Migration::CommandRecorder)
end

#---------------------------------------------------------------------------------------------------
# Enable the magic
if DbCharmer.rails3?
  require 'db_charmer/rails3/active_record/master_slave_routing'
else
  require 'db_charmer/rails2/active_record/master_slave_routing'
end

require 'db_charmer/active_record/sharding'
require 'db_charmer/active_record/db_magic'
ActiveRecord::Base.extend(DbCharmer::ActiveRecord::DbMagic)

#---------------------------------------------------------------------------------------------------
# Setup association preload magic
if DbCharmer.rails31?
  require 'db_charmer/rails31/active_record/preloader/association'
  ActiveRecord::Associations::Preloader::Association.send(:include, DbCharmer::ActiveRecord::Preloader::Association)
  require 'db_charmer/rails31/active_record/preloader/has_and_belongs_to_many'
  ActiveRecord::Associations::Preloader::HasAndBelongsToMany.send(:include, DbCharmer::ActiveRecord::Preloader::HasAndBelongsToMany)
else
  require 'db_charmer/active_record/association_preload'
  ActiveRecord::Base.extend(DbCharmer::ActiveRecord::AssociationPreload)

  # Open up really useful API method
  ActiveRecord::AssociationPreload::ClassMethods.send(:public, :preload_associations)
end


================================================
FILE: test-project/.gitignore
================================================
log/*.log
db/schema.*
.idea
TAGS
config/database.yml
.bundle
tmp
.DS_Store
vendor
Gemfile.lock
doc


================================================
FILE: test-project/.rspec
================================================
--colour
--format documentation


================================================
FILE: test-project/Gemfile
================================================
source 'http://rubygems.org'

gem 'rake', "0.9.2.2"
gem 'mysql', "2.8.1"

gem 'rspec', '< 3.0'
gem 'rspec-core', '< 3.0'
gem 'rspec-rails', '< 3.0'

# Load DbCharmer as a gem
if ENV['DB_CHARMER_GEM'].to_s == ''
  gem_path = File.expand_path(File.dirname(File.dirname(__FILE__)))
  puts "Using on-disk db-charmer code from '#{gem_path}'..."
  gem 'db-charmer', :path => gem_path, :require => 'db_charmer'
else
  puts "Using db-charmer gem: #{ENV['DB_CHARMER_GEM']}..."
  gem 'db-charmer', ENV['DB_CHARMER_GEM'], :require => 'db_charmer'
end

# Detect Rails version we need to use
rails_version_file = File.expand_path("../.rails-version", __FILE__)
version = File.exists?(rails_version_file) && File.read(rails_version_file).chomp
version ||= ENV['RAILS_VERSION']
version ||= '3-2-stable'

# Require gems for selected rails version
case version
when /master/
  gem "rails", :git => "git://github.com/rails/rails.git"
  gem "arel", :git => "git://github.com/rails/arel.git"
  gem "journey", :git => "git://github.com/rails/journey.git"
when /3-0-stable/
  gem "rails", :git => "git://github.com/rails/rails.git", :branch => "3-0-stable"
  gem "arel",  :git => "git://github.com/rails/arel.git", :branch => "2-0-stable"
when /3-1-stable/
  gem "rails", :git => "git://github.com/rails/rails.git", :branch => "3-1-stable"
when /3-2-stable/
  gem "rails", :git => "git://github.com/rail
Download .txt
gitextract_9iqagwm9/

├── .gitignore
├── .travis.yml
├── CHANGES
├── LICENSE
├── Makefile
├── README.rdoc
├── Rakefile
├── ci_build
├── db-charmer.gemspec
├── init.rb
├── issues/
│   └── issues-as-of-2014-11-14.json
├── lib/
│   ├── db_charmer/
│   │   ├── action_controller/
│   │   │   └── force_slave_reads.rb
│   │   ├── active_record/
│   │   │   ├── association_preload.rb
│   │   │   ├── class_attributes.rb
│   │   │   ├── connection_switching.rb
│   │   │   ├── db_magic.rb
│   │   │   ├── migration/
│   │   │   │   └── multi_db_migrations.rb
│   │   │   ├── multi_db_proxy.rb
│   │   │   └── sharding.rb
│   │   ├── connection_factory.rb
│   │   ├── connection_proxy.rb
│   │   ├── core_extensions.rb
│   │   ├── force_slave_reads.rb
│   │   ├── rails2/
│   │   │   ├── abstract_adapter/
│   │   │   │   └── log_formatting.rb
│   │   │   └── active_record/
│   │   │       ├── master_slave_routing.rb
│   │   │       └── named_scope/
│   │   │           └── scope_proxy.rb
│   │   ├── rails3/
│   │   │   ├── abstract_adapter/
│   │   │   │   └── connection_name.rb
│   │   │   └── active_record/
│   │   │       ├── log_subscriber.rb
│   │   │       ├── master_slave_routing.rb
│   │   │       ├── relation/
│   │   │       │   └── connection_routing.rb
│   │   │       └── relation_method.rb
│   │   ├── rails31/
│   │   │   └── active_record/
│   │   │       ├── migration/
│   │   │       │   └── command_recorder.rb
│   │   │       └── preloader/
│   │   │           ├── association.rb
│   │   │           └── has_and_belongs_to_many.rb
│   │   ├── railtie.rb
│   │   ├── sharding/
│   │   │   ├── connection.rb
│   │   │   ├── method/
│   │   │   │   ├── db_block_group_map.rb
│   │   │   │   ├── db_block_map.rb
│   │   │   │   ├── hash_map.rb
│   │   │   │   └── range.rb
│   │   │   ├── method.rb
│   │   │   └── stub_connection.rb
│   │   ├── sharding.rb
│   │   ├── tasks/
│   │   │   └── databases.rake
│   │   ├── version.rb
│   │   └── with_remapped_databases.rb
│   └── db_charmer.rb
├── test-project/
│   ├── .gitignore
│   ├── .rspec
│   ├── Gemfile
│   ├── Rakefile
│   ├── TODO
│   ├── app/
│   │   ├── controllers/
│   │   │   ├── application_controller.rb
│   │   │   └── posts_controller.rb
│   │   ├── helpers/
│   │   │   └── application_helper.rb
│   │   ├── models/
│   │   │   ├── avatar.rb
│   │   │   ├── car.rb
│   │   │   ├── categories_posts.rb
│   │   │   ├── category.rb
│   │   │   ├── comment.rb
│   │   │   ├── event.rb
│   │   │   ├── ford.rb
│   │   │   ├── house.rb
│   │   │   ├── log_record.rb
│   │   │   ├── post.rb
│   │   │   ├── range_sharded_model.rb
│   │   │   ├── toyota.rb
│   │   │   └── user.rb
│   │   └── views/
│   │       ├── layouts/
│   │       │   └── application.html.erb
│   │       └── posts/
│   │           ├── index.html.erb
│   │           ├── new.html.erb
│   │           └── show.html.erb
│   ├── config/
│   │   ├── application.rb
│   │   ├── boot.rb
│   │   ├── database.yml.example
│   │   ├── environment.rb
│   │   ├── environments/
│   │   │   └── test.rb
│   │   ├── initializers/
│   │   │   ├── backtrace_silencers.rb
│   │   │   ├── db_charmer.rb
│   │   │   ├── secret_token.rb
│   │   │   ├── session_store.rb
│   │   │   └── sharding.rb
│   │   ├── locales/
│   │   │   └── en.yml
│   │   └── routes.rb
│   ├── db/
│   │   ├── create_databases.sql
│   │   ├── migrate/
│   │   │   ├── 20090810013829_create_log_records.rb
│   │   │   ├── 20090810013922_create_posts.rb
│   │   │   ├── 20090810221944_create_users.rb
│   │   │   ├── 20100305234245_create_categories.rb
│   │   │   ├── 20100305234340_create_categories_posts.rb
│   │   │   ├── 20100305235831_create_avatars.rb
│   │   │   ├── 20100328201317_create_sharding_map_tables.rb
│   │   │   ├── 20100330180517_create_event_tables.rb
│   │   │   ├── 20100817191548_create_cars.rb
│   │   │   └── 20111005193941_create_comments.rb
│   │   ├── seeds.rb
│   │   └── sharding.sql
│   └── spec/
│       ├── controllers/
│       │   └── posts_controller_spec.rb
│       ├── fixtures/
│       │   ├── avatars.yml
│       │   ├── categories.yml
│       │   ├── categories_posts.yml
│       │   ├── comments.yml
│       │   ├── event_shards_info.yml
│       │   ├── event_shards_map.yml
│       │   ├── log_records.yml
│       │   ├── posts.yml
│       │   └── users.yml
│       ├── integration/
│       │   └── multi_threading_spec.rb
│       ├── models/
│       │   ├── avatar_spec.rb
│       │   ├── cars_spec.rb
│       │   ├── categories_posts_spec.rb
│       │   ├── category_spec.rb
│       │   ├── comment_spec.rb
│       │   ├── event_spec.rb
│       │   ├── log_record_spec.rb
│       │   ├── post_spec.rb
│       │   ├── range_sharded_model_spec.rb
│       │   └── user_spec.rb
│       ├── sharding/
│       │   ├── connection_spec.rb
│       │   ├── method/
│       │   │   ├── db_block_map_spec.rb
│       │   │   ├── hash_map_spec.rb
│       │   │   └── range_spec.rb
│       │   └── sharding_spec.rb
│       ├── spec_helper.rb
│       ├── support/
│       │   └── rails31_stub_connection.rb
│       └── unit/
│           ├── abstract_adapter/
│           │   └── log_formatting_spec.rb
│           ├── action_controller/
│           │   └── force_slave_reads_spec.rb
│           ├── active_record/
│           │   ├── association_preload_spec.rb
│           │   ├── association_proxy_spec.rb
│           │   ├── class_attributes_spec.rb
│           │   ├── connection_switching_spec.rb
│           │   ├── db_magic_spec.rb
│           │   ├── master_slave_routing_spec.rb
│           │   ├── migration/
│           │   │   └── multi_db_migrations_spec.rb
│           │   ├── named_scope/
│           │   │   └── named_scope_spec.rb
│           │   └── relation_spec.rb
│           ├── connection_factory_spec.rb
│           ├── connection_proxy_spec.rb
│           ├── db_charmer_spec.rb
│           ├── multi_db_proxy_spec.rb
│           └── with_remapped_databases_spec.rb
└── test-project-2.x/
    ├── Gemfile
    ├── Rakefile
    ├── config/
    │   ├── boot.rb
    │   ├── database.yml.example
    │   ├── environment.rb
    │   ├── environments/
    │   │   └── test.rb
    │   ├── initializers/
    │   │   ├── backtrace_silencers.rb
    │   │   ├── db_charmer.rb
    │   │   ├── inflections.rb
    │   │   ├── mime_types.rb
    │   │   ├── new_rails_defaults.rb
    │   │   ├── session_store.rb
    │   │   └── sharding.rb
    │   ├── locales/
    │   │   └── en.yml
    │   ├── preinitializer.rb
    │   └── routes.rb
    ├── script/
    │   └── console
    └── spec/
        ├── spec.opts
        └── spec_helper.rb
Download .txt
SYMBOL INDEX (437 symbols across 77 files)

FILE: lib/db_charmer.rb
  type DbCharmer (line 6) | module DbCharmer
    type ActionController (line 10) | module ActionController
    function rails3? (line 16) | def self.rails3?
    function rails31? (line 21) | def self.rails31?
    function rails2? (line 26) | def self.rails2?
    function rails324? (line 31) | def self.rails324?
    function running_with_rails? (line 37) | def self.running_with_rails?
    function detect_environment (line 42) | def self.detect_environment
    function connections_should_exist? (line 56) | def self.connections_should_exist?
    function logger (line 61) | def self.logger
    function enable_controller_magic! (line 68) | def self.enable_controller_magic!
  function proxy? (line 144) | def proxy?
  function on_db (line 149) | def on_db(con, proxy_target = nil, &block)
  function on_slave (line 154) | def on_slave(con = nil, &block)
  function on_master (line 158) | def on_master(&block)
  function on_db (line 162) | def on_db(con, proxy_target = nil, &block)
  function on_slave (line 167) | def on_slave(con = nil, &block)
  function on_master (line 171) | def on_master(&block)

FILE: lib/db_charmer/action_controller/force_slave_reads.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActionController (line 2) | module ActionController
      type ForceSlaveReads (line 3) | module ForceSlaveReads
        type ClassMethods (line 5) | module ClassMethods
          function force_slave_reads (line 7) | def force_slave_reads(params = {})
          function force_slave_reads_options (line 14) | def force_slave_reads_options
          function force_slave_reads_action? (line 18) | def force_slave_reads_action?(name = nil)
        type InstanceMethods (line 37) | module InstanceMethods
          function included (line 40) | def self.included(base)
          function force_slave_reads! (line 44) | def force_slave_reads!
          function dont_force_slave_reads! (line 48) | def dont_force_slave_reads!
          function force_slave_reads? (line 52) | def force_slave_reads?

FILE: lib/db_charmer/active_record/association_preload.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type AssociationPreload (line 3) | module AssociationPreload
        function extended (line 6) | def self.extended(base)

FILE: lib/db_charmer/active_record/class_attributes.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type ClassAttributes (line 3) | module ClassAttributes
        function db_charmer_opts= (line 5) | def db_charmer_opts=(opts)
        function db_charmer_opts (line 9) | def db_charmer_opts
        function db_charmer_default_connection= (line 15) | def db_charmer_default_connection=(conn)
        function db_charmer_default_connection (line 19) | def db_charmer_default_connection
        function db_charmer_slaves= (line 25) | def db_charmer_slaves=(slaves)
        function db_charmer_slaves (line 29) | def db_charmer_slaves
        function db_charmer_random_slave (line 34) | def db_charmer_random_slave
        function db_charmer_connection_proxies (line 40) | def db_charmer_connection_proxies
        function db_charmer_connection_proxy= (line 44) | def db_charmer_connection_proxy=(proxy)
        function db_charmer_connection_proxy (line 48) | def db_charmer_connection_proxy
        function db_charmer_force_slave_reads_flags (line 53) | def db_charmer_force_slave_reads_flags
        function db_charmer_force_slave_reads= (line 57) | def db_charmer_force_slave_reads=(force)
        function db_charmer_force_slave_reads (line 61) | def db_charmer_force_slave_reads
        function db_charmer_force_slave_reads? (line 68) | def db_charmer_force_slave_reads?
        function db_charmer_connection_levels (line 73) | def db_charmer_connection_levels
        function db_charmer_connection_level= (line 77) | def db_charmer_connection_level=(level)
        function db_charmer_connection_level (line 81) | def db_charmer_connection_level
        function db_charmer_top_level_connection? (line 85) | def db_charmer_top_level_connection?
        function db_charmer_remapped_connection (line 90) | def db_charmer_remapped_connection
        function db_charmer_database_remappings (line 100) | def db_charmer_database_remappings
        function db_charmer_database_remappings= (line 104) | def db_charmer_database_remappings=(mappings)
        function db_charmer_model_connection_proxy (line 111) | def db_charmer_model_connection_proxy

FILE: lib/db_charmer/active_record/connection_switching.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type ConnectionSwitching (line 3) | module ConnectionSwitching
        function establish_real_connection_if_exists (line 4) | def establish_real_connection_if_exists(name, should_exist = false)
        function hijack_connection! (line 29) | def hijack_connection!
        function coerce_to_connection_proxy (line 51) | def coerce_to_connection_proxy(conn, should_exist = true)
        function switch_connection_to (line 81) | def switch_connection_to(conn, should_exist = true)

FILE: lib/db_charmer/active_record/db_magic.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type DbMagic (line 3) | module DbMagic
        function db_magic (line 5) | def db_magic(opt = {})
        function setup_children_magic (line 38) | def setup_children_magic(opt)
        function setup_sharding_magic (line 53) | def setup_sharding_magic(config)
        function setup_connection_magic (line 66) | def setup_connection_magic(conn, should_exist = true)
        function setup_slaves_magic (line 72) | def setup_slaves_magic(slaves, force_slave_reads, should_exist = t...

FILE: lib/db_charmer/active_record/migration/multi_db_migrations.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type Migration (line 3) | module Migration
        type MultiDbMigrations (line 4) | module MultiDbMigrations
          function append_features (line 6) | def self.append_features(base)
          type ClassMethods (line 22) | module ClassMethods
            function multi_db_names (line 24) | def multi_db_names
            function multi_db_names= (line 28) | def multi_db_names=(names)
            function migrate_with_db_wrapper (line 33) | def migrate_with_db_wrapper(direction)
            function on_db (line 45) | def on_db(db_name)
            function db_magic (line 62) | def db_magic(opts = {})
            function shard_connections (line 76) | def shard_connections(conn_name)
          function migrate_with_db_wrapper (line 82) | def migrate_with_db_wrapper(direction)
          function record_on_db (line 94) | def record_on_db(db_name, block)
          function replay_commands_on_db (line 102) | def replay_commands_on_db(name, commands)
          function on_db (line 110) | def on_db(db_name, &block)

FILE: lib/db_charmer/active_record/multi_db_proxy.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type MultiDbProxy (line 3) | module MultiDbProxy
        class OnDbProxy (line 6) | class OnDbProxy < ActiveSupport::BasicObject
          method initialize (line 10) | def initialize(proxy_target, slave)
          method method_missing (line 17) | def method_missing(meth, *args, &block)
        type ClassMethods (line 28) | module ClassMethods
          function on_db (line 29) | def on_db(con, proxy_target = nil)
        type InstanceMethods (line 48) | module InstanceMethods
          function on_db (line 49) | def on_db(con, proxy_target = nil, &block)
        type MasterSlaveClassMethods (line 55) | module MasterSlaveClassMethods
          function on_slave (line 56) | def on_slave(con = nil, proxy_target = nil, &block)
          function on_master (line 62) | def on_master(proxy_target = nil, &block)
          function first_level_on_slave (line 66) | def first_level_on_slave

FILE: lib/db_charmer/active_record/sharding.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type Sharding (line 3) | module Sharding
        function extended (line 5) | def self.extended(model)
        function shard_for (line 9) | def shard_for(key, proxy_target = nil, &block)
        function on_default_shard (line 16) | def on_default_shard(proxy_target = nil, &block)
        function on_each_shard (line 27) | def on_each_shard(proxy_target = nil, &block)

FILE: lib/db_charmer/connection_factory.rb
  type DbCharmer (line 7) | module DbCharmer
    type ConnectionFactory (line 8) | module ConnectionFactory
      function connection_classes (line 9) | def self.connection_classes
      function connection_classes= (line 13) | def self.connection_classes=(val)
      function reset! (line 17) | def self.reset!
      function connect (line 22) | def self.connect(connection_name, should_exist = true)
      function connect_to_db (line 28) | def self.connect_to_db(connection_name, config)
      function establish_connection (line 34) | def self.establish_connection(connection_name, should_exist = true)
      function establish_connection_to_db (line 40) | def self.establish_connection_to_db(connection_name, config)
      function generate_abstract_class (line 46) | def self.generate_abstract_class(connection_name, should_exist = true)
      function generate_abstract_class_for_db (line 58) | def self.generate_abstract_class_for_db(connection_name, config)
      function generate_empty_abstract_ar_class (line 69) | def self.generate_empty_abstract_ar_class(klass)
      function abstract_connection_class_name (line 78) | def self.abstract_connection_class_name(connection_name)

FILE: lib/db_charmer/connection_proxy.rb
  type DbCharmer (line 2) | module DbCharmer
    class ConnectionProxy (line 3) | class ConnectionProxy < ActiveSupport::BasicObject
      method initialize (line 10) | def initialize(abstract_class, db_name)
      method db_charmer_connection_name (line 15) | def db_charmer_connection_name
      method db_charmer_connection_proxy (line 19) | def db_charmer_connection_proxy
      method db_charmer_retrieve_connection (line 23) | def db_charmer_retrieve_connection
      method nil? (line 27) | def nil?
      method respond_to? (line 45) | def respond_to?(method_name, include_all = false)
      method method_missing (line 52) | def method_missing(meth, *args, &block)

FILE: lib/db_charmer/core_extensions.rb
  class Object (line 1) | class Object
    method try (line 3) | def try(method, *options, &block)
    method proxy? (line 10) | def self.proxy?
    method proxy? (line 14) | def proxy?
  class NilClass (line 19) | class NilClass
    method try (line 20) | def try(*args)

FILE: lib/db_charmer/force_slave_reads.rb
  type DbCharmer (line 1) | module DbCharmer
    function current_controller (line 2) | def self.current_controller
    function current_controller= (line 6) | def self.current_controller=(val)
    function forced_slave_reads_setting (line 11) | def self.forced_slave_reads_setting
    function forced_slave_reads_setting= (line 15) | def self.forced_slave_reads_setting=(val)
    function force_slave_reads? (line 20) | def self.force_slave_reads?
    function with_controller (line 33) | def self.with_controller(controller)
    function force_slave_reads (line 45) | def self.force_slave_reads

FILE: lib/db_charmer/rails2/abstract_adapter/log_formatting.rb
  type DbCharmer (line 1) | module DbCharmer
    type AbstractAdapter (line 2) | module AbstractAdapter
      type LogFormatting (line 3) | module LogFormatting
        function included (line 5) | def self.included(base)
        function connection_name (line 9) | def connection_name
        function format_log_entry_with_connection_name (line 15) | def format_log_entry_with_connection_name(message, dump = nil)

FILE: lib/db_charmer/rails2/active_record/master_slave_routing.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type MasterSlaveRouting (line 3) | module MasterSlaveRouting
        type ClassMethods (line 5) | module ClassMethods
          function find (line 29) | def find(*args, &block)
        type InstanceMethods (line 39) | module InstanceMethods
          function reload (line 40) | def reload(*args, &block)

FILE: lib/db_charmer/rails2/active_record/named_scope/scope_proxy.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type NamedScope (line 3) | module NamedScope
        type ScopeProxy (line 4) | module ScopeProxy
          function proxy? (line 6) | def proxy?
          function on_db (line 10) | def on_db(con, proxy_target = nil, &block)
          function on_slave (line 15) | def on_slave(con = nil, &block)
          function on_master (line 19) | def on_master(&block)

FILE: lib/db_charmer/rails3/abstract_adapter/connection_name.rb
  type DbCharmer (line 1) | module DbCharmer
    type AbstractAdapter (line 2) | module AbstractAdapter
      type ConnectionName (line 3) | module ConnectionName
        class InstrumenterDecorator (line 6) | class InstrumenterDecorator < ActiveSupport::BasicObject
          method initialize (line 7) | def initialize(adapter, instrumenter)
          method instrument (line 12) | def instrument(name, payload = {}, &block)
          method method_missing (line 17) | def method_missing(meth, *args, &block)
        function included (line 22) | def self.included(base)
        function connection_name (line 26) | def connection_name
        function initialize_with_connection_name (line 31) | def initialize_with_connection_name(*args)

FILE: lib/db_charmer/rails3/active_record/log_subscriber.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type LogSubscriber (line 3) | module LogSubscriber
        function included (line 5) | def self.included(base)
        function sql_with_connection_name (line 11) | def sql_with_connection_name(event)
        function debug_with_connection_name (line 16) | def debug_with_connection_name(msg)

FILE: lib/db_charmer/rails3/active_record/master_slave_routing.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type MasterSlaveRouting (line 3) | module MasterSlaveRouting
        type ClassMethods (line 5) | module ClassMethods
        type InstanceMethods (line 30) | module InstanceMethods

FILE: lib/db_charmer/rails3/active_record/relation/connection_routing.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type Relation (line 3) | module Relation
        type ConnectionRouting (line 4) | module ConnectionRouting
          function included (line 14) | def self.included(base)
          function init_attributes (line 20) | def self.init_attributes(base)
          function init_routing (line 31) | def self.init_routing(base)
          function except_with_db_charmer (line 41) | def except_with_db_charmer(*args)
          function only_with_db_charmer (line 48) | def only_with_db_charmer(*args)
          function copy_db_charmer_options (line 55) | def copy_db_charmer_options(src, dst)
          function on_db (line 62) | def on_db(con, &block)
          function connection (line 74) | def connection
          function select_destination (line 79) | def select_destination(method, recommendation = :default)
          function switch_connection_for_method (line 102) | def switch_connection_for_method(method, recommendation = nil)
          function to_a_with_db_charmer (line 118) | def to_a_with_db_charmer(*args, &block)
          function aliased_method_name (line 128) | def self.aliased_method_name(target, with)

FILE: lib/db_charmer/rails3/active_record/relation_method.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type RelationMethod (line 3) | module RelationMethod
        function extended (line 5) | def self.extended(base)
        function relation_with_db_charmer (line 13) | def relation_with_db_charmer(*args, &block)
        function arel_engine_with_db_charmer (line 22) | def arel_engine_with_db_charmer(*)

FILE: lib/db_charmer/rails31/active_record/migration/command_recorder.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type Migration (line 3) | module Migration
        type CommandRecorder (line 4) | module CommandRecorder
          function invert_on_db (line 5) | def invert_on_db(args)

FILE: lib/db_charmer/rails31/active_record/preloader/association.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type Preloader (line 3) | module Preloader
        type Association (line 4) | module Association
          function build_scope_with_db_magic (line 10) | def build_scope_with_db_magic

FILE: lib/db_charmer/rails31/active_record/preloader/has_and_belongs_to_many.rb
  type DbCharmer (line 1) | module DbCharmer
    type ActiveRecord (line 2) | module ActiveRecord
      type Preloader (line 3) | module Preloader
        type HasAndBelongsToMany (line 4) | module HasAndBelongsToMany
          function records_for_with_db_magic (line 10) | def records_for_with_db_magic(ids)

FILE: lib/db_charmer/railtie.rb
  type DbCharmer (line 1) | module DbCharmer
    class Railtie (line 2) | class Railtie < Rails::Railtie

FILE: lib/db_charmer/sharding.rb
  type DbCharmer (line 1) | module DbCharmer
    type Sharding (line 2) | module Sharding
      function register_connection (line 9) | def self.register_connection(config)
      function sharded_connection (line 14) | def self.sharded_connection(name)

FILE: lib/db_charmer/sharding/connection.rb
  type DbCharmer (line 1) | module DbCharmer
    type Sharding (line 2) | module Sharding
      class Connection (line 3) | class Connection
        method initialize (line 6) | def initialize(config)
        method instantiate_sharder (line 11) | def instantiate_sharder
        method shard_connections (line 18) | def shard_connections
        method support_default_shard? (line 22) | def support_default_shard?
        method default_connection (line 26) | def default_connection

FILE: lib/db_charmer/sharding/method.rb
  type DbCharmer (line 1) | module DbCharmer
    type Sharding (line 2) | module Sharding
      type Method (line 3) | module Method

FILE: lib/db_charmer/sharding/method/db_block_group_map.rb
  type DbCharmer (line 8) | module DbCharmer
    type Sharding (line 9) | module Sharding
      type Method (line 10) | module Method
        class DbBlockGroupMap (line 11) | class DbBlockGroupMap
          class Shard (line 13) | class Shard < ::ActiveRecord::Base
          class Group (line 24) | class Group < ::ActiveRecord::Base
          method initialize (line 48) | def initialize(config)
          method shard_for_key (line 66) | def shard_for_key(key)
          method block_for_key (line 83) | def block_for_key(key, cache = true)
          method get_cached_block (line 105) | def get_cached_block(block_cache_key)
          method set_cached_block (line 109) | def set_cached_block(block_cache_key, block)
          method group_info_by_id (line 115) | def group_info_by_id(group_id, cache = true)
          method shard_info_by_id (line 127) | def shard_info_by_id(shard_id, cache = true)
          method shard_info_by_group_id (line 139) | def shard_info_by_group_id(group_id)
          method allocate_new_block_for_key (line 151) | def allocate_new_block_for_key(key)
          method least_loaded_group (line 178) | def least_loaded_group
          method block_start_for_key (line 188) | def block_start_for_key(key)
          method block_end_for_key (line 192) | def block_end_for_key(key)
          method shard_connection_config (line 198) | def shard_connection_config(shard, group_id)
          method group_database_name (line 217) | def group_database_name(shard, group_id)
          method create_shard (line 222) | def create_shard(params)
          method shard_connections (line 241) | def shard_connections
          method prepare_shard_models (line 250) | def prepare_shard_models

FILE: lib/db_charmer/sharding/method/db_block_map.rb
  type DbCharmer (line 5) | module DbCharmer
    type Sharding (line 6) | module Sharding
      type Method (line 7) | module Method
        class DbBlockMap (line 8) | class DbBlockMap
          method initialize (line 24) | def initialize(config)
          method shard_for_key (line 39) | def shard_for_key(key)
          class ShardInfo (line 61) | class ShardInfo < ::ActiveRecord::Base
          method block_for_key (line 70) | def block_for_key(key, cache = true)
          method get_cached_block (line 91) | def get_cached_block(block_cache_key)
          method set_cached_block (line 95) | def set_cached_block(block_cache_key, block)
          method shard_info_by_id (line 100) | def shard_info_by_id(shard_id, cache = true)
          method allocate_new_block_for_key (line 111) | def allocate_new_block_for_key(key)
          method least_loaded_shard (line 138) | def least_loaded_shard
          method block_start_for_key (line 147) | def block_start_for_key(key)
          method block_end_for_key (line 151) | def block_end_for_key(key)
          method shard_connection_config (line 156) | def shard_connection_config(shard)
          method create_shard (line 175) | def create_shard(params)
          method shard_connections (line 194) | def shard_connections
          method prepare_shard_model (line 203) | def prepare_shard_model

FILE: lib/db_charmer/sharding/method/hash_map.rb
  type DbCharmer (line 1) | module DbCharmer
    type Sharding (line 2) | module Sharding
      type Method (line 3) | module Method
        class HashMap (line 4) | class HashMap
          method initialize (line 7) | def initialize(config)
          method shard_for_key (line 11) | def shard_for_key(key)
          method support_default_shard? (line 17) | def support_default_shard?

FILE: lib/db_charmer/sharding/method/range.rb
  type DbCharmer (line 1) | module DbCharmer
    type Sharding (line 2) | module Sharding
      type Method (line 3) | module Method
        class Range (line 4) | class Range
          method initialize (line 7) | def initialize(config)
          method shard_for_key (line 11) | def shard_for_key(key)
          method support_default_shard? (line 23) | def support_default_shard?
          method shard_connections (line 27) | def shard_connections

FILE: lib/db_charmer/sharding/stub_connection.rb
  type DbCharmer (line 7) | module DbCharmer
    type Sharding (line 8) | module Sharding
      class StubConnection (line 9) | class StubConnection
        method initialize (line 12) | def initialize(sharded_connection)
        method set_real_connection (line 17) | def set_real_connection(real_conn)
        method db_charmer_connection_name (line 21) | def db_charmer_connection_name
        method real_connection (line 25) | def real_connection
        method respond_to? (line 40) | def respond_to?(method_name, include_all = false)
        method method_missing (line 46) | def method_missing(meth, *args, &block)

FILE: lib/db_charmer/tasks/databases.rake
  function create_core_and_sub_database (line 29) | def create_core_and_sub_database(config)
  function local_database? (line 61) | def local_database?(config, &block)
  function drop_core_and_sub_database (line 70) | def drop_core_and_sub_database(config)

FILE: lib/db_charmer/version.rb
  type DbCharmer (line 1) | module DbCharmer
    type Version (line 2) | module Version

FILE: lib/db_charmer/with_remapped_databases.rb
  type DbCharmer (line 1) | module DbCharmer
    function with_remapped_databases (line 2) | def self.with_remapped_databases(mappings, &proc)
    function hijack_new_classes? (line 16) | def self.hijack_new_classes?
    function with_all_hijacked (line 22) | def self.with_all_hijacked
  class ActiveRecord::Base (line 39) | class ActiveRecord::Base
    method inherited_with_hijacking (line 41) | def inherited_with_hijacking(subclass)

FILE: test-project-2.x/config/boot.rb
  type Rails (line 9) | module Rails
    function boot! (line 11) | def boot!
    function booted? (line 18) | def booted?
    function pick_boot (line 22) | def pick_boot
    function vendor_rails? (line 26) | def vendor_rails?
    function preinitialize (line 30) | def preinitialize
    function preinitializer_path (line 34) | def preinitializer_path
    class Boot (line 39) | class Boot
      method run (line 40) | def run
    class VendorBoot (line 53) | class VendorBoot < Boot
      method load_initializer (line 54) | def load_initializer
    class GemBoot (line 61) | class GemBoot < Boot
      method load_initializer (line 62) | def load_initializer
      method load_rails_gem (line 68) | def load_rails_gem
      method rubygems_version (line 80) | def rubygems_version
      method gem_version (line 84) | def gem_version
      method load_rubygems (line 94) | def load_rubygems
      method parse_gem_version (line 107) | def parse_gem_version(text)
      method read_environment_rb (line 112) | def read_environment_rb

FILE: test-project/app/controllers/application_controller.rb
  class ApplicationController (line 1) | class ApplicationController < ActionController::Base

FILE: test-project/app/controllers/posts_controller.rb
  class PostsController (line 1) | class PostsController < ApplicationController
    method index (line 9) | def index
    method show (line 13) | def show
    method new (line 17) | def new
    method create (line 21) | def create
    method destroy (line 26) | def destroy

FILE: test-project/app/helpers/application_helper.rb
  type ApplicationHelper (line 1) | module ApplicationHelper

FILE: test-project/app/models/avatar.rb
  class Avatar (line 1) | class Avatar < ActiveRecord::Base

FILE: test-project/app/models/car.rb
  class Car (line 1) | class Car < ActiveRecord::Base

FILE: test-project/app/models/categories_posts.rb
  class CategoriesPosts (line 1) | class CategoriesPosts < ActiveRecord::Base

FILE: test-project/app/models/category.rb
  class Category (line 1) | class Category < ActiveRecord::Base

FILE: test-project/app/models/comment.rb
  class Comment (line 1) | class Comment < ActiveRecord::Base

FILE: test-project/app/models/event.rb
  class Event (line 1) | class Event < ActiveRecord::Base

FILE: test-project/app/models/ford.rb
  class Ford (line 1) | class Ford < Car

FILE: test-project/app/models/house.rb
  class House (line 1) | class House < ActiveRecord::Base

FILE: test-project/app/models/log_record.rb
  class LogRecord (line 1) | class LogRecord < ActiveRecord::Base

FILE: test-project/app/models/post.rb
  class Post (line 1) | class Post < ActiveRecord::Base
    method define_scope (line 8) | def self.define_scope(*args, &block)

FILE: test-project/app/models/range_sharded_model.rb
  class RangeShardedModel (line 1) | class RangeShardedModel < ActiveRecord::Base

FILE: test-project/app/models/toyota.rb
  class Toyota (line 1) | class Toyota < Car

FILE: test-project/app/models/user.rb
  class User (line 1) | class User < ActiveRecord::Base

FILE: test-project/config/application.rb
  type DbCharmerSandbox (line 9) | module DbCharmerSandbox
    class Application (line 10) | class Application < Rails::Application

FILE: test-project/db/migrate/20090810013829_create_log_records.rb
  class CreateLogRecords (line 1) | class CreateLogRecords < ActiveRecord::Migration
    method up (line 4) | def self.up
    method down (line 13) | def self.down

FILE: test-project/db/migrate/20090810013922_create_posts.rb
  class CreatePosts (line 1) | class CreatePosts < ActiveRecord::Migration
    method up (line 2) | def self.up
    method down (line 11) | def self.down

FILE: test-project/db/migrate/20090810221944_create_users.rb
  class CreateUsers (line 1) | class CreateUsers < ActiveRecord::Migration
    method up (line 2) | def self.up
    method down (line 10) | def self.down

FILE: test-project/db/migrate/20100305234245_create_categories.rb
  class CreateCategories (line 1) | class CreateCategories < ActiveRecord::Migration
    method up (line 2) | def self.up
    method down (line 10) | def self.down

FILE: test-project/db/migrate/20100305234340_create_categories_posts.rb
  class CreateCategoriesPosts (line 1) | class CreateCategoriesPosts < ActiveRecord::Migration
    method up (line 2) | def self.up
    method down (line 10) | def self.down

FILE: test-project/db/migrate/20100305235831_create_avatars.rb
  class CreateAvatars (line 1) | class CreateAvatars < ActiveRecord::Migration
    method up (line 2) | def self.up
    method down (line 11) | def self.down

FILE: test-project/db/migrate/20100328201317_create_sharding_map_tables.rb
  class CreateShardingMapTables (line 1) | class CreateShardingMapTables < ActiveRecord::Migration
    method up (line 4) | def self.up
    method down (line 31) | def self.down

FILE: test-project/db/migrate/20100330180517_create_event_tables.rb
  class CreateEventTables (line 1) | class CreateEventTables < ActiveRecord::Migration
    method up (line 9) | def self.up
    method down (line 30) | def self.down

FILE: test-project/db/migrate/20100817191548_create_cars.rb
  class CreateCars (line 1) | class CreateCars < ActiveRecord::Migration
    method up (line 2) | def self.up
    method down (line 10) | def self.down

FILE: test-project/db/migrate/20111005193941_create_comments.rb
  class CreateComments (line 1) | class CreateComments < ActiveRecord::Migration
    method up (line 2) | def self.up
    method down (line 12) | def self.down

FILE: test-project/db/sharding.sql
  type `events_shard_info` (line 25) | CREATE TABLE `events_shard_info` (
  type `events_shard_dict` (line 56) | CREATE TABLE `events_shard_dict` (

FILE: test-project/spec/integration/multi_threading_spec.rb
  function do_test (line 4) | def do_test(test_seconds, thread_count)
  class TestLogRecordWithThreads (line 31) | class TestLogRecordWithThreads < ActiveRecord::Base
  class TestLogRecordWithThreadsAndRemapping (line 46) | class TestLogRecordWithThreadsAndRemapping < ActiveRecord::Base

FILE: test-project/spec/support/rails31_stub_connection.rb
  function stub_columns_for_rails31 (line 1) | def stub_columns_for_rails31(connection)

FILE: test-project/spec/unit/action_controller/force_slave_reads_spec.rb
  class BlahController (line 3) | class BlahController < ActionController::Base; end

FILE: test-project/spec/unit/active_record/class_attributes_spec.rb
  class FooModel (line 3) | class FooModel < ActiveRecord::Base; end

FILE: test-project/spec/unit/active_record/connection_switching_spec.rb
  class FooModelForConnSwitching (line 3) | class FooModelForConnSwitching < ActiveRecord::Base; end
  class BarModelForConnSwitching (line 4) | class BarModelForConnSwitching < ActiveRecord::Base; end

FILE: test-project/spec/unit/active_record/db_magic_spec.rb
  class Blah (line 3) | class Blah < ActiveRecord::Base; end
  class ParentFoo (line 62) | class ParentFoo < ActiveRecord::Base
  class ChildFoo (line 65) | class ChildFoo < ParentFoo; end
  class ShardTestingFoo (line 71) | class ShardTestingFoo < ActiveRecord::Base

FILE: test-project/spec/unit/active_record/master_slave_routing_spec.rb
  class User (line 5) | class User < ActiveRecord::Base

FILE: test-project/spec/unit/active_record/migration/multi_db_migrations_spec.rb
  class SpecMigration (line 3) | class SpecMigration < ActiveRecord::Migration
    method up (line 4) | def self.up
    method down (line 8) | def self.down
  class SpecMultiDbMigration (line 13) | class SpecMultiDbMigration < ActiveRecord::Migration
    method up (line 16) | def self.up
    method down (line 20) | def self.down
  class SpecMultiDbMigration2 (line 25) | class SpecMultiDbMigration2 < ActiveRecord::Migration
    method up (line 26) | def self.up
    method down (line 31) | def self.down
  class SpecMultiDbMigration3 (line 37) | class SpecMultiDbMigration3 < ActiveRecord::Migration
    method up (line 40) | def self.up
    method down (line 44) | def self.down
  class SpecMultiDbMigration4 (line 49) | class SpecMultiDbMigration4 < ActiveRecord::Migration
    method up (line 52) | def self.up
    method down (line 56) | def self.down
  class SpecMultiDbMigration5 (line 61) | class SpecMultiDbMigration5 < ActiveRecord::Migration
    method up (line 64) | def up
    method down (line 68) | def down
  class SpecMultiDbMigration6 (line 73) | class SpecMultiDbMigration6 < ActiveRecord::Migration
    method change (line 74) | def change
  function connection_with_name (line 92) | def connection_with_name(name)

FILE: test-project/spec/unit/active_record/relation_spec.rb
  class RelTestModel (line 6) | class RelTestModel < ActiveRecord::Base

FILE: test-project/spec/unit/connection_proxy_spec.rb
  class ProxyTest (line 5) | class ProxyTest; end
  type MockConnection (line 21) | module MockConnection
    function foo (line 22) | def self.foo

FILE: test-project/spec/unit/multi_db_proxy_spec.rb
  class Blah (line 5) | class Blah < ActiveRecord::Base

FILE: test-project/spec/unit/with_remapped_databases_spec.rb
  class User (line 13) | class User < ActiveRecord::Base
  function should_have_connection (line 18) | def should_have_connection(model_class, connection)
  function unhijack! (line 94) | def unhijack!(klass)
Condensed preview — 160 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (330K chars).
[
  {
    "path": ".gitignore",
    "chars": 31,
    "preview": "doc\npkg\n.DS_Store\n_site\n.idea\n\n"
  },
  {
    "path": ".travis.yml",
    "chars": 894,
    "preview": "language: ruby\nrvm:\n  - 1.8.7\n  - 1.9.3\n  - 2.0.0\n\nenv:\n  - RAILS_VERSION=2.x\n  - RAILS_VERSION=3.0.20\n  - RAILS_VERSION"
  },
  {
    "path": "CHANGES",
    "chars": 10649,
    "preview": "1.9.1 (2014-11-14):\n\nThe project has been suspended. No updates will be provided and no Rails versions\nbeyond 3.2.x will"
  },
  {
    "path": "LICENSE",
    "chars": 1077,
    "preview": "The MIT License\n\nCopyright (c) 2011, Oleksiy Kovyrin\n\nPermission is hereby granted, free of charge, to any person obtain"
  },
  {
    "path": "Makefile",
    "chars": 57,
    "preview": "doc/files/README_rdoc.html:\tREADME.rdoc\n\trdoc README.rdoc"
  },
  {
    "path": "README.rdoc",
    "chars": 4630,
    "preview": "= WARNING: The Project Has Been Suspended\n\nPlease note, that this project has been suspended. No updates will be provide"
  },
  {
    "path": "Rakefile",
    "chars": 67,
    "preview": "require 'rake'\nrequire 'bundler'\n\nBundler::GemHelper.install_tasks\n"
  },
  {
    "path": "ci_build",
    "chars": 1517,
    "preview": "#!/bin/bash\n\n# Making the script more robust\nset -e # Exit on errors\nset -u # Exit on uninitialized variables\n\nRAILS_VER"
  },
  {
    "path": "db-charmer.gemspec",
    "chars": 1195,
    "preview": "# -*- encoding: utf-8 -*-\n$:.push File.expand_path('../lib', __FILE__)\nrequire 'db_charmer/version'\n\nGem::Specification."
  },
  {
    "path": "init.rb",
    "chars": 21,
    "preview": "require 'db_charmer'\n"
  },
  {
    "path": "issues/issues-as-of-2014-11-14.json",
    "chars": 91576,
    "preview": "[\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/98\",\n    \"labels_url\": \"https://api.github.com/"
  },
  {
    "path": "lib/db_charmer/action_controller/force_slave_reads.rb",
    "chars": 2198,
    "preview": "module DbCharmer\n  module ActionController\n    module ForceSlaveReads\n\n      module ClassMethods\n        @@db_charmer_fo"
  },
  {
    "path": "lib/db_charmer/active_record/association_preload.rb",
    "chars": 881,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module AssociationPreload\n      ASSOCIATION_TYPES = [ :has_one, :has_many, :b"
  },
  {
    "path": "lib/db_charmer/active_record/class_attributes.rb",
    "chars": 4075,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module ClassAttributes\n      @@db_charmer_opts = {}\n      def db_charmer_opts"
  },
  {
    "path": "lib/db_charmer/active_record/connection_switching.rb",
    "chars": 3891,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module ConnectionSwitching\n      def establish_real_connection_if_exists(name"
  },
  {
    "path": "lib/db_charmer/active_record/db_magic.rb",
    "chars": 3218,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module DbMagic\n\n      def db_magic(opt = {})\n        # Make sure we could use"
  },
  {
    "path": "lib/db_charmer/active_record/migration/multi_db_migrations.rb",
    "chars": 4719,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module Migration\n      module MultiDbMigrations\n\n        def self.append_feat"
  },
  {
    "path": "lib/db_charmer/active_record/multi_db_proxy.rb",
    "chars": 2561,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module MultiDbProxy\n      # Simple proxy class that switches connections and "
  },
  {
    "path": "lib/db_charmer/active_record/sharding.rb",
    "chars": 1304,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module Sharding\n\n      def self.extended(model)\n        model.cattr_accessor("
  },
  {
    "path": "lib/db_charmer/connection_factory.rb",
    "chars": 3284,
    "preview": "#\n# This class is used to automatically generate small abstract ActiveRecord classes\n# that would then be used as a sour"
  },
  {
    "path": "lib/db_charmer/connection_proxy.rb",
    "chars": 1775,
    "preview": "# Simple proxy that sends all method calls to a real database connection\nmodule DbCharmer\n  class ConnectionProxy < Acti"
  },
  {
    "path": "lib/db_charmer/core_extensions.rb",
    "chars": 405,
    "preview": "class Object\n  unless defined?(try)\n    def try(method, *options, &block)\n      send(method, *options, &block)\n    end\n "
  },
  {
    "path": "lib/db_charmer/force_slave_reads.rb",
    "chars": 2008,
    "preview": "module DbCharmer\n  def self.current_controller\n    Thread.current[:db_charmer_current_controller]\n  end\n\n  def self.curr"
  },
  {
    "path": "lib/db_charmer/rails2/abstract_adapter/log_formatting.rb",
    "chars": 688,
    "preview": "module DbCharmer\n  module AbstractAdapter\n    module LogFormatting\n\n      def self.included(base)\n        base.alias_met"
  },
  {
    "path": "lib/db_charmer/rails2/active_record/master_slave_routing.rb",
    "chars": 1270,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module MasterSlaveRouting\n\n      module ClassMethods\n        SLAVE_METHODS = "
  },
  {
    "path": "lib/db_charmer/rails2/active_record/named_scope/scope_proxy.rb",
    "chars": 504,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module NamedScope\n      module ScopeProxy\n\n        def proxy?\n          true\n"
  },
  {
    "path": "lib/db_charmer/rails3/abstract_adapter/connection_name.rb",
    "chars": 1122,
    "preview": "module DbCharmer\n  module AbstractAdapter\n    module ConnectionName\n\n      # We use this proxy to push connection name d"
  },
  {
    "path": "lib/db_charmer/rails3/active_record/log_subscriber.rb",
    "chars": 662,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module LogSubscriber\n\n      def self.included(base)\n        base.send(:attr_a"
  },
  {
    "path": "lib/db_charmer/rails3/active_record/master_slave_routing.rb",
    "chars": 1220,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module MasterSlaveRouting\n\n      module ClassMethods\n        SLAVE_METHODS = "
  },
  {
    "path": "lib/db_charmer/rails3/active_record/relation/connection_routing.rb",
    "chars": 5527,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module Relation\n      module ConnectionRouting\n\n        # All the methods tha"
  },
  {
    "path": "lib/db_charmer/rails3/active_record/relation_method.rb",
    "chars": 822,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module RelationMethod\n\n      def self.extended(base)\n        class << base\n  "
  },
  {
    "path": "lib/db_charmer/rails31/active_record/migration/command_recorder.rb",
    "chars": 225,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module Migration\n      module CommandRecorder\n        def invert_on_db(args)\n"
  },
  {
    "path": "lib/db_charmer/rails31/active_record/preloader/association.rb",
    "chars": 591,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module Preloader\n      module Association\n        extend ActiveSupport::Conce"
  },
  {
    "path": "lib/db_charmer/rails31/active_record/preloader/has_and_belongs_to_many.rb",
    "chars": 653,
    "preview": "module DbCharmer\n  module ActiveRecord\n    module Preloader\n      module HasAndBelongsToMany\n        extend ActiveSuppor"
  },
  {
    "path": "lib/db_charmer/railtie.rb",
    "chars": 133,
    "preview": "module DbCharmer\n  class Railtie < Rails::Railtie\n\n    rake_tasks do\n      load \"db_charmer/tasks/databases.rake\"\n    en"
  },
  {
    "path": "lib/db_charmer/sharding/connection.rb",
    "chars": 887,
    "preview": "module DbCharmer\n  module Sharding\n    class Connection\n      attr_accessor :config, :sharder\n\n      def initialize(conf"
  },
  {
    "path": "lib/db_charmer/sharding/method/db_block_group_map.rb",
    "chars": 10025,
    "preview": "# This is a more sophisticated sharding method based on a two layer database-backed\n# blocks map that holds block-shard "
  },
  {
    "path": "lib/db_charmer/sharding/method/db_block_map.rb",
    "chars": 7260,
    "preview": "# This is a more sophisticated sharding method based on a database-backed\n# blocks map that holds block-shard associatio"
  },
  {
    "path": "lib/db_charmer/sharding/method/hash_map.rb",
    "chars": 532,
    "preview": "module DbCharmer\n  module Sharding\n    module Method\n      class HashMap\n        attr_accessor :map\n\n        def initial"
  },
  {
    "path": "lib/db_charmer/sharding/method/range.rb",
    "chars": 814,
    "preview": "module DbCharmer\n  module Sharding\n    module Method\n      class Range\n        attr_accessor :ranges\n\n        def initia"
  },
  {
    "path": "lib/db_charmer/sharding/method.rb",
    "chars": 342,
    "preview": "module DbCharmer\n  module Sharding\n    module Method\n      autoload :Range, 'db_charmer/sharding/method/range'\n      aut"
  },
  {
    "path": "lib/db_charmer/sharding/stub_connection.rb",
    "chars": 2471,
    "preview": "# This is a simple proxy class used as a default connection on sharded models\n#\n# The idea is to proxy all utility metho"
  },
  {
    "path": "lib/db_charmer/sharding.rb",
    "chars": 602,
    "preview": "module DbCharmer\n  module Sharding\n    autoload :Connection, 'db_charmer/sharding/connection'\n    autoload :StubConnecti"
  },
  {
    "path": "lib/db_charmer/tasks/databases.rake",
    "chars": 2582,
    "preview": "namespace :db_charmer do\n  namespace :create do\n    desc 'Create all the local databases defined in config/database.yml'"
  },
  {
    "path": "lib/db_charmer/version.rb",
    "chars": 163,
    "preview": "module DbCharmer\n  module Version\n    MAJOR = 1\n    MINOR = 9\n    PATCH = 1\n    BUILD = nil\n\n    STRING = [MAJOR, MINOR,"
  },
  {
    "path": "lib/db_charmer/with_remapped_databases.rb",
    "chars": 1489,
    "preview": "module DbCharmer\n  def self.with_remapped_databases(mappings, &proc)\n    old_mappings = ::ActiveRecord::Base.db_charmer_"
  },
  {
    "path": "lib/db_charmer.rb",
    "chars": 8676,
    "preview": "# In Rails 2.2 they did not add it to the autoload so it won't work w/o this require\nrequire 'active_record/version' unl"
  },
  {
    "path": "test-project/.gitignore",
    "chars": 99,
    "preview": "log/*.log\ndb/schema.*\n.idea\nTAGS\nconfig/database.yml\n.bundle\ntmp\n.DS_Store\nvendor\nGemfile.lock\ndoc\n"
  },
  {
    "path": "test-project/.rspec",
    "chars": 32,
    "preview": "--colour\n--format documentation\n"
  },
  {
    "path": "test-project/Gemfile",
    "chars": 1451,
    "preview": "source 'http://rubygems.org'\n\ngem 'rake', \"0.9.2.2\"\ngem 'mysql', \"2.8.1\"\n\ngem 'rspec', '< 3.0'\ngem 'rspec-core', '< 3.0'"
  },
  {
    "path": "test-project/Rakefile",
    "chars": 303,
    "preview": "ENV['RAILS_ENV'] = 'test'\n\n# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/ca"
  },
  {
    "path": "test-project/TODO",
    "chars": 284,
    "preview": "Functionality:\n- Add a controller wrapper to force all queries to the master (thanks mascohism for the idea)\n\nDocs:\n- Do"
  },
  {
    "path": "test-project/app/controllers/application_controller.rb",
    "chars": 80,
    "preview": "class ApplicationController < ActionController::Base\n  protect_from_forgery\nend\n"
  },
  {
    "path": "test-project/app/controllers/posts_controller.rb",
    "chars": 546,
    "preview": "class PostsController < ApplicationController\n  force_slave_reads :only => [ :index, :show, :new ], :except => :new\n\n  #"
  },
  {
    "path": "test-project/app/helpers/application_helper.rb",
    "chars": 29,
    "preview": "module ApplicationHelper\nend\n"
  },
  {
    "path": "test-project/app/models/avatar.rb",
    "chars": 38,
    "preview": "class Avatar < ActiveRecord::Base\nend\n"
  },
  {
    "path": "test-project/app/models/car.rb",
    "chars": 65,
    "preview": "class Car < ActiveRecord::Base\n  db_magic :slave => :slave01\nend\n"
  },
  {
    "path": "test-project/app/models/categories_posts.rb",
    "chars": 89,
    "preview": "class CategoriesPosts < ActiveRecord::Base\n  belongs_to :category\n  belongs_to :post\nend\n"
  },
  {
    "path": "test-project/app/models/category.rb",
    "chars": 73,
    "preview": "class Category < ActiveRecord::Base\n  has_and_belongs_to_many :posts\nend\n"
  },
  {
    "path": "test-project/app/models/comment.rb",
    "chars": 87,
    "preview": "class Comment < ActiveRecord::Base\n  belongs_to :commentable, :polymorphic => true\nend\n"
  },
  {
    "path": "test-project/app/models/event.rb",
    "chars": 160,
    "preview": "class Event < ActiveRecord::Base\n  self.table_name = :timeline_events\n\n  db_magic :sharded => {\n    :key => :to_uid,\n   "
  },
  {
    "path": "test-project/app/models/ford.rb",
    "chars": 20,
    "preview": "class Ford < Car\nend"
  },
  {
    "path": "test-project/app/models/house.rb",
    "chars": 96,
    "preview": "class House < ActiveRecord::Base\n  db_magic :slave => :slave01, :force_slave_reads => false\nend\n"
  },
  {
    "path": "test-project/app/models/log_record.rb",
    "chars": 92,
    "preview": "class LogRecord < ActiveRecord::Base\n  db_magic :connection => :logs\n  belongs_to :user\nend\n"
  },
  {
    "path": "test-project/app/models/post.rb",
    "chars": 473,
    "preview": "class Post < ActiveRecord::Base\n  DB_MAGIC_DEFAULT_PARAMS = { :slave => :slave01, :force_slave_reads => false }\n  db_mag"
  },
  {
    "path": "test-project/app/models/range_sharded_model.rb",
    "chars": 130,
    "preview": "class RangeShardedModel < ActiveRecord::Base\n  db_magic :sharded => {\n    :key => :id,\n    :sharded_connection => :texts"
  },
  {
    "path": "test-project/app/models/toyota.rb",
    "chars": 22,
    "preview": "class Toyota < Car\nend"
  },
  {
    "path": "test-project/app/models/user.rb",
    "chars": 96,
    "preview": "class User < ActiveRecord::Base\n  has_many :posts\n  has_many :log_records\n  has_one :avatar\nend\n"
  },
  {
    "path": "test-project/app/views/layouts/application.html.erb",
    "chars": 209,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <title>DbCharmerSandbox</title>\n  <%= stylesheet_link_tag :all %>\n  <%= javascript_inclu"
  },
  {
    "path": "test-project/app/views/posts/index.html.erb",
    "chars": 137,
    "preview": "<h1>Posts</h1>\n<br/>\n<% @posts.each do |post| %>\n  <p>\n    Post #<%= post.id %><br/>\n    <pre><%= post.inspect %></pre>\n"
  },
  {
    "path": "test-project/app/views/posts/new.html.erb",
    "chars": 66,
    "preview": "<h1>Posts#new</h1>\n<p>Find me in app/views/posts/new.html.erb</p>\n"
  },
  {
    "path": "test-project/app/views/posts/show.html.erb",
    "chars": 68,
    "preview": "<h1>Posts#show</h1>\n<p>Find me in app/views/posts/show.html.erb</p>\n"
  },
  {
    "path": "test-project/config/application.rb",
    "chars": 1934,
    "preview": "require File.expand_path('../boot', __FILE__)\n\nrequire 'rails/all'\n\n# If you have a Gemfile, require the gems listed the"
  },
  {
    "path": "test-project/config/boot.rb",
    "chars": 191,
    "preview": "require 'rubygems'\n\n# Set up gems listed in the Gemfile.\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __F"
  },
  {
    "path": "test-project/config/database.yml.example",
    "chars": 1503,
    "preview": "common: &common\n  adapter: mysql\n  encoding: utf8\n  reconnect: false\n  pool: 10\n  username: root\n  password:\n\n#---------"
  },
  {
    "path": "test-project/config/environment.rb",
    "chars": 160,
    "preview": "# Load the rails application\nrequire File.expand_path('../application', __FILE__)\n\n# Initialize the rails application\nDb"
  },
  {
    "path": "test-project/config/environments/test.rb",
    "chars": 1520,
    "preview": "DbCharmerSandbox::Application.configure do\n  # Settings specified here will take precedence over those in config/applica"
  },
  {
    "path": "test-project/config/initializers/backtrace_silencers.rb",
    "chars": 404,
    "preview": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're"
  },
  {
    "path": "test-project/config/initializers/db_charmer.rb",
    "chars": 111,
    "preview": "DbCharmer.connections_should_exist = false # Since we are not in production\nDbCharmer.enable_controller_magic!\n"
  },
  {
    "path": "test-project/config/initializers/secret_token.rb",
    "chars": 507,
    "preview": "# Be sure to restart your server when you modify this file.\n\n# Your secret key for verifying the integrity of signed coo"
  },
  {
    "path": "test-project/config/initializers/session_store.rb",
    "chars": 445,
    "preview": "# Be sure to restart your server when you modify this file.\n\nDbCharmerSandbox::Application.config.session_store :cookie_"
  },
  {
    "path": "test-project/config/initializers/sharding.rb",
    "chars": 581,
    "preview": "# Range-based shards for testing\n\nTEXTS_SHARDING_RANGES = {\n  0...100   => :shard1,\n  100..200  => :shard2,\n  :default  "
  },
  {
    "path": "test-project/config/locales/en.yml",
    "chars": 213,
    "preview": "# Sample localization file for English. Add more files in this directory for other locales.\n# See http://github.com/sven"
  },
  {
    "path": "test-project/config/routes.rb",
    "chars": 1855,
    "preview": "DbCharmerSandbox::Application.routes.draw do\n  # The priority is based upon order of creation:\n  # first created -> high"
  },
  {
    "path": "test-project/db/create_databases.sql",
    "chars": 468,
    "preview": "drop database if exists db_charmer_sandbox_test;\ncreate database db_charmer_sandbox_test;\n\ndrop database if exists db_ch"
  },
  {
    "path": "test-project/db/migrate/20090810013829_create_log_records.rb",
    "chars": 292,
    "preview": "class CreateLogRecords < ActiveRecord::Migration\n  db_magic :connection => :logs\n\n  def self.up\n    create_table :log_re"
  },
  {
    "path": "test-project/db/migrate/20090810013922_create_posts.rb",
    "chars": 237,
    "preview": "class CreatePosts < ActiveRecord::Migration\n  def self.up\n    create_table :posts do |t|\n      t.string :title\n      t.t"
  },
  {
    "path": "test-project/db/migrate/20090810221944_create_users.rb",
    "chars": 218,
    "preview": "class CreateUsers < ActiveRecord::Migration\n  def self.up\n    create_table :users do |t|\n      t.string :login\n      t.s"
  },
  {
    "path": "test-project/db/migrate/20100305234245_create_categories.rb",
    "chars": 208,
    "preview": "class CreateCategories < ActiveRecord::Migration\n  def self.up\n    create_table :categories do |t|\n      t.string :name\n"
  },
  {
    "path": "test-project/db/migrate/20100305234340_create_categories_posts.rb",
    "chars": 305,
    "preview": "class CreateCategoriesPosts < ActiveRecord::Migration\n  def self.up\n    pk_in_join_table = !DbCharmer.rails3?\n    create"
  },
  {
    "path": "test-project/db/migrate/20100305235831_create_avatars.rb",
    "chars": 224,
    "preview": "class CreateAvatars < ActiveRecord::Migration\n  def self.up\n    create_table :avatars do |t|\n      t.integer :user_id\n  "
  },
  {
    "path": "test-project/db/migrate/20100328201317_create_sharding_map_tables.rb",
    "chars": 1223,
    "preview": "class CreateShardingMapTables < ActiveRecord::Migration\n  db_magic :connection => :social_shard_info\n\n  def self.up\n    "
  },
  {
    "path": "test-project/db/migrate/20100330180517_create_event_tables.rb",
    "chars": 1128,
    "preview": "class CreateEventTables < ActiveRecord::Migration\n  # In test environment just use database.yml-defined connections\n  if"
  },
  {
    "path": "test-project/db/migrate/20100817191548_create_cars.rb",
    "chars": 213,
    "preview": "class CreateCars < ActiveRecord::Migration\n  def self.up\n    create_table :cars do |t|\n      t.string :type\n      t.stri"
  },
  {
    "path": "test-project/db/migrate/20111005193941_create_comments.rb",
    "chars": 331,
    "preview": "class CreateComments < ActiveRecord::Migration\n  def self.up\n    create_table :comments do |t|\n      t.string  :commenta"
  },
  {
    "path": "test-project/db/seeds.rb",
    "chars": 353,
    "preview": "# This file should contain all the record creation needed to seed the database with its default values.\n# The data can t"
  },
  {
    "path": "test-project/db/sharding.sql",
    "chars": 3254,
    "preview": "-- MySQL dump 10.13  Distrib 5.1.44, for apple-darwin10.2.0 (i386)\n--\n-- Host: localhost    Database: db_charmer_sandbox"
  },
  {
    "path": "test-project/spec/controllers/posts_controller_spec.rb",
    "chars": 3450,
    "preview": "require 'spec_helper'\n\ndescribe PostsController do\n  fixtures :posts\n\n  # Delete these examples and add some real ones\n "
  },
  {
    "path": "test-project/spec/fixtures/avatars.yml",
    "chars": 143,
    "preview": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n\none:\n  user_id: 1\n  name: avatar1\n\ntwo:\n  user"
  },
  {
    "path": "test-project/spec/fixtures/categories.yml",
    "chars": 125,
    "preview": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n\none:\n  id: 1\n  name: one\n\ntwo:\n  id: 2\n  name:"
  },
  {
    "path": "test-project/spec/fixtures/categories_posts.yml",
    "chars": 237,
    "preview": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n\none_one:\n  post_id: 1\n  category_id: 1\n\none_tw"
  },
  {
    "path": "test-project/spec/fixtures/comments.yml",
    "chars": 180,
    "preview": "avatar:\n  commentable: one (Avatar)\n  body: \"This is an avatar\"\n\npost:\n  commentable: one (Post)\n  body: \"This is a post"
  },
  {
    "path": "test-project/spec/fixtures/event_shards_info.yml",
    "chars": 601,
    "preview": "shard1:\n  id: 1\n  db_host: localhost\n  db_name: db_charmer_events_test_shard01\n  open: 1\n  enabled: 1\n  blocks_count: 2\n"
  },
  {
    "path": "test-project/spec/fixtures/event_shards_map.yml",
    "chars": 442,
    "preview": "block1:\n  start_id: 0\n  end_id: 10\n  shard_id: 1\n  block_size: 10\n  created_at: <%= Time.now.to_s(:db) %>\n  updated_at: "
  },
  {
    "path": "test-project/spec/fixtures/log_records.yml",
    "chars": 161,
    "preview": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n\none:\n  level: MyString\n  message: MyString\n\ntw"
  },
  {
    "path": "test-project/spec/fixtures/posts.yml",
    "chars": 253,
    "preview": "one:\n  id: 1\n  title: MyString\n  body: MyText\n  user_id: 1\n\ntwo:\n  id: 2\n  title: MyString\n  body: MyText\n  user_id: 2\n\n"
  },
  {
    "path": "test-project/spec/fixtures/users.yml",
    "chars": 228,
    "preview": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n\none:\n  id: 1\n  login: MyString\n  password: MyS"
  },
  {
    "path": "test-project/spec/integration/multi_threading_spec.rb",
    "chars": 1908,
    "preview": "require 'spec_helper'\n\ndescribe \"DbCharmer integration tests\" do\n  def do_test(test_seconds, thread_count)\n    start_tim"
  },
  {
    "path": "test-project/spec/models/avatar_spec.rb",
    "chars": 263,
    "preview": "require 'spec_helper'\n\ndescribe Avatar do\n  before(:each) do\n    @valid_attributes = {\n      :user_id => 1,\n      :name "
  },
  {
    "path": "test-project/spec/models/cars_spec.rb",
    "chars": 658,
    "preview": "require 'spec_helper'\n\ndescribe Ford, \"STI model\" do\n  before(:each) do\n    @valid_attributes = {\n      :license => \"FFG"
  },
  {
    "path": "test-project/spec/models/categories_posts_spec.rb",
    "chars": 273,
    "preview": "require 'spec_helper'\n\ndescribe CategoriesPosts do\n  before(:each) do\n    @valid_attributes = {\n      :post_id => 1,\n   "
  },
  {
    "path": "test-project/spec/models/category_spec.rb",
    "chars": 246,
    "preview": "require 'spec_helper'\n\ndescribe Category do\n  before(:each) do\n    @valid_attributes = {\n      :name => \"value for name\""
  },
  {
    "path": "test-project/spec/models/comment_spec.rb",
    "chars": 283,
    "preview": "require 'spec_helper'\n\ndescribe Comment do\n  fixtures :comments, :avatars, :posts, :users\n\n  describe \"preload polymorph"
  },
  {
    "path": "test-project/spec/models/event_spec.rb",
    "chars": 2476,
    "preview": "require 'spec_helper'\n\ndescribe Event, \"sharded model\" do\n  fixtures :event_shards_info, :event_shards_map\n\n  it \"should"
  },
  {
    "path": "test-project/spec/models/log_record_spec.rb",
    "chars": 289,
    "preview": "require 'spec_helper'\n\ndescribe LogRecord do\n  before(:each) do\n    @valid_attributes = {\n      :level => \"value for lev"
  },
  {
    "path": "test-project/spec/models/post_spec.rb",
    "chars": 273,
    "preview": "require 'spec_helper'\n\ndescribe Post do\n  before(:each) do\n    @valid_attributes = {\n      :title => \"value for title\",\n"
  },
  {
    "path": "test-project/spec/models/range_sharded_model_spec.rb",
    "chars": 1403,
    "preview": "require 'spec_helper'\n\ndescribe RangeShardedModel do\n  describe \"class method shard_for\" do\n    describe \"should correct"
  },
  {
    "path": "test-project/spec/models/user_spec.rb",
    "chars": 820,
    "preview": "require 'spec_helper'\n\ndescribe User do\n  before(:each) do\n    @valid_attributes = {\n      :login => \"value for login\",\n"
  },
  {
    "path": "test-project/spec/sharding/connection_spec.rb",
    "chars": 871,
    "preview": "require 'spec_helper'\n\ndescribe DbCharmer::Sharding::Connection do\n  describe \"in constructor\" do\n    it \"should not fai"
  },
  {
    "path": "test-project/spec/sharding/method/db_block_map_spec.rb",
    "chars": 4519,
    "preview": "require 'spec_helper'\n\ndescribe DbCharmer::Sharding::Method::DbBlockMap do\n  fixtures :event_shards_info, :event_shards_"
  },
  {
    "path": "test-project/spec/sharding/method/hash_map_spec.rb",
    "chars": 1199,
    "preview": "require 'spec_helper'\n\ndescribe DbCharmer::Sharding::Method::HashMap do\n  SHARDING_MAP = {\n    'US'  => :us_users,\n    '"
  },
  {
    "path": "test-project/spec/sharding/method/range_spec.rb",
    "chars": 1438,
    "preview": "require 'spec_helper'\n\ndescribe DbCharmer::Sharding::Method::Range do\n  SHARDING_RANGES = {\n    0...100   => :shard1,\n  "
  },
  {
    "path": "test-project/spec/sharding/sharding_spec.rb",
    "chars": 829,
    "preview": "require 'spec_helper'\n\ndescribe \"DbCharmer::Sharding\" do\n  describe \"in register_connection method\" do\n    it \"should ra"
  },
  {
    "path": "test-project/spec/spec_helper.rb",
    "chars": 1021,
    "preview": "# This file is copied to spec/ when you run 'rails generate rspec:install'\nENV[\"RAILS_ENV\"] = 'test'\nrequire File.expand"
  },
  {
    "path": "test-project/spec/support/rails31_stub_connection.rb",
    "chars": 169,
    "preview": "def stub_columns_for_rails31(connection)\n  return unless DbCharmer.rails31?\n  connection.abstract_connection_class.retri"
  },
  {
    "path": "test-project/spec/unit/abstract_adapter/log_formatting_spec.rb",
    "chars": 999,
    "preview": "require 'spec_helper'\n\nif DbCharmer.rails2?\n  describe 'AbstractAdapter' do\n    it \"should respond to connection_name ac"
  },
  {
    "path": "test-project/spec/unit/action_controller/force_slave_reads_spec.rb",
    "chars": 1691,
    "preview": "require 'spec_helper'\n\nclass BlahController < ActionController::Base; end\n\ndescribe ActionController, \"with force_slave_"
  },
  {
    "path": "test-project/spec/unit/active_record/association_preload_spec.rb",
    "chars": 1822,
    "preview": "require 'spec_helper'\n\nif DbCharmer.rails2?\n  describe \"ActiveRecord preload_associations method\" do\n    it \"should be p"
  },
  {
    "path": "test-project/spec/unit/active_record/association_proxy_spec.rb",
    "chars": 2984,
    "preview": "require 'spec_helper'\n\ndescribe \"DbCharmer::AssociationProxy extending AR::Associations\" do\n  fixtures :users, :posts\n\n "
  },
  {
    "path": "test-project/spec/unit/active_record/class_attributes_spec.rb",
    "chars": 3984,
    "preview": "require 'spec_helper'\n\nclass FooModel < ActiveRecord::Base; end\n\ndescribe DbCharmer, \"for ActiveRecord models\" do\n  cont"
  },
  {
    "path": "test-project/spec/unit/active_record/connection_switching_spec.rb",
    "chars": 3892,
    "preview": "require 'spec_helper'\n\nclass FooModelForConnSwitching < ActiveRecord::Base; end\nclass BarModelForConnSwitching < ActiveR"
  },
  {
    "path": "test-project/spec/unit/active_record/db_magic_spec.rb",
    "chars": 2848,
    "preview": "require 'spec_helper'\n\nclass Blah < ActiveRecord::Base; end\n\ndescribe \"In ActiveRecord models\" do\n  describe \"db_magic m"
  },
  {
    "path": "test-project/spec/unit/active_record/master_slave_routing_spec.rb",
    "chars": 4729,
    "preview": "require 'spec_helper'\n\ndescribe \"ActiveRecord slave-enabled models\" do\n  before do\n    class User < ActiveRecord::Base\n "
  },
  {
    "path": "test-project/spec/unit/active_record/migration/multi_db_migrations_spec.rb",
    "chars": 7626,
    "preview": "require 'spec_helper'\n\nclass SpecMigration < ActiveRecord::Migration\n  def self.up\n    execute \"UPDATE log_records SET l"
  },
  {
    "path": "test-project/spec/unit/active_record/named_scope/named_scope_spec.rb",
    "chars": 1871,
    "preview": "require 'spec_helper'\n\ndescribe \"Named scopes\" do\n  fixtures :users, :posts\n\n  before(:all) do\n    Post.switch_connectio"
  },
  {
    "path": "test-project/spec/unit/active_record/relation_spec.rb",
    "chars": 2489,
    "preview": "require 'spec_helper'\n\nif DbCharmer.rails3?\n  describe \"ActiveRecord::Relation for a model with db_magic\" do\n    before "
  },
  {
    "path": "test-project/spec/unit/connection_factory_spec.rb",
    "chars": 4658,
    "preview": "require 'spec_helper'\n\ndescribe DbCharmer::ConnectionFactory do\n  context \"in generate_abstract_class method\" do\n    it "
  },
  {
    "path": "test-project/spec/unit/connection_proxy_spec.rb",
    "chars": 1006,
    "preview": "require 'spec_helper'\n\ndescribe DbCharmer::ConnectionProxy do\n  before(:each) do\n    class ProxyTest; end\n    @conn = mo"
  },
  {
    "path": "test-project/spec/unit/db_charmer_spec.rb",
    "chars": 2877,
    "preview": "require 'spec_helper'\n\ndescribe DbCharmer do\n  after do\n    DbCharmer.current_controller = nil\n    DbCharmer.connections"
  },
  {
    "path": "test-project/spec/unit/multi_db_proxy_spec.rb",
    "chars": 4877,
    "preview": "require 'spec_helper'\n\ndescribe \"ActiveRecord model with db_magic\" do\n  before do\n    class Blah < ActiveRecord::Base\n  "
  },
  {
    "path": "test-project/spec/unit/with_remapped_databases_spec.rb",
    "chars": 4792,
    "preview": "require 'spec_helper'\n\ndescribe \"DbCharmer#with_remapped_databases\" do\n  before(:all) do\n    DbCharmer.connections_shoul"
  },
  {
    "path": "test-project-2.x/Gemfile",
    "chars": 221,
    "preview": "source 'http://rubygems.org'\n\ngem 'rails', '2.3.18'\n\ngem 'rake', '0.9.2.2'\ngem 'mysql'\n\ngem 'rspec', '1.3.2'\ngem 'rspec-"
  },
  {
    "path": "test-project-2.x/Rakefile",
    "chars": 307,
    "preview": "# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they wil"
  },
  {
    "path": "test-project-2.x/config/boot.rb",
    "chars": 3010,
    "preview": "# We only have test environment here\nENV['RAILS_ENV'] = 'test'\n\n# Don't change this file!\n# Configure your app in config"
  },
  {
    "path": "test-project-2.x/config/database.yml.example",
    "chars": 1502,
    "preview": "common: &common\n  adapter: mysql\n  encoding: utf8\n  reconnect: false\n  pool: 1\n  username: root\n  password:\n\n#----------"
  },
  {
    "path": "test-project-2.x/config/environment.rb",
    "chars": 328,
    "preview": "# Specifies gem version of Rails to use when vendor/rails is not present\nRAILS_GEM_VERSION = '2.3.18' unless defined? RA"
  },
  {
    "path": "test-project-2.x/config/environments/test.rb",
    "chars": 1312,
    "preview": "# Settings specified here will take precedence over those in config/environment.rb\n\n# The test environment is used exclu"
  },
  {
    "path": "test-project-2.x/config/initializers/backtrace_silencers.rb",
    "chars": 404,
    "preview": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're"
  },
  {
    "path": "test-project-2.x/config/initializers/db_charmer.rb",
    "chars": 110,
    "preview": "DbCharmer.connections_should_exist = false # Since we are not in production\nDbCharmer.enable_controller_magic!"
  },
  {
    "path": "test-project-2.x/config/initializers/inflections.rb",
    "chars": 377,
    "preview": "# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules using the following format \n# (a"
  },
  {
    "path": "test-project-2.x/config/initializers/mime_types.rb",
    "chars": 205,
    "preview": "# Be sure to restart your server when you modify this file.\n\n# Add new mime types for use in respond_to blocks:\n# Mime::"
  },
  {
    "path": "test-project-2.x/config/initializers/new_rails_defaults.rb",
    "chars": 778,
    "preview": "# Be sure to restart your server when you modify this file.\n\n# These settings change the behavior of Rails 2 apps and wi"
  },
  {
    "path": "test-project-2.x/config/initializers/session_store.rb",
    "chars": 811,
    "preview": "# Be sure to restart your server when you modify this file.\n\n# Your secret key for verifying cookie session data integri"
  },
  {
    "path": "test-project-2.x/config/initializers/sharding.rb",
    "chars": 581,
    "preview": "# Range-based shards for testing\n\nTEXTS_SHARDING_RANGES = {\n  0...100   => :shard1,\n  100..200  => :shard2,\n  :default  "
  },
  {
    "path": "test-project-2.x/config/locales/en.yml",
    "chars": 212,
    "preview": "# Sample localization file for English. Add more files in this directory for other locales.\n# See http://github.com/sven"
  },
  {
    "path": "test-project-2.x/config/preinitializer.rb",
    "chars": 601,
    "preview": "begin\n  require \"rubygems\"\n  require \"bundler\"\nrescue LoadError\n  raise \"Could not load the bundler gem. Install it with"
  },
  {
    "path": "test-project-2.x/config/routes.rb",
    "chars": 458,
    "preview": "ActionController::Routing::Routes.draw do |map|\n  # Resource routes\n  map.resources :posts\n  map.resources :cars\n\n  # In"
  },
  {
    "path": "test-project-2.x/script/console",
    "chars": 98,
    "preview": "#!/usr/bin/env ruby\nrequire File.dirname(__FILE__) + '/../config/boot'\nrequire 'commands/console'\n"
  },
  {
    "path": "test-project-2.x/spec/spec.opts",
    "chars": 26,
    "preview": "--colour\n--format specdoc\n"
  },
  {
    "path": "test-project-2.x/spec/spec_helper.rb",
    "chars": 1833,
    "preview": "# This file is copied to ~/spec when you run 'ruby script/generate rspec'\n# from the project root directory.\nENV[\"RAILS_"
  }
]

About this extraction

This page contains the full source code of the kovyrin/db-charmer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 160 files (297.8 KB), approximately 84.1k tokens, and a symbol index with 437 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!