[
  {
    "path": ".gitignore",
    "content": "doc\npkg\n.DS_Store\n_site\n.idea\n\n"
  },
  {
    "path": ".travis.yml",
    "content": "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=3.1.12\n  - RAILS_VERSION=3.2.3\n  - RAILS_VERSION=3.2.15\n  - RAILS_VERSION=3.2.15 DB_CHARMER_GEM=1.9.0\n\nnotifications:\n  recipients:\n    - alexey@kovyrin.net\n\nscript: ./ci_build\n\n# Whitelist branches to test\nbranches:\n  only:\n    - master\n    - rails4\n\n# Build matrix configuration\nmatrix:\n  exclude:\n    # Do not run Rails 2.x tests on ruby 1.9\n    - rvm: 1.9.3\n      env: RAILS_VERSION=2.x\n\n    # Do not run Rails 2.x tests on ruby 2.0\n    - rvm: 2.0.0\n      env: RAILS_VERSION=2.x\n\n    # Do not run Rails 3.0 tests on ruby 2.0\n    - rvm: 2.0.0\n      env: RAILS_VERSION=3.0.20\n\n    # Do not run Rails 3.1 tests on ruby 2.0\n    - rvm: 2.0.0\n      env: RAILS_VERSION=3.1.12\n\n    # Do not run early Rails 3.2 tests on ruby 2.0\n    - rvm: 2.0.0\n      env: RAILS_VERSION=3.2.3\n"
  },
  {
    "path": "CHANGES",
    "content": "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 be supported.\n\nFor more information please check out this blog post: http://kovyrin.net/2014/11/14/dbcharmer-suspended/\n\n----------------------------------------------------------------------------------------\n1.9.0 (2013-10-09):\n\nMost of the major changes in this version are related to our initial push towards making\nDbCharmer thread-safe and making sure it works correctly in multi-threaded environments.\n\nPlease note, that even though we now test DbCharmer in multi-threaded environments, we still\nconsider multi-threaded support experimental.\n\nBug fix: Improved Rails environment detection (sometimes DbCharmer would use\nRails-specific code while running in non-rails projects).\n\nBug fix: Make sure on_db() method could restore original connection after an exception is\nraised from a DB driver during connection switching (Thanks to Dmytro Shteflyuk for finding\nthe issue and helping with debugging).\n\nThis is the first release that does not have a really strict constraint for point-releases\nwithin the Rails 3.2.x branch.\n\n----------------------------------------------------------------------------------------\n1.8.4 (2013-03-18):\n\nBumped up rails dependencies up to 3.2.13.\n\n----------------------------------------------------------------------------------------\n1.8.3 (2013-02-11):\n\nBumped up rails dependencies up to 3.2.12.\n\n----------------------------------------------------------------------------------------\n1.8.2 (2013-01-11):\n\nBumped up rails dependencies up to 3.2.11.\n\n----------------------------------------------------------------------------------------\n1.8.1 (2013-01-02):\n\nBumped up rails dependencies up to 3.2.10.\n\n----------------------------------------------------------------------------------------\n1.8.0 (2012-11-12):\n\nAdded support for Rails versions up to 3.2.9. Please note, that Rails 3.2.4 is not officially\nsupported. Your code may work on that version, but no bug reports will be accepted about this\nversion.\n\nTests for DbCharmer have been moved to the gem repository to make Travis-CI integration more\nstable. We do not put test files into the gem inself so it should not be a problem for most\nof the users. If you still use db-charmer as a plugin, please switch to gem mode.\n\n----------------------------------------------------------------------------------------\n1.7.1 (2012-04-22):\n\nBeta feature: Rails 3.1 and 3.2 support\n\nThanks to the community (and Eugene Pimenov aka @libc in particular) we now have support\nfor Rails versions up to 3.2.1, including new migrations classes.\n\n----------------------------------------------------------------------------------------\n1.7.0 (2011-08-29):\n\nBeta feature: Rails 3 support\n\nBeta feature: Added force_slave_reads functionality. Now we could have models with slaves\nthat are not used by default, but could be turned on globally (per-controller or per-action).\n\nHeavily reorganized the source code to match Rails code structure (class names, etc). This should\nmake it much easier for other contributors to work with the code.\nAdded smarter environment detection (using Rails.env, RAILS_ENV or RACK_ENV).\n\nChanged dependencies a bit: instead of depending on rails, we now require specific components\n(ActiveRecord, ActiveSupport, etc) + we do not require blankslate gem anymore.\n\nBugfixes: Fix for N+1 queries when accessing shard_info for db_block_group_map sharding method.\n\n----------------------------------------------------------------------------------------\n1.6.17-19 (2011-04-25):\n\nBugfixes: Do not touch database for sharded models until we really need to. Before 1.6.17\nif a database server was dead and there were any other connection issues, class loading\nin Ruby would be broken and sharded model class would not be initialized.\n\n----------------------------------------------------------------------------------------\n1.6.14 (2011-01-09):\n\nBugfixes: We do not support Rails 3, and now we prohibit any versions but 2.2 and 2.3 from\nbeing used with db-charmer gem.\n\n----------------------------------------------------------------------------------------\n1.6.13 (2010-08-17):\n\nStarting with this version we use Rails.env instead of RAILS_ENV to auto-detect rails\nenvironment. If you use DbCharmer in non-rails project, please set DbCharmer.env manually.\n\nBugfixes: Thanks to Eric Lindvall we now allow connection names that have symbols ruby\nwouldn't like for class names.\n\n----------------------------------------------------------------------------------------\n1.6.12 (2010-05-09):\n\nStarting with this version we use Rails.cache (memcache or whatever you use in your project)\nto cache sharding blocks information.\n\nBugfixes: Thanks to Allen Madsen (github user blatyo) we've fixed a few minor issues in\ndatabase connections handling.\n\n----------------------------------------------------------------------------------------\n1.6.11 (2010-04-16):\n\nBugfix: Change the way we allocate sharding blocks in block map sharding method to\nprevent race-conditions from happening on block to shard assignments.\nBreaking change: We require connections to exist by default in all connection factory\nmethods. If you need old behavior, pass should_exist=false explicitly.\n\n----------------------------------------------------------------------------------------\n1.6.10 (2010-04-09):\n\nMulti-Db migrations changed. Now it is possible to call ActiveRecord::Migration.db_magic\nand specify default migration connection that would be used by all migrations without\nexcplicitly switched connections.\n\n----------------------------------------------------------------------------------------\n1.6.9 (2010-04-08):\n\nBugfix release: now DbCharmer works without Rails.\n\n----------------------------------------------------------------------------------------\n1.6.7 (2010-04-07):\n\nChanged the way we handle associations in on_db(:foo).find(:include) calls. Now we\nswitch association's connection only if its default connection is the same as the\nmaster model's connection (not more \"table does not exist\" problems I hope).\n\n----------------------------------------------------------------------------------------\n1.6.5 (2010-04-05):\n\nBugfix release: Fixed :connection vs :slave in db_magic behaviour. Model.on_master should\nrun queries on the master, not on AR's default connection.\n\n----------------------------------------------------------------------------------------\n1.6.4 (2010-04-05):\n\nDefault behaviour changed: DbCharmer.connections_should_exist is true in all environments\nby default. Old default behaviour was too misleading for many developers.\n\n----------------------------------------------------------------------------------------\n1.6.3 (2010-04-03):\n\nBugfix release: Modified stub connection initialization code to set default connections\nfor sharded models using shards enumeration or default shard features of sharding methods.\n\n----------------------------------------------------------------------------------------\n1.6.2 (2010-04-03):\n\nBugfix release: Modified our stub connection used on sharded models to fail on db-calling\nmethods only. Proxy the rest to a real shard connection. Another bug fixed in db_block_map\nsharding method: we didn't increment block counters when assigning blocks to shards.\n\n----------------------------------------------------------------------------------------\n1.6.1 (2010-03-31):\n\nBreaking change from now on all connection-switching methods (both in migrations and in\nmodels) are controlled by a single option DbCharmer.connections_should_exist. This\noption is false by default in all non-production environments. Check out README for\nmore details.\n\n----------------------------------------------------------------------------------------\n1.6.0 (2010-03-31):\n\nThe major (and arguably the only noticeable) change in this version is our simple database\nsharding support. The feature is still in alpha stage and should not be used in production\nwithout complete understanding of the principles of its work.\n\n----------------------------------------------------------------------------------------\n1.5.5 (2010-03-15):\n\nThanks to ngmoco.com (http://github.com/ngmoco) now DbCharmer supports one more use-case\nfor multi-db migrations. Now you can run the same migration on many databases at once.\nFor example, the following migration would create test_table on all three shard databases:\n\n    class MultiDbTest < ActiveRecord::Migration\n      db_magic :connections => [ :shard01, :shard02, :shard03 ]\n\n      def self.up\n        create_table :test_table do |t|\n          t.string :test_string\n          t.timestamps\n        end\n      end\n\n      def self.down\n        drop_table :test_table\n      end\n    end\n\n----------------------------------------------------------------------------------------\n1.5.4 (2010-03-12):\n\nAdded DbCharmer.with_remapped_databases, so that you can change the connection for\nmany models simultaneously, and implicitly. Very useful for work where you want to use\na particular slave for a whole range of database access.\n\n----------------------------------------------------------------------------------------\n1.5.3 (2010-03-10):\n\nFew changes:\n * Colorized connection names in the logs for development mode\n * We do not log connection names when connection does not exist\n\n----------------------------------------------------------------------------------------\n1.5.1 (2010-03-06):\n\nIn this version we've added support for connection names logging in Rails queries log.\nNew log records have [connection_name] prefix for all queries that are executed on\nnon-standard connections:\n\n[logs]   LogRecord Columns (1.1ms)   SHOW FIELDS FROM `log_records`\n[logs]   User Delete all (0.1ms)   DELETE FROM `users`\n[slave01]   User Load (0.2ms)   SELECT * FROM `users` WHERE (`users`.`login` = 'foo')\n\n----------------------------------------------------------------------------------------\n1.4.6 -> 1.5.0 (2010-03-05):\n\nMajor change in this version of DbCharmer is association preload support. For example,\nlet's say we have a schema:\n\n    class Post < ActiveRecord::Base\n      belongs_to :user\n    end\n\n    class User < ActiveRecord::Base\n      has_many :posts\n    end\n\nNow, if we have the following call in our code:\n\n    User.on_db(:foo).all(:include => :posts)\n\nIn 1.4.6 it would load the users from connection :foo and posts from the\ndefault connection, which is not what we would expect from this line of code.\nSo, starting 1.5.0 all finder calls on models having :include parameter would\nswitch associated models' connections to the same connection as the main model\nin the call.\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License\n\nCopyright (c) 2011, Oleksiy Kovyrin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "doc/files/README_rdoc.html:\tREADME.rdoc\n\trdoc README.rdoc"
  },
  {
    "path": "README.rdoc",
    "content": "= WARNING: The Project Has Been Suspended\n\nPlease note, that this project has been suspended. No updates will be provided and no Rails versions\nbeyond 3.2.x will be supported. For more information please check out this blog post: http://kovyrin.net/2014/11/14/dbcharmer-suspended/\n\n= DB Charmer - ActiveRecord Connection Magic Plugin\n\n+DbCharmer+ is a simple yet powerful plugin for ActiveRecord that significantly extends its ability to work with\nmultiple databases and/or database servers. The major features we add to ActiveRecord are:\n\n1. Simple management for AR model connections (+switch_connection_to+ method)\n2. Switching of default AR model connections to separate servers/databases\n3. Ability to easily choose where your query should go (<tt>Model.on_*</tt> methods family)\n4. Automated master/slave queries routing (selects go to a slave, updates handled by the master).\n5. Multiple database migrations with very flexible query routing controls.\n6. Simple database sharding functionality with multiple sharding methods (value, range, mapping table).\n\nFor more information on the project, you can check out our web site at http://kovyrin.github.io/db-charmer/.\n\n== Installation\n\nThere are two options when approaching +DbCharmer+ installation:\n* using the gem (recommended and the only way of using it with Rails 3.2+)\n* install as a Rails plugin (works in Rails 2.x only)\n\nTo install as a gem, add this to your Gemfile:\n\n  gem 'db-charmer', :require => 'db_charmer'\n\nTo install +DbCharmer+ as a Rails plugin use the following command:\n\n  ./script/plugin install git://github.com/kovyrin/db-charmer.git\n\n_Notice_: If you use +DbCharmer+ in a non-rails project, you may need to set <tt>DbCharmer.env</tt> to a correct value\nbefore using any of its connection management methods. Correct value here is a valid <tt>database.yml</tt>\nfirst-level section name.\n\n\n== Documentation/Questions\n\nFor more information about the library, please visit our site at http://dbcharmer.net.\nIf you need more defails on DbCharmer internals, please check out the source code. All the plugin's\ncode is ~100% covered with tests. The project located in <tt>test-project</tt> directory has unit\ntests for all or, at least, the most actively used code paths.\n\nIf you have any questions regarding this project, you could contact the author using\nthe DbCharmer Users Group mailing list:\n\n- Group Info: http://groups.google.com/group/db-charmer\n- Subscribe using the info page or by sending an email to mailto:db-charmer-subscribe@googlegroups.com\n\n\n== What Ruby and Rails implementations does it work for?\n\nWe have a continuous integration setup for this gem on with Rails 2.3, 3.0, 3.1 and 3.2 using a few\ndifferent versions of Ruby.\n\nCI is running on TravisCI.org: https://travis-ci.org/kovyrin/db-charmer\nBuild 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]\n\nAt the moment we have the following build matrix:\n* Rails versions:\n  - 2.3\n  - 3.0\n  - 3.1\n  - 3.2\n* Ruby versions:\n  - 1.8.7\n  - 1.9.3 (Rails 3.0+ only)\n  - 2.0.0 (Rails 3.2+ only)\n* Databases:\n  - MySQL\n\nIn addition to CI testing, this gem is used in production on Scribd.com (one of the largest RoR\nsites in the world) with Ruby Enterprise Edition and Rails 2.2, Rails 2.3, Sinatra and plain\nRack applications.\n\nStarting with version 1.8.0 we support Rails versions 3.2.8 and higher. Please note, that Rails 3.2.4\nis not officially supported. Your code may work on that version, but no bug reports will be\naccepted about this version.\n\n\n== Is it Thread-Safe?\n\nStarting with version 1.9.0 we have started working on making the code thread-safe and making sure\nDbCharmer works correctly in multi-threaded environments. At this moment we consider multi-threaded\nmode experimental. If you use it and it works for you - please let us know, if it does not - please\nmake sure to file a ticket so that we could improve the code and make it work in your situation.\n\n\n== Who are the authors?\n\nThis plugin has been created in Scribd.com for our internal use and then the sources were opened for\nother people to use. Most of the code in this package has been developed by Oleksiy Kovyrin for\nScribd.com and is released under the MIT license. For more details, see the LICENSE file.\n\nOther contributors who have helped with the development of this library are (alphabetically ordered):\n* Allen Madsen\n* Andrew Geweke\n* Ashley Martens\n* Cauê Guerra\n* David Dai\n* Dmytro Shteflyuk\n* Eric Lindvall\n* Eugene Pimenov\n* Jonathan Viney\n* Gregory Man\n* Michael Birk\n* Tyler McMullen\n"
  },
  {
    "path": "Rakefile",
    "content": "require 'rake'\nrequire 'bundler'\n\nBundler::GemHelper.install_tasks\n"
  },
  {
    "path": "ci_build",
    "content": "#!/bin/bash\n\n# Making the script more robust\nset -e # Exit on errors\nset -u # Exit on uninitialized variables\n\nRAILS_VERSION=${RAILS_VERSION:-}\nif [ \"$RAILS_VERSION\" == \"\" ]; then\n  echo \"Please specify rails version using RAILS_VERSION environment variable!\"\n  exit 1\nfi\n\n# Change directory according to the rails version\nif [ \"$RAILS_VERSION\" == \"2.x\" ]; then\n  # Downgrade rubygems because rails 2.3 does not work on 2.0+\n  gem update --system 1.8.25\n  cd test-project-2.x\nelse\n  cd test-project\nfi\n\n# Print version info\necho \"-----------------------------------------------------------------------------------------------------------------\"\necho \" * Running specs for Rails version $RAILS_VERSION...\"\necho \" * Ruby version: `ruby --version`\"\necho \" * Rubygems version: `gem --version`\"\necho \" * DbCharmer gem version: '${DB_CHARMER_GEM:-trunk}'\"\necho \"-----------------------------------------------------------------------------------------------------------------\"\n\n# Test environment\nexport RAILS_ENV=test\n\n# Configure database access\ncp -f config/database.yml.example config/database.yml\n\n# Create databases and sharding tables\nmysql -u root < db/create_databases.sql\nmysql -u root db_charmer_sandbox_test < db/sharding.sql\n\n# Install gems\nrm -f Gemfile.lock\nbundle install\n\n# Run migrations\nbundle exec rake --trace db:migrate\n\n# Run the build and return its exit code\nif [ \"$RAILS_VERSION\" == \"2.x\" ]; then\n  exec bundle exec spec -p '/*/**/*_spec.rb' -cbfs spec\nelse\n  exec bundle exec rspec -cbfs spec\nfi\n"
  },
  {
    "path": "db-charmer.gemspec",
    "content": "# -*- encoding: utf-8 -*-\n$:.push File.expand_path('../lib', __FILE__)\nrequire 'db_charmer/version'\n\nGem::Specification.new do |s|\n  s.name          = 'db-charmer'\n  s.version       = DbCharmer::Version::STRING\n  s.platform      = Gem::Platform::RUBY\n\n  s.authors       = [ 'Oleksiy Kovyrin' ]\n  s.email         = 'alexey@kovyrin.net'\n  s.homepage      = 'http://kovyrin.github.io/db-charmer/'\n  s.summary       = 'ActiveRecord Connections Magic (slaves, multiple connections, etc)'\n  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.'\n  s.license       = 'MIT'\n\n  s.rdoc_options = [ '--charset=UTF-8' ]\n\n  s.files         = Dir['lib/**/*'] + Dir['*.rb']\n  s.files        += %w[ README.rdoc LICENSE CHANGES ]\n\n  s.require_paths    = [ 'lib' ]\n  s.extra_rdoc_files = [ 'LICENSE', 'README.rdoc' ]\n\n  # Dependencies\n  s.add_dependency 'activesupport', '< 4.0.0'\n  s.add_dependency 'activerecord', '< 4.0.0'\n\n  s.add_development_dependency 'rspec'\n  s.add_development_dependency 'yard'\n  s.add_development_dependency 'actionpack'\nend\n"
  },
  {
    "path": "init.rb",
    "content": "require 'db_charmer'\n"
  },
  {
    "path": "issues/issues-as-of-2014-11-14.json",
    "content": "[\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/98\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/98/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/98/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/98/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/98\",\n    \"id\": 45164122,\n    \"number\": 98,\n    \"title\": \"Rails 4 blocker update_all may ignore condition with db_charmer !!\",\n    \"user\": {\n      \"login\": \"AvnerCohen\",\n      \"id\": 1297254,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1297254?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/AvnerCohen\",\n      \"html_url\": \"https://github.com/AvnerCohen\",\n      \"followers_url\": \"https://api.github.com/users/AvnerCohen/followers\",\n      \"following_url\": \"https://api.github.com/users/AvnerCohen/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/AvnerCohen/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/AvnerCohen/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/AvnerCohen/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/AvnerCohen/orgs\",\n      \"repos_url\": \"https://api.github.com/users/AvnerCohen/repos\",\n      \"events_url\": \"https://api.github.com/users/AvnerCohen/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/AvnerCohen/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2014-10-07T20:42:29Z\",\n    \"updated_at\": \"2014-10-07T20:42:29Z\",\n    \"closed_at\": null,\n    \"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.\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/97\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/97/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/97/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/97/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/97\",\n    \"id\": 38187982,\n    \"number\": 97,\n    \"title\": \"DB connections not closing properly\",\n    \"user\": {\n      \"login\": \"nchafai\",\n      \"id\": 436617,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/436617?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/nchafai\",\n      \"html_url\": \"https://github.com/nchafai\",\n      \"followers_url\": \"https://api.github.com/users/nchafai/followers\",\n      \"following_url\": \"https://api.github.com/users/nchafai/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/nchafai/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/nchafai/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/nchafai/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/nchafai/orgs\",\n      \"repos_url\": \"https://api.github.com/users/nchafai/repos\",\n      \"events_url\": \"https://api.github.com/users/nchafai/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/nchafai/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 2,\n    \"created_at\": \"2014-07-18T15:47:56Z\",\n    \"updated_at\": \"2014-07-21T07:17:26Z\",\n    \"closed_at\": \"2014-07-21T07:16:55Z\",\n    \"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)\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/96\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/96/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/96/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/96/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/96\",\n    \"id\": 35993889,\n    \"number\": 96,\n    \"title\": \"[Rails 4] rake db:migrate:redo doesn't redo all migrations\",\n    \"user\": {\n      \"login\": \"akshetpandey\",\n      \"id\": 1213060,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1213060?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/akshetpandey\",\n      \"html_url\": \"https://github.com/akshetpandey\",\n      \"followers_url\": \"https://api.github.com/users/akshetpandey/followers\",\n      \"following_url\": \"https://api.github.com/users/akshetpandey/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/akshetpandey/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/akshetpandey/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/akshetpandey/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/akshetpandey/orgs\",\n      \"repos_url\": \"https://api.github.com/users/akshetpandey/repos\",\n      \"events_url\": \"https://api.github.com/users/akshetpandey/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/akshetpandey/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2014-06-18T14:58:18Z\",\n    \"updated_at\": \"2014-07-08T00:00:58Z\",\n    \"closed_at\": \"2014-07-08T00:00:58Z\",\n    \"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.\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/95\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/95/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/95/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/95/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/95\",\n    \"id\": 35756037,\n    \"number\": 95,\n    \"title\": \"Rails 4.1+\",\n    \"user\": {\n      \"login\": \"richpeck\",\n      \"id\": 1104431,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1104431?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/richpeck\",\n      \"html_url\": \"https://github.com/richpeck\",\n      \"followers_url\": \"https://api.github.com/users/richpeck/followers\",\n      \"following_url\": \"https://api.github.com/users/richpeck/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/richpeck/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/richpeck/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/richpeck/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/richpeck/orgs\",\n      \"repos_url\": \"https://api.github.com/users/richpeck/repos\",\n      \"events_url\": \"https://api.github.com/users/richpeck/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/richpeck/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 7,\n    \"created_at\": \"2014-06-15T19:23:32Z\",\n    \"updated_at\": \"2014-11-03T15:25:13Z\",\n    \"closed_at\": null,\n    \"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 :(\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/94\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/94/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/94/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/94/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/94\",\n    \"id\": 28744882,\n    \"number\": 94,\n    \"title\": \"Fix #93 Keep slave connections thread local.\",\n    \"user\": {\n      \"login\": \"gworley3\",\n      \"id\": 809976,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/809976?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/gworley3\",\n      \"html_url\": \"https://github.com/gworley3\",\n      \"followers_url\": \"https://api.github.com/users/gworley3/followers\",\n      \"following_url\": \"https://api.github.com/users/gworley3/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/gworley3/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/gworley3/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/gworley3/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/gworley3/orgs\",\n      \"repos_url\": \"https://api.github.com/users/gworley3/repos\",\n      \"events_url\": \"https://api.github.com/users/gworley3/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/gworley3/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2014-03-04T21:57:32Z\",\n    \"updated_at\": \"2014-03-04T21:57:32Z\",\n    \"closed_at\": null,\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/94\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/94\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/94.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/94.patch\"\n    },\n    \"body\": \"This is probably not an ideal fix for #93 but it seems to work.\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/93\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/93/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/93/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/93/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/93\",\n    \"id\": 28739552,\n    \"number\": 93,\n    \"title\": \"Multi-threaded race conditions with Postgres\",\n    \"user\": {\n      \"login\": \"gworley3\",\n      \"id\": 809976,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/809976?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/gworley3\",\n      \"html_url\": \"https://github.com/gworley3\",\n      \"followers_url\": \"https://api.github.com/users/gworley3/followers\",\n      \"following_url\": \"https://api.github.com/users/gworley3/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/gworley3/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/gworley3/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/gworley3/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/gworley3/orgs\",\n      \"repos_url\": \"https://api.github.com/users/gworley3/repos\",\n      \"events_url\": \"https://api.github.com/users/gworley3/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/gworley3/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2014-03-04T20:52:19Z\",\n    \"updated_at\": \"2014-07-09T00:38:31Z\",\n    \"closed_at\": null,\n    \"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```\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/92\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/92/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/92/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/92/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/92\",\n    \"id\": 28669704,\n    \"number\": 92,\n    \"title\": \"habtm associations support  broken in rails 4 branch.\",\n    \"user\": {\n      \"login\": \"bobbarjung\",\n      \"id\": 1243200,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1243200?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/bobbarjung\",\n      \"html_url\": \"https://github.com/bobbarjung\",\n      \"followers_url\": \"https://api.github.com/users/bobbarjung/followers\",\n      \"following_url\": \"https://api.github.com/users/bobbarjung/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/bobbarjung/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/bobbarjung/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/bobbarjung/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/bobbarjung/orgs\",\n      \"repos_url\": \"https://api.github.com/users/bobbarjung/repos\",\n      \"events_url\": \"https://api.github.com/users/bobbarjung/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/bobbarjung/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 6,\n    \"created_at\": \"2014-03-04T00:18:47Z\",\n    \"updated_at\": \"2014-07-29T14:40:22Z\",\n    \"closed_at\": null,\n    \"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.\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/91\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/91/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/91/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/91/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/91\",\n    \"id\": 28574942,\n    \"number\": 91,\n    \"title\": \"can't query against the default db on_db(:default)\",\n    \"user\": {\n      \"login\": \"ohadpartuck\",\n      \"id\": 2236337,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/2236337?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/ohadpartuck\",\n      \"html_url\": \"https://github.com/ohadpartuck\",\n      \"followers_url\": \"https://api.github.com/users/ohadpartuck/followers\",\n      \"following_url\": \"https://api.github.com/users/ohadpartuck/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/ohadpartuck/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/ohadpartuck/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/ohadpartuck/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/ohadpartuck/orgs\",\n      \"repos_url\": \"https://api.github.com/users/ohadpartuck/repos\",\n      \"events_url\": \"https://api.github.com/users/ohadpartuck/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/ohadpartuck/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 1,\n    \"created_at\": \"2014-03-02T07:33:20Z\",\n    \"updated_at\": \"2014-03-02T09:53:04Z\",\n    \"closed_at\": \"2014-03-02T09:52:28Z\",\n    \"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\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/90\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/90/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/90/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/90/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/90\",\n    \"id\": 28014934,\n    \"number\": 90,\n    \"title\": \"RuntimeError: can't add a new key into hash during iteration\",\n    \"user\": {\n      \"login\": \"mhfs\",\n      \"id\": 78422,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/78422?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/mhfs\",\n      \"html_url\": \"https://github.com/mhfs\",\n      \"followers_url\": \"https://api.github.com/users/mhfs/followers\",\n      \"following_url\": \"https://api.github.com/users/mhfs/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/mhfs/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/mhfs/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/mhfs/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/mhfs/orgs\",\n      \"repos_url\": \"https://api.github.com/users/mhfs/repos\",\n      \"events_url\": \"https://api.github.com/users/mhfs/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/mhfs/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 12,\n    \"created_at\": \"2014-02-21T02:38:17Z\",\n    \"updated_at\": \"2014-06-03T23:26:05Z\",\n    \"closed_at\": null,\n    \"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```\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/89\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/89/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/89/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/89/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/89\",\n    \"id\": 27979122,\n    \"number\": 89,\n    \"title\": \"force_slave_reads option ignored\",\n    \"user\": {\n      \"login\": \"gworley3\",\n      \"id\": 809976,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/809976?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/gworley3\",\n      \"html_url\": \"https://github.com/gworley3\",\n      \"followers_url\": \"https://api.github.com/users/gworley3/followers\",\n      \"following_url\": \"https://api.github.com/users/gworley3/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/gworley3/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/gworley3/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/gworley3/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/gworley3/orgs\",\n      \"repos_url\": \"https://api.github.com/users/gworley3/repos\",\n      \"events_url\": \"https://api.github.com/users/gworley3/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/gworley3/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 1,\n    \"created_at\": \"2014-02-20T17:19:06Z\",\n    \"updated_at\": \"2014-02-20T17:41:46Z\",\n    \"closed_at\": \"2014-02-20T17:41:46Z\",\n    \"body\": \"I set `:force_slave_reads => false` in the `db_magic` opts but still reads from slaves by default.\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/88\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/88/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/88/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/88/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/88\",\n    \"id\": 24576212,\n    \"number\": 88,\n    \"title\": \"Skip HasAndBelongsToMany preloader for Rails 4.1\",\n    \"user\": {\n      \"login\": \"kmcbride\",\n      \"id\": 597435,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/597435?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/kmcbride\",\n      \"html_url\": \"https://github.com/kmcbride\",\n      \"followers_url\": \"https://api.github.com/users/kmcbride/followers\",\n      \"following_url\": \"https://api.github.com/users/kmcbride/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/kmcbride/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/kmcbride/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/kmcbride/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/kmcbride/orgs\",\n      \"repos_url\": \"https://api.github.com/users/kmcbride/repos\",\n      \"events_url\": \"https://api.github.com/users/kmcbride/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/kmcbride/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2013-12-19T18:31:26Z\",\n    \"updated_at\": \"2014-06-11T19:21:31Z\",\n    \"closed_at\": \"2014-06-11T19:21:31Z\",\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/88\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/88\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/88.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/88.patch\"\n    },\n    \"body\": \"See: https://github.com/rails/rails/commit/a03ea3ff97b43340d0904525083bf8bc7a1c6ebc\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/87\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/87/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/87/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/87/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/87\",\n    \"id\": 24129460,\n    \"number\": 87,\n    \"title\": \"Make database rake auto load on rails\",\n    \"user\": {\n      \"login\": \"arthurnn\",\n      \"id\": 833383,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/833383?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/arthurnn\",\n      \"html_url\": \"https://github.com/arthurnn\",\n      \"followers_url\": \"https://api.github.com/users/arthurnn/followers\",\n      \"following_url\": \"https://api.github.com/users/arthurnn/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/arthurnn/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/arthurnn/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/arthurnn/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/arthurnn/orgs\",\n      \"repos_url\": \"https://api.github.com/users/arthurnn/repos\",\n      \"events_url\": \"https://api.github.com/users/arthurnn/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/arthurnn/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 3,\n    \"created_at\": \"2013-12-11T19:02:34Z\",\n    \"updated_at\": \"2013-12-12T23:09:55Z\",\n    \"closed_at\": \"2013-12-12T23:08:46Z\",\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/87\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/87\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/87.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/87.patch\"\n    },\n    \"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,\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/86\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/86/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/86/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/86/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/86\",\n    \"id\": 23877630,\n    \"number\": 86,\n    \"title\": \"Allow AR::B.db_magic m/s split to work with abstract AR classes.\",\n    \"user\": {\n      \"login\": \"perplexes\",\n      \"id\": 13812,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/13812?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/perplexes\",\n      \"html_url\": \"https://github.com/perplexes\",\n      \"followers_url\": \"https://api.github.com/users/perplexes/followers\",\n      \"following_url\": \"https://api.github.com/users/perplexes/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/perplexes/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/perplexes/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/perplexes/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/perplexes/orgs\",\n      \"repos_url\": \"https://api.github.com/users/perplexes/repos\",\n      \"events_url\": \"https://api.github.com/users/perplexes/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/perplexes/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2013-12-06T18:56:28Z\",\n    \"updated_at\": \"2013-12-06T18:56:28Z\",\n    \"closed_at\": null,\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/86\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/86\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/86.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/86.patch\"\n    },\n    \"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.\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/85\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/85/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/85/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/85/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/85\",\n    \"id\": 22639819,\n    \"number\": 85,\n    \"title\": \"Rails4 Support\",\n    \"user\": {\n      \"login\": \"kovyrin\",\n      \"id\": 3467,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/3467?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/kovyrin\",\n      \"html_url\": \"https://github.com/kovyrin\",\n      \"followers_url\": \"https://api.github.com/users/kovyrin/followers\",\n      \"following_url\": \"https://api.github.com/users/kovyrin/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/kovyrin/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/kovyrin/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/kovyrin/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/kovyrin/orgs\",\n      \"repos_url\": \"https://api.github.com/users/kovyrin/repos\",\n      \"events_url\": \"https://api.github.com/users/kovyrin/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/kovyrin/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 16,\n    \"created_at\": \"2013-11-14T02:58:39Z\",\n    \"updated_at\": \"2014-10-22T09:35:58Z\",\n    \"closed_at\": null,\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/85\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/85\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/85.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/85.patch\"\n    },\n    \"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.\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/84\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/84/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/84/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/84/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/84\",\n    \"id\": 22639397,\n    \"number\": 84,\n    \"title\": \"License missing from gemspec\",\n    \"user\": {\n      \"login\": \"bf4\",\n      \"id\": 142914,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/142914?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/bf4\",\n      \"html_url\": \"https://github.com/bf4\",\n      \"followers_url\": \"https://api.github.com/users/bf4/followers\",\n      \"following_url\": \"https://api.github.com/users/bf4/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/bf4/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/bf4/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/bf4/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/bf4/orgs\",\n      \"repos_url\": \"https://api.github.com/users/bf4/repos\",\n      \"events_url\": \"https://api.github.com/users/bf4/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/bf4/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 2,\n    \"created_at\": \"2013-11-14T02:46:06Z\",\n    \"updated_at\": \"2013-11-14T04:18:04Z\",\n    \"closed_at\": \"2013-11-14T02:57:03Z\",\n    \"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\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/83\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/83/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/83/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/83/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/83\",\n    \"id\": 22158156,\n    \"number\": 83,\n    \"title\": \"Gemspec updates\",\n    \"user\": {\n      \"login\": \"bradherman\",\n      \"id\": 384172,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/384172?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/bradherman\",\n      \"html_url\": \"https://github.com/bradherman\",\n      \"followers_url\": \"https://api.github.com/users/bradherman/followers\",\n      \"following_url\": \"https://api.github.com/users/bradherman/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/bradherman/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/bradherman/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/bradherman/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/bradherman/orgs\",\n      \"repos_url\": \"https://api.github.com/users/bradherman/repos\",\n      \"events_url\": \"https://api.github.com/users/bradherman/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/bradherman/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 1,\n    \"created_at\": \"2013-11-05T22:50:37Z\",\n    \"updated_at\": \"2013-11-10T06:31:59Z\",\n    \"closed_at\": \"2013-11-10T06:31:59Z\",\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/83\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/83\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/83.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/83.patch\"\n    },\n    \"body\": \"\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/82\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/82/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/82/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/82/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/82\",\n    \"id\": 22002182,\n    \"number\": 82,\n    \"title\": \"Update db-charmer.gemspec\",\n    \"user\": {\n      \"login\": \"yhuang\",\n      \"id\": 154587,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/154587?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/yhuang\",\n      \"html_url\": \"https://github.com/yhuang\",\n      \"followers_url\": \"https://api.github.com/users/yhuang/followers\",\n      \"following_url\": \"https://api.github.com/users/yhuang/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/yhuang/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/yhuang/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/yhuang/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/yhuang/orgs\",\n      \"repos_url\": \"https://api.github.com/users/yhuang/repos\",\n      \"events_url\": \"https://api.github.com/users/yhuang/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/yhuang/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 1,\n    \"created_at\": \"2013-11-02T14:09:36Z\",\n    \"updated_at\": \"2013-11-10T15:41:32Z\",\n    \"closed_at\": \"2013-11-10T15:41:32Z\",\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/82\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/82\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/82.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/82.patch\"\n    },\n    \"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/\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/81\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/81/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/81/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/81/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/81\",\n    \"id\": 21460804,\n    \"number\": 81,\n    \"title\": \"Sharded connection key parameter meaning?\",\n    \"user\": {\n      \"login\": \"fabn\",\n      \"id\": 324213,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/324213?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/fabn\",\n      \"html_url\": \"https://github.com/fabn\",\n      \"followers_url\": \"https://api.github.com/users/fabn/followers\",\n      \"following_url\": \"https://api.github.com/users/fabn/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/fabn/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/fabn/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/fabn/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/fabn/orgs\",\n      \"repos_url\": \"https://api.github.com/users/fabn/repos\",\n      \"events_url\": \"https://api.github.com/users/fabn/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/fabn/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2013-10-23T15:14:48Z\",\n    \"updated_at\": \"2013-10-23T15:14:48Z\",\n    \"closed_at\": null,\n    \"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?\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/80\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/80/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/80/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/80/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/80\",\n    \"id\": 21106472,\n    \"number\": 80,\n    \"title\": \"Bump rails to 3.2.15\",\n    \"user\": {\n      \"login\": \"arthurnn\",\n      \"id\": 833383,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/833383?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/arthurnn\",\n      \"html_url\": \"https://github.com/arthurnn\",\n      \"followers_url\": \"https://api.github.com/users/arthurnn/followers\",\n      \"following_url\": \"https://api.github.com/users/arthurnn/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/arthurnn/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/arthurnn/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/arthurnn/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/arthurnn/orgs\",\n      \"repos_url\": \"https://api.github.com/users/arthurnn/repos\",\n      \"events_url\": \"https://api.github.com/users/arthurnn/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/arthurnn/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2013-10-16T20:13:02Z\",\n    \"updated_at\": \"2013-10-16T20:13:33Z\",\n    \"closed_at\": \"2013-10-16T20:13:33Z\",\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/80\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/80\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/80.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/80.patch\"\n    },\n    \"body\": \"\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/79\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/79/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/79/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/79/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/79\",\n    \"id\": 19604764,\n    \"number\": 79,\n    \"title\": \"Connection not switching connection consistantly.\",\n    \"user\": {\n      \"login\": \"tysliu\",\n      \"id\": 68217,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/68217?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/tysliu\",\n      \"html_url\": \"https://github.com/tysliu\",\n      \"followers_url\": \"https://api.github.com/users/tysliu/followers\",\n      \"following_url\": \"https://api.github.com/users/tysliu/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/tysliu/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/tysliu/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/tysliu/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/tysliu/orgs\",\n      \"repos_url\": \"https://api.github.com/users/tysliu/repos\",\n      \"events_url\": \"https://api.github.com/users/tysliu/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/tysliu/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 6,\n    \"created_at\": \"2013-09-17T09:49:32Z\",\n    \"updated_at\": \"2013-11-14T03:45:53Z\",\n    \"closed_at\": null,\n    \"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!\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/78\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/78/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/78/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/78/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/78\",\n    \"id\": 19461002,\n    \"number\": 78,\n    \"title\": \"Kill rails 2 support\",\n    \"user\": {\n      \"login\": \"arthurnn\",\n      \"id\": 833383,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/833383?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/arthurnn\",\n      \"html_url\": \"https://github.com/arthurnn\",\n      \"followers_url\": \"https://api.github.com/users/arthurnn/followers\",\n      \"following_url\": \"https://api.github.com/users/arthurnn/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/arthurnn/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/arthurnn/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/arthurnn/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/arthurnn/orgs\",\n      \"repos_url\": \"https://api.github.com/users/arthurnn/repos\",\n      \"events_url\": \"https://api.github.com/users/arthurnn/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/arthurnn/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 1,\n    \"created_at\": \"2013-09-13T15:59:17Z\",\n    \"updated_at\": \"2013-11-10T15:44:43Z\",\n    \"closed_at\": \"2013-11-10T15:44:43Z\",\n    \"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?\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/77\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/77/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/77/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/77/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/77\",\n    \"id\": 19411140,\n    \"number\": 77,\n    \"title\": \"Rescue error on drop database on the main db\",\n    \"user\": {\n      \"login\": \"arthurnn\",\n      \"id\": 833383,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/833383?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/arthurnn\",\n      \"html_url\": \"https://github.com/arthurnn\",\n      \"followers_url\": \"https://api.github.com/users/arthurnn/followers\",\n      \"following_url\": \"https://api.github.com/users/arthurnn/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/arthurnn/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/arthurnn/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/arthurnn/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/arthurnn/orgs\",\n      \"repos_url\": \"https://api.github.com/users/arthurnn/repos\",\n      \"events_url\": \"https://api.github.com/users/arthurnn/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/arthurnn/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 1,\n    \"created_at\": \"2013-09-12T20:02:28Z\",\n    \"updated_at\": \"2013-10-16T20:08:52Z\",\n    \"closed_at\": \"2013-10-16T20:08:52Z\",\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/77\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/77\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/77.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/77.patch\"\n    },\n    \"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. \"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/76\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/76/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/76/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/76/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/76\",\n    \"id\": 19410987,\n    \"number\": 76,\n    \"title\": \"Update .travis.yml\",\n    \"user\": {\n      \"login\": \"arthurnn\",\n      \"id\": 833383,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/833383?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/arthurnn\",\n      \"html_url\": \"https://github.com/arthurnn\",\n      \"followers_url\": \"https://api.github.com/users/arthurnn/followers\",\n      \"following_url\": \"https://api.github.com/users/arthurnn/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/arthurnn/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/arthurnn/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/arthurnn/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/arthurnn/orgs\",\n      \"repos_url\": \"https://api.github.com/users/arthurnn/repos\",\n      \"events_url\": \"https://api.github.com/users/arthurnn/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/arthurnn/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2013-09-12T19:59:31Z\",\n    \"updated_at\": \"2013-09-12T20:23:12Z\",\n    \"closed_at\": \"2013-09-12T20:22:48Z\",\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/76\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/76\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/76.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/76.patch\"\n    },\n    \"body\": \"use RAILS_VERSION=3.2.14 on travis.\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/75\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/75/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/75/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/75/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/75\",\n    \"id\": 19130612,\n    \"number\": 75,\n    \"title\": \"Update rails version limits to 3.2.14\",\n    \"user\": {\n      \"login\": \"beedub\",\n      \"id\": 102646,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/102646?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/beedub\",\n      \"html_url\": \"https://github.com/beedub\",\n      \"followers_url\": \"https://api.github.com/users/beedub/followers\",\n      \"following_url\": \"https://api.github.com/users/beedub/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/beedub/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/beedub/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/beedub/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/beedub/orgs\",\n      \"repos_url\": \"https://api.github.com/users/beedub/repos\",\n      \"events_url\": \"https://api.github.com/users/beedub/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/beedub/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 1,\n    \"created_at\": \"2013-09-06T21:56:18Z\",\n    \"updated_at\": \"2013-09-06T21:58:53Z\",\n    \"closed_at\": \"2013-09-06T21:58:48Z\",\n    \"pull_request\": {\n      \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/pulls/75\",\n      \"html_url\": \"https://github.com/kovyrin/db-charmer/pull/75\",\n      \"diff_url\": \"https://github.com/kovyrin/db-charmer/pull/75.diff\",\n      \"patch_url\": \"https://github.com/kovyrin/db-charmer/pull/75.patch\"\n    },\n    \"body\": \"\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/74\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/74/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/74/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/74/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/74\",\n    \"id\": 16779471,\n    \"number\": 74,\n    \"title\": \"hasone relationship does not seem to work with db-charmer\",\n    \"user\": {\n      \"login\": \"bobbarjung\",\n      \"id\": 1243200,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1243200?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/bobbarjung\",\n      \"html_url\": \"https://github.com/bobbarjung\",\n      \"followers_url\": \"https://api.github.com/users/bobbarjung/followers\",\n      \"following_url\": \"https://api.github.com/users/bobbarjung/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/bobbarjung/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/bobbarjung/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/bobbarjung/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/bobbarjung/orgs\",\n      \"repos_url\": \"https://api.github.com/users/bobbarjung/repos\",\n      \"events_url\": \"https://api.github.com/users/bobbarjung/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/bobbarjung/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 0,\n    \"created_at\": \"2013-07-15T21:16:41Z\",\n    \"updated_at\": \"2014-06-11T21:06:07Z\",\n    \"closed_at\": null,\n    \"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.\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/73\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/73/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/73/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/73/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/73\",\n    \"id\": 16121766,\n    \"number\": 73,\n    \"title\": \"Multi-Threading: with_remapped_databases fails to remap classes\",\n    \"user\": {\n      \"login\": \"chadrem\",\n      \"id\": 22150,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/22150?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/chadrem\",\n      \"html_url\": \"https://github.com/chadrem\",\n      \"followers_url\": \"https://api.github.com/users/chadrem/followers\",\n      \"following_url\": \"https://api.github.com/users/chadrem/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/chadrem/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/chadrem/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/chadrem/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/chadrem/orgs\",\n      \"repos_url\": \"https://api.github.com/users/chadrem/repos\",\n      \"events_url\": \"https://api.github.com/users/chadrem/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/chadrem/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n      {\n        \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/labels/reproducible-issue\",\n        \"name\": \"reproducible-issue\",\n        \"color\": \"e10c02\"\n      }\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 4,\n    \"created_at\": \"2013-06-28T00:27:00Z\",\n    \"updated_at\": \"2014-06-11T21:01:35Z\",\n    \"closed_at\": \"2014-06-11T21:01:35Z\",\n    \"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{}\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/72\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/72/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/72/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/72/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/72\",\n    \"id\": 15789793,\n    \"number\": 72,\n    \"title\": \"Difference in schemas between master and slave affects whole app.\",\n    \"user\": {\n      \"login\": \"andriytyurnikov\",\n      \"id\": 3668,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/3668?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/andriytyurnikov\",\n      \"html_url\": \"https://github.com/andriytyurnikov\",\n      \"followers_url\": \"https://api.github.com/users/andriytyurnikov/followers\",\n      \"following_url\": \"https://api.github.com/users/andriytyurnikov/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/andriytyurnikov/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/andriytyurnikov/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/andriytyurnikov/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/andriytyurnikov/orgs\",\n      \"repos_url\": \"https://api.github.com/users/andriytyurnikov/repos\",\n      \"events_url\": \"https://api.github.com/users/andriytyurnikov/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/andriytyurnikov/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 1,\n    \"created_at\": \"2013-06-20T09:39:08Z\",\n    \"updated_at\": \"2013-11-10T15:49:36Z\",\n    \"closed_at\": \"2013-11-10T15:49:36Z\",\n    \"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?)\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/71\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/71/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/71/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/71/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/71\",\n    \"id\": 15777336,\n    \"number\": 71,\n    \"title\": \"Forcing writes to master in bang methods (create!, etc)\",\n    \"user\": {\n      \"login\": \"kpumuk\",\n      \"id\": 10163,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/10163?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/kpumuk\",\n      \"html_url\": \"https://github.com/kpumuk\",\n      \"followers_url\": \"https://api.github.com/users/kpumuk/followers\",\n      \"following_url\": \"https://api.github.com/users/kpumuk/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/kpumuk/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/kpumuk/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/kpumuk/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/kpumuk/orgs\",\n      \"repos_url\": \"https://api.github.com/users/kpumuk/repos\",\n      \"events_url\": \"https://api.github.com/users/kpumuk/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/kpumuk/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n      {\n        \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/labels/reproducible-issue\",\n        \"name\": \"reproducible-issue\",\n        \"color\": \"e10c02\"\n      }\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 1,\n    \"created_at\": \"2013-06-20T01:27:59Z\",\n    \"updated_at\": \"2013-06-20T01:31:16Z\",\n    \"closed_at\": null,\n    \"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\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/70\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/70/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/70/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/70/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/70\",\n    \"id\": 15004735,\n    \"number\": 70,\n    \"title\": \"Support for sharing a connection to same server / switching databases as necessary\",\n    \"user\": {\n      \"login\": \"boourns\",\n      \"id\": 699550,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/699550?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/boourns\",\n      \"html_url\": \"https://github.com/boourns\",\n      \"followers_url\": \"https://api.github.com/users/boourns/followers\",\n      \"following_url\": \"https://api.github.com/users/boourns/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/boourns/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/boourns/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/boourns/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/boourns/orgs\",\n      \"repos_url\": \"https://api.github.com/users/boourns/repos\",\n      \"events_url\": \"https://api.github.com/users/boourns/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/boourns/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"open\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 2,\n    \"created_at\": \"2013-05-31T17:41:34Z\",\n    \"updated_at\": \"2013-05-31T18:48:02Z\",\n    \"closed_at\": null,\n    \"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\"\n  },\n  {\n    \"url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/69\",\n    \"labels_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/69/labels{/name}\",\n    \"comments_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/69/comments\",\n    \"events_url\": \"https://api.github.com/repos/kovyrin/db-charmer/issues/69/events\",\n    \"html_url\": \"https://github.com/kovyrin/db-charmer/issues/69\",\n    \"id\": 14541052,\n    \"number\": 69,\n    \"title\": \"execution expired - timing out getting connections - multi-threading issue\",\n    \"user\": {\n      \"login\": \"dashbitla\",\n      \"id\": 114106,\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/114106?v=3\",\n      \"gravatar_id\": \"\",\n      \"url\": \"https://api.github.com/users/dashbitla\",\n      \"html_url\": \"https://github.com/dashbitla\",\n      \"followers_url\": \"https://api.github.com/users/dashbitla/followers\",\n      \"following_url\": \"https://api.github.com/users/dashbitla/following{/other_user}\",\n      \"gists_url\": \"https://api.github.com/users/dashbitla/gists{/gist_id}\",\n      \"starred_url\": \"https://api.github.com/users/dashbitla/starred{/owner}{/repo}\",\n      \"subscriptions_url\": \"https://api.github.com/users/dashbitla/subscriptions\",\n      \"organizations_url\": \"https://api.github.com/users/dashbitla/orgs\",\n      \"repos_url\": \"https://api.github.com/users/dashbitla/repos\",\n      \"events_url\": \"https://api.github.com/users/dashbitla/events{/privacy}\",\n      \"received_events_url\": \"https://api.github.com/users/dashbitla/received_events\",\n      \"type\": \"User\",\n      \"site_admin\": false\n    },\n    \"labels\": [\n\n    ],\n    \"state\": \"closed\",\n    \"locked\": false,\n    \"assignee\": null,\n    \"milestone\": null,\n    \"comments\": 2,\n    \"created_at\": \"2013-05-20T21:43:35Z\",\n    \"updated_at\": \"2013-11-10T15:52:05Z\",\n    \"closed_at\": \"2013-11-10T15:52:05Z\",\n    \"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\"\n  }\n]\n"
  },
  {
    "path": "lib/db_charmer/action_controller/force_slave_reads.rb",
    "content": "module DbCharmer\n  module ActionController\n    module ForceSlaveReads\n\n      module ClassMethods\n        @@db_charmer_force_slave_reads_actions = {}\n        def force_slave_reads(params = {})\n          @@db_charmer_force_slave_reads_actions[self.name] = {\n            :except => params[:except] ? [*params[:except]].map(&:to_s) : [],\n            :only => params[:only] ? [*params[:only]].map(&:to_s) : []\n          }\n        end\n\n        def force_slave_reads_options\n          @@db_charmer_force_slave_reads_actions[self.name]\n        end\n\n        def force_slave_reads_action?(name = nil)\n          name = name.to_s\n\n          options = force_slave_reads_options\n          # If no options were defined for this controller, all actions are not forced to use slaves\n          return false unless options\n\n          # Actions where force_slave_reads mode was turned off\n          return false if options[:except].include?(name)\n\n          # Only for these actions force_slave_reads was turned on\n          return options[:only].include?(name) if options[:only].any?\n\n          # If :except is not empty, we're done with the checks and rest of the actions are should force slave reads\n          # Otherwise, all the actions are not in force_slave_reads mode\n          options[:except].any?\n        end\n      end\n\n      module InstanceMethods\n        DISPATCH_METHOD = (DbCharmer.rails3?) ? :process_action : :perform_action\n\n        def self.included(base)\n          base.alias_method_chain DISPATCH_METHOD, :forced_slave_reads\n        end\n\n        def force_slave_reads!\n          @db_charmer_force_slave_reads = true\n        end\n\n        def dont_force_slave_reads!\n          @db_charmer_force_slave_reads = false\n        end\n\n        def force_slave_reads?\n          @db_charmer_force_slave_reads || self.class.force_slave_reads_action?(params[:action])\n        end\n\n      protected\n\n        class_eval <<-EOF, __FILE__, __LINE__+1\n          def #{DISPATCH_METHOD}_with_forced_slave_reads(*args, &block)\n            DbCharmer.with_controller(self) do\n              #{DISPATCH_METHOD}_without_forced_slave_reads(*args, &block)\n            end\n          end\n        EOF\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/active_record/association_preload.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module AssociationPreload\n      ASSOCIATION_TYPES = [ :has_one, :has_many, :belongs_to, :has_and_belongs_to_many ]\n\n      def self.extended(base)\n        ASSOCIATION_TYPES.each do |association_type|\n          base.class_eval <<-EOF, __FILE__, __LINE__ + 1\n            def self.preload_#{association_type}_association(records, reflection, preload_options = {})\n              if self.db_charmer_top_level_connection? || reflection.options[:polymorphic] ||\n                    self.db_charmer_default_connection != reflection.klass.db_charmer_default_connection\n                return super(records, reflection, preload_options)\n              end\n              reflection.klass.on_db(self) do\n                super(records, reflection, preload_options)\n              end\n            end\n          EOF\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/active_record/class_attributes.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module ClassAttributes\n      @@db_charmer_opts = {}\n      def db_charmer_opts=(opts)\n        @@db_charmer_opts[self.name] = opts\n      end\n\n      def db_charmer_opts\n        @@db_charmer_opts[self.name] || {}\n      end\n\n      #---------------------------------------------------------------------------------------------\n      @@db_charmer_default_connections = {}\n      def db_charmer_default_connection=(conn)\n        @@db_charmer_default_connections[self.name] = conn\n      end\n\n      def db_charmer_default_connection\n        @@db_charmer_default_connections[self.name]\n      end\n\n      #---------------------------------------------------------------------------------------------\n      @@db_charmer_slaves = {}\n      def db_charmer_slaves=(slaves)\n        @@db_charmer_slaves[self.name] = slaves\n      end\n\n      def db_charmer_slaves\n        @@db_charmer_slaves[self.name] || []\n      end\n\n      # Returns a random connection from the list of slaves configured for this AR class\n      def db_charmer_random_slave\n        return nil unless db_charmer_slaves.any?\n        db_charmer_slaves[rand(db_charmer_slaves.size)]\n      end\n\n      #---------------------------------------------------------------------------------------------\n      def db_charmer_connection_proxies\n        Thread.current[:db_charmer_connection_proxies] ||= {}\n      end\n\n      def db_charmer_connection_proxy=(proxy)\n        db_charmer_connection_proxies[self.name] = proxy\n      end\n\n      def db_charmer_connection_proxy\n        db_charmer_connection_proxies[self.name]\n      end\n\n      #---------------------------------------------------------------------------------------------\n      def db_charmer_force_slave_reads_flags\n        Thread.current[:db_charmer_force_slave_reads] ||= {}\n      end\n\n      def db_charmer_force_slave_reads=(force)\n        db_charmer_force_slave_reads_flags[self.name] = force\n      end\n\n      def db_charmer_force_slave_reads\n        db_charmer_force_slave_reads_flags[self.name]\n      end\n\n      # Slave reads are used in two cases:\n      #  - per-model slave reads are enabled (see db_magic method for more details)\n      #  - global slave reads enforcing is enabled (in a controller action)\n      def db_charmer_force_slave_reads?\n        db_charmer_force_slave_reads || DbCharmer.force_slave_reads?\n      end\n\n      #---------------------------------------------------------------------------------------------\n      def db_charmer_connection_levels\n        Thread.current[:db_charmer_connection_levels] ||= Hash.new(0)\n      end\n\n      def db_charmer_connection_level=(level)\n        db_charmer_connection_levels[self.name] = level\n      end\n\n      def db_charmer_connection_level\n        db_charmer_connection_levels[self.name] || 0\n      end\n\n      def db_charmer_top_level_connection?\n        db_charmer_connection_level.zero?\n      end\n\n      #---------------------------------------------------------------------------------------------\n      def db_charmer_remapped_connection\n        return nil unless db_charmer_top_level_connection?\n        name = :master\n        proxy = db_charmer_model_connection_proxy\n        name = proxy.db_charmer_connection_name.to_sym if proxy\n\n        remapped = db_charmer_database_remappings[name]\n        remapped ? DbCharmer::ConnectionFactory.connect(remapped, true) : nil\n      end\n\n      def db_charmer_database_remappings\n        Thread.current[:db_charmer_database_remappings] ||= Hash.new\n      end\n\n      def db_charmer_database_remappings=(mappings)\n        raise \"Mappings must be nil or respond to []\" if mappings && (! mappings.respond_to?(:[]))\n        Thread.current[:db_charmer_database_remappings] = mappings || {}\n      end\n\n      #---------------------------------------------------------------------------------------------\n      # Returns model-specific connection proxy, ignoring any global connection remappings\n      def db_charmer_model_connection_proxy\n        db_charmer_connection_proxy || db_charmer_default_connection\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/active_record/connection_switching.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module ConnectionSwitching\n      def establish_real_connection_if_exists(name, should_exist = false)\n        name = name.to_s\n\n        # Check environment name\n        config = configurations[DbCharmer.env]\n        unless config\n          error = \"Invalid environment name (does not exist in database.yml): #{DbCharmer.env}. Please set correct Rails.env or DbCharmer.env.\"\n          raise ArgumentError, error\n        end\n\n        # Check connection name\n        config = config[name]\n        unless config\n          if should_exist\n            raise ArgumentError, \"Invalid connection name (does not exist in database.yml): #{DbCharmer.env}/#{name}\"\n          end\n          return # No need to establish connection - they do not want us to\n        end\n\n        # Pass connection name with config\n        config[:connection_name] = name\n        establish_connection(config)\n      end\n\n      #-----------------------------------------------------------------------------------------------------------------\n      def hijack_connection!\n        return if self.respond_to?(:connection_with_magic)\n        class << self\n          # Make sure we check our accessors before going to the default connection retrieval method\n          def connection_with_magic\n            db_charmer_remapped_connection || db_charmer_model_connection_proxy || connection_without_magic\n          end\n          alias_method_chain :connection, :magic\n\n          def connection_pool_with_magic\n            if connection.respond_to?(:abstract_connection_class)\n              abstract_connection_class = connection.abstract_connection_class\n              connection_handler.retrieve_connection_pool(abstract_connection_class) || connection_pool_without_magic\n            else\n              connection_pool_without_magic\n            end\n          end\n          alias_method_chain :connection_pool, :magic\n        end\n      end\n\n      #-----------------------------------------------------------------------------------------------------------------\n      def coerce_to_connection_proxy(conn, should_exist = true)\n        # Return nil if given no connection specification\n        return nil if conn.nil?\n\n        # For sharded proxies just use them as-is\n        return conn if conn.respond_to?(:set_real_connection)\n\n        # For connection proxies and objects that could be coerced into a proxy just call the coercion method\n        return conn.db_charmer_connection_proxy if conn.respond_to?(:db_charmer_connection_proxy)\n\n        # For plain AR connection adapters, just use them as-is\n        return conn if conn.kind_of?(::ActiveRecord::ConnectionAdapters::AbstractAdapter)\n\n        # For connection names, use connection factory to create new connections\n        if conn.kind_of?(Symbol) || conn.kind_of?(String)\n          return DbCharmer::ConnectionFactory.connect(conn, should_exist)\n        end\n\n        # For connection configs (hashes), create connections\n        if conn.kind_of?(Hash)\n          conn = conn.symbolize_keys\n          raise ArgumentError, \"Missing required :connection_name parameter\" unless conn[:connection_name]\n          return DbCharmer::ConnectionFactory.connect_to_db(conn[:connection_name], conn)\n        end\n\n        # Fails for unsupported connection types\n        raise \"Unsupported connection type: #{conn.class}\"\n      end\n\n      #-----------------------------------------------------------------------------------------------------------------\n      def switch_connection_to(conn, should_exist = true)\n        new_conn = coerce_to_connection_proxy(conn, should_exist)\n\n        if db_charmer_connection_proxy.respond_to?(:set_real_connection)\n          db_charmer_connection_proxy.set_real_connection(new_conn)\n        end\n\n        self.db_charmer_connection_proxy = new_conn\n        self.hijack_connection!\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/active_record/db_magic.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module DbMagic\n\n      def db_magic(opt = {})\n        # Make sure we could use our connections management here\n        hijack_connection!\n\n        # Should requested connections exist in the config?\n        should_exist = opt.has_key?(:should_exist) ? opt[:should_exist] : DbCharmer.connections_should_exist?\n\n        # Main connection management\n        setup_connection_magic(opt[:connection], should_exist)\n\n        # Set up slaves pool\n        opt[:slaves] ||= []\n        opt[:slaves] = [ opt[:slaves] ].flatten\n        opt[:slaves] << opt[:slave] if opt[:slave]\n\n        # Forced reads are enabled for all models by default, could be disabled by the user\n        forced_slave_reads = opt.has_key?(:force_slave_reads) ? opt[:force_slave_reads] : true\n\n        # Setup all the slaves related magic if needed\n        setup_slaves_magic(opt[:slaves], forced_slave_reads, should_exist)\n\n        # Setup inheritance magic\n        setup_children_magic(opt)\n\n        # Setup sharding if needed\n        if opt[:sharded]\n          raise ArgumentError, \"Can't use sharding on a model with slaves!\" if opt[:slaves].any?\n          setup_sharding_magic(opt[:sharded])\n        end\n      end\n\n    private\n\n      def setup_children_magic(opt)\n        self.db_charmer_opts = opt.clone\n\n        unless self.respond_to?(:inherited_with_db_magic)\n          class << self\n            def inherited_with_db_magic(child)\n              o = inherited_without_db_magic(child)\n              child.db_magic(self.db_charmer_opts)\n              o\n            end\n            alias_method_chain :inherited, :db_magic\n          end\n        end\n      end\n\n      def setup_sharding_magic(config)\n        # Add sharding-specific methods\n        self.extend(DbCharmer::ActiveRecord::Sharding)\n\n        # Get configuration\n        name = config[:sharded_connection] or raise ArgumentError, \"No :sharded_connection!\"\n        # Assign sharded connection\n        self.sharded_connection = DbCharmer::Sharding.sharded_connection(name)\n\n        # Setup model default connection\n        setup_connection_magic(sharded_connection.default_connection)\n      end\n\n      def setup_connection_magic(conn, should_exist = true)\n        conn_proxy = coerce_to_connection_proxy(conn, should_exist)\n        self.db_charmer_default_connection = conn_proxy\n        switch_connection_to(conn_proxy, should_exist)\n      end\n\n      def setup_slaves_magic(slaves, force_slave_reads, should_exist = true)\n        self.db_charmer_force_slave_reads = force_slave_reads\n\n        # Initialize the slave connections list\n        self.db_charmer_slaves = slaves.collect do |slave|\n          coerce_to_connection_proxy(slave, should_exist)\n        end\n        return if db_charmer_slaves.empty?\n\n        # Enable on_slave/on_master methods\n        self.extend(DbCharmer::ActiveRecord::MultiDbProxy::MasterSlaveClassMethods)\n\n        # Enable automatic master/slave queries routing (we have specialized versions on those modules for rails2/3)\n        self.extend(DbCharmer::ActiveRecord::MasterSlaveRouting::ClassMethods)\n        self.send(:include, DbCharmer::ActiveRecord::MasterSlaveRouting::InstanceMethods)\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/active_record/migration/multi_db_migrations.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module Migration\n      module MultiDbMigrations\n\n        def self.append_features(base)\n          return false if base < self\n          super\n          base.extend const_get(\"ClassMethods\") if const_defined?(\"ClassMethods\")\n\n          base.class_eval do\n            if DbCharmer.rails31?\n              alias_method_chain :migrate, :db_wrapper\n            else\n              class << self\n                alias_method_chain :migrate, :db_wrapper\n              end\n            end\n          end\n        end\n\n        module ClassMethods\n          @@multi_db_names = {}\n          def multi_db_names\n            @@multi_db_names[self.name] || @@multi_db_names['ActiveRecord::Migration']\n          end\n\n          def multi_db_names=(names)\n            @@multi_db_names[self.name] = names\n          end\n\n          unless DbCharmer.rails31?\n            def migrate_with_db_wrapper(direction)\n              if names = multi_db_names\n                names.each do |multi_db_name|\n                  on_db(multi_db_name) do\n                    migrate_without_db_wrapper(direction)\n                  end\n                end\n              else\n                migrate_without_db_wrapper(direction)\n              end\n            end\n\n            def on_db(db_name)\n              name = db_name.is_a?(Hash) ? db_name[:connection_name] : db_name.inspect\n              announce \"Switching connection to #{name}\"\n              # Switch connection\n              old_proxy = ::ActiveRecord::Base.db_charmer_connection_proxy\n              db_name = nil if db_name == :default\n              ::ActiveRecord::Base.switch_connection_to(db_name, DbCharmer.connections_should_exist?)\n              # Yield the block\n              yield\n            ensure\n              # Switch it back\n              ::ActiveRecord::Base.verify_active_connections!\n              announce \"Switching connection back\"\n              ::ActiveRecord::Base.switch_connection_to(old_proxy)\n            end\n          end\n\n          def db_magic(opts = {})\n            # Collect connections from all possible options\n            conns = [ opts[:connection], opts[:connections] ]\n            conns << shard_connections(opts[:sharded_connection]) if opts[:sharded_connection]\n\n            # Get a unique set of connections\n            conns = conns.flatten.compact.uniq\n            raise ArgumentError, \"No connection name - no magic!\" unless conns.any?\n\n            # Save connections\n            self.multi_db_names = conns\n          end\n\n          # Return a list of connections to shards in a sharded connection\n          def shard_connections(conn_name)\n            conn = DbCharmer::Sharding.sharded_connection(conn_name)\n            conn.shard_connections\n          end\n        end\n\n        def migrate_with_db_wrapper(direction)\n          if names = self.class.multi_db_names\n            names.each do |multi_db_name|\n              on_db(multi_db_name) do\n                migrate_without_db_wrapper(direction)\n              end\n            end\n          else\n            migrate_without_db_wrapper(direction)\n          end\n        end\n\n        def record_on_db(db_name, block)\n          recorder = ::ActiveRecord::Migration::CommandRecorder.new(DbCharmer::ConnectionFactory.connect(db_name))\n          old_recorder, @connection = @connection, recorder\n          block.call\n          old_recorder.record :on_db, [db_name, @connection]\n          @connection = old_recorder\n        end\n\n        def replay_commands_on_db(name, commands)\n          on_db(name) do\n            commands.each do |cmd, args|\n              send(cmd, *args)\n            end\n          end\n        end\n\n        def on_db(db_name, &block)\n          if @connection.is_a?(::ActiveRecord::Migration::CommandRecorder)\n            record_on_db(db_name, block)\n            return\n          end\n\n          name = db_name.is_a?(Hash) ? db_name[:connection_name] : db_name.inspect\n          announce \"Switching connection to #{name}\"\n          # Switch connection\n          old_connection, old_proxy = @connection, ::ActiveRecord::Base.db_charmer_connection_proxy\n          db_name = nil if db_name == :default\n          ::ActiveRecord::Base.switch_connection_to(db_name, DbCharmer.connections_should_exist?)\n          # Yield the block\n          ::ActiveRecord::Base.connection_pool.with_connection do |conn|\n            @connection = conn\n            yield\n          end\n        ensure\n          @connection = old_connection\n          # Switch it back\n          ::ActiveRecord::Base.verify_active_connections!\n          announce \"Switching connection back\"\n          ::ActiveRecord::Base.switch_connection_to(old_proxy)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/active_record/multi_db_proxy.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module MultiDbProxy\n      # Simple proxy class that switches connections and then proxies all the calls\n      # This class is used to implement chained on_db calls\n      class OnDbProxy < ActiveSupport::BasicObject\n        # We need to do this because in Rails 2.3 BasicObject does not remove object_id method, which is stupid\n        undef_method(:object_id) if instance_methods.member?('object_id')\n\n        def initialize(proxy_target, slave)\n          @proxy_target = proxy_target\n          @slave = slave\n        end\n\n      private\n\n        def method_missing(meth, *args, &block)\n          # Switch connection and proxy the method call\n          @proxy_target.on_db(@slave) do |proxy_target|\n            res = proxy_target.__send__(meth, *args, &block)\n\n            # If result is a scope/association, return a new proxy for it, otherwise return the result itself\n            (res.proxy?) ? OnDbProxy.new(res, @slave) : res\n          end\n        end\n      end\n\n      module ClassMethods\n        def on_db(con, proxy_target = nil)\n          proxy_target ||= self\n\n          # Chain call\n          return OnDbProxy.new(proxy_target, con) unless block_given?\n\n          # Block call\n          begin\n            self.db_charmer_connection_level += 1\n            old_proxy = db_charmer_connection_proxy\n            switch_connection_to(con, DbCharmer.connections_should_exist?)\n            yield(proxy_target)\n          ensure\n            switch_connection_to(old_proxy)\n            self.db_charmer_connection_level -= 1\n          end\n        end\n      end\n\n      module InstanceMethods\n        def on_db(con, proxy_target = nil, &block)\n          proxy_target ||= self\n          self.class.on_db(con, proxy_target, &block)\n        end\n      end\n\n      module MasterSlaveClassMethods\n        def on_slave(con = nil, proxy_target = nil, &block)\n          con ||= db_charmer_random_slave\n          raise ArgumentError, \"No slaves found in the class and no slave connection given\" unless con\n          on_db(con, proxy_target, &block)\n        end\n\n        def on_master(proxy_target = nil, &block)\n          on_db(db_charmer_default_connection, proxy_target, &block)\n        end\n\n        def first_level_on_slave\n          first_level = db_charmer_top_level_connection? && on_master.connection.open_transactions.zero?\n          if first_level && db_charmer_force_slave_reads? && db_charmer_slaves.any?\n            on_slave { yield }\n          else\n            yield\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/active_record/sharding.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module Sharding\n\n      def self.extended(model)\n        model.cattr_accessor(:sharded_connection)\n      end\n\n      def shard_for(key, proxy_target = nil, &block)\n        raise ArgumentError, \"No sharded connection configured!\" unless sharded_connection\n        conn = sharded_connection.sharder.shard_for_key(key)\n        on_db(conn, proxy_target, &block)\n      end\n\n      # Run on default shard (if supported by the sharding method)\n      def on_default_shard(proxy_target = nil, &block)\n        raise ArgumentError, \"No sharded connection configured!\" unless sharded_connection\n\n        if sharded_connection.support_default_shard?\n          shard_for(:default, proxy_target, &block)\n        else\n          raise ArgumentError, \"This model's sharding method does not support default shard\"\n        end\n      end\n\n      # Enumerate shards\n      def on_each_shard(proxy_target = nil, &block)\n        raise ArgumentError, \"No sharded connection configured!\" unless sharded_connection\n\n        conns = sharded_connection.shard_connections\n        raise ArgumentError, \"This model's sharding method does not support shards enumeration\" unless conns\n\n        conns.each do |conn|\n          on_db(conn, proxy_target, &block)\n        end\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/connection_factory.rb",
    "content": "#\n# This class is used to automatically generate small abstract ActiveRecord classes\n# that would then be used as a source of database connections for DbCharmer magic.\n# This way we do not need to re-implement all the connection establishing code\n# that ActiveRecord already has and we make our code less dependant on Rails versions.\n#\nmodule DbCharmer\n  module ConnectionFactory\n    def self.connection_classes\n      Thread.current[:db_charmer_generated_connection_classes] ||= {}\n    end\n\n    def self.connection_classes=(val)\n      Thread.current[:db_charmer_generated_connection_classes] = val\n    end\n\n    def self.reset!\n      self.connection_classes = {}\n    end\n\n    # Establishes connection or return an existing one from cache\n    def self.connect(connection_name, should_exist = true)\n      connection_name = connection_name.to_s\n      connection_classes[connection_name] ||= establish_connection(connection_name, should_exist)\n    end\n\n    # Establishes connection or return an existing one from cache (not using AR database configs)\n    def self.connect_to_db(connection_name, config)\n      connection_name = connection_name.to_s\n      connection_classes[connection_name] ||= establish_connection_to_db(connection_name, config)\n    end\n\n    # Establish connection with a specified name\n    def self.establish_connection(connection_name, should_exist = true)\n      abstract_class = generate_abstract_class(connection_name, should_exist)\n      DbCharmer::ConnectionProxy.new(abstract_class, connection_name)\n    end\n\n    # Establish connection with a specified name (not using AR database configs)\n    def self.establish_connection_to_db(connection_name, config)\n      abstract_class = generate_abstract_class_for_db(connection_name, config)\n      DbCharmer::ConnectionProxy.new(abstract_class, connection_name)\n    end\n\n    # Generate an abstract AR class with specified connection established\n    def self.generate_abstract_class(connection_name, should_exist = true)\n      # Generate class\n      klass = generate_empty_abstract_ar_class(abstract_connection_class_name(connection_name))\n\n      # Establish connection\n      klass.establish_real_connection_if_exists(connection_name.to_sym, !!should_exist)\n\n      # Return the class\n      return klass\n    end\n\n    # Generate an abstract AR class with specified connection established (not using AR database configs)\n    def self.generate_abstract_class_for_db(connection_name, config)\n      # Generate class\n      klass = generate_empty_abstract_ar_class(abstract_connection_class_name(connection_name))\n\n      # Establish connection\n      klass.establish_connection(config)\n\n      # Return the class\n      return klass\n    end\n\n    def self.generate_empty_abstract_ar_class(klass)\n      # Define class\n      module_eval \"class #{klass} < ::ActiveRecord::Base; self.abstract_class = true; end\"\n\n      # Return class\n      klass.constantize\n    end\n\n    # Generates unique names for our abstract AR classes\n    def self.abstract_connection_class_name(connection_name)\n      conn_name_klass = connection_name.to_s.gsub(/\\W+/, '_').camelize\n      thread = Thread.current.object_id.abs # need to make sure it is non-negative\n      \"::AutoGeneratedAbstractConnectionClass#{conn_name_klass}ForThread#{thread}\"\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/connection_proxy.rb",
    "content": "# Simple proxy that sends all method calls to a real database connection\nmodule DbCharmer\n  class ConnectionProxy < ActiveSupport::BasicObject\n    # We need to do this because in Rails 2.3 BasicObject does not remove object_id method, which is stupid\n    undef_method(:object_id) if instance_methods.member?('object_id')\n\n    # We use this to get a connection class from the proxy\n    attr_accessor :abstract_connection_class\n\n    def initialize(abstract_class, db_name)\n      @abstract_connection_class = abstract_class\n      @db_name = db_name\n    end\n\n    def db_charmer_connection_name\n      @db_name\n    end\n\n    def db_charmer_connection_proxy\n      self\n    end\n\n    def db_charmer_retrieve_connection\n      @abstract_connection_class.retrieve_connection\n    end\n\n    def nil?\n      false\n    end\n\n    #-----------------------------------------------------------------------------------------------\n    RESPOND_TO_METHODS = [\n      :abstract_connection_class,\n      :db_charmer_connection_name,\n      :db_charmer_connection_proxy,\n      :db_charmer_retrieve_connection,\n      :nil?\n    ].freeze\n\n    # Short-circuit some of the methods for which we know there is a separate check in coercion code\n    DOESNT_RESPOND_TO_METHODS = [\n      :set_real_connection\n    ].freeze\n\n    def respond_to?(method_name, include_all = false)\n      return true if RESPOND_TO_METHODS.include?(method_name)\n      return false if DOESNT_RESPOND_TO_METHODS.include?(method_name)\n      db_charmer_retrieve_connection.respond_to?(method_name, include_all)\n    end\n\n    #-----------------------------------------------------------------------------------------------\n    def method_missing(meth, *args, &block)\n      db_charmer_retrieve_connection.send(meth, *args, &block)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/core_extensions.rb",
    "content": "class Object\n  unless defined?(try)\n    def try(method, *options, &block)\n      send(method, *options, &block)\n    end\n  end\n\n  # These methods are added to all objects so we could call proxy? on anything\n  # and figure if an object is a proxy w/o hitting method_missing or respond_to?\n  def self.proxy?\n    false\n  end\n\n  def proxy?\n    false\n  end\nend\n\nclass NilClass\n  def try(*args)\n    nil\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/force_slave_reads.rb",
    "content": "module DbCharmer\n  def self.current_controller\n    Thread.current[:db_charmer_current_controller]\n  end\n\n  def self.current_controller=(val)\n    Thread.current[:db_charmer_current_controller] = val\n  end\n\n  #-------------------------------------------------------------------------------------------------\n  def self.forced_slave_reads_setting\n    Thread.current[:db_charmer_forced_slave_reads]\n  end\n\n  def self.forced_slave_reads_setting=(val)\n    Thread.current[:db_charmer_forced_slave_reads] = val\n  end\n\n  #-------------------------------------------------------------------------------------------------\n  def self.force_slave_reads?\n    # If global force slave reads is requested, do it\n    return true if Thread.current[:db_charmer_forced_slave_reads]\n\n    # If not, try to use current controller to decide on this\n    return false unless current_controller.respond_to?(:force_slave_reads?)\n\n    slave_reads = current_controller.force_slave_reads?\n    logger.debug(\"Using controller to figure out if slave reads should be forced: #{slave_reads}\")\n    return slave_reads\n  end\n\n  #-------------------------------------------------------------------------------------------------\n  def self.with_controller(controller)\n    raise ArgumentError, \"No block given\" unless block_given?\n    logger.debug(\"Setting current controller for db_charmer: #{controller.class.name}\")\n    self.current_controller = controller\n    yield\n  ensure\n    logger.debug('Clearing current controller for db_charmer')\n    self.current_controller = nil\n  end\n\n  #-------------------------------------------------------------------------------------------------\n  # Force all reads in a block of code to go to a slave\n  def self.force_slave_reads\n    raise ArgumentError, \"No block given\" unless block_given?\n    old_forced_slave_reads = self.forced_slave_reads_setting\n    begin\n      self.forced_slave_reads_setting = true\n      yield\n    ensure\n      self.forced_slave_reads_setting = old_forced_slave_reads\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails2/abstract_adapter/log_formatting.rb",
    "content": "module DbCharmer\n  module AbstractAdapter\n    module LogFormatting\n\n      def self.included(base)\n        base.alias_method_chain :format_log_entry, :connection_name\n      end\n\n      def connection_name\n        raise \"Can't find connection configuration!\" unless @config\n        @config[:connection_name]\n      end\n\n      # Rails 2.X specific logging method\n      def format_log_entry_with_connection_name(message, dump = nil)\n        msg = connection_name ? \"[#{connection_name}] \" : ''\n        msg = \"  \\e[0;34;1m#{msg}\\e[0m\" if connection_name && ::ActiveRecord::Base.colorize_logging\n        msg << format_log_entry_without_connection_name(message, dump)\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails2/active_record/master_slave_routing.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module MasterSlaveRouting\n\n      module ClassMethods\n        SLAVE_METHODS = [ :find_by_sql, :count_by_sql, :calculate ]\n        MASTER_METHODS = [ :update, :create, :delete, :destroy, :delete_all, :destroy_all, :update_all, :update_counters ]\n\n        SLAVE_METHODS.each do |slave_method|\n          class_eval <<-EOF, __FILE__, __LINE__ + 1\n            def #{slave_method}(*args, &block)\n              first_level_on_slave do\n                super(*args, &block)\n              end\n            end\n          EOF\n        end\n\n        MASTER_METHODS.each do |master_method|\n          class_eval <<-EOF, __FILE__, __LINE__ + 1\n            def #{master_method}(*args, &block)\n              on_master do\n                super(*args, &block)\n              end\n            end\n          EOF\n        end\n\n        def find(*args, &block)\n          options = args.last\n          if options.is_a?(Hash) && options[:lock]\n            on_master { super(*args, &block) }\n          else\n            super(*args, &block)\n          end\n        end\n      end\n\n      module InstanceMethods\n        def reload(*args, &block)\n          self.class.on_master do\n            super(*args, &block)\n          end\n        end\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails2/active_record/named_scope/scope_proxy.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module NamedScope\n      module ScopeProxy\n\n        def proxy?\n          true\n        end\n\n        def on_db(con, proxy_target = nil, &block)\n          proxy_target ||= self\n          proxy_scope.on_db(con, proxy_target, &block)\n        end\n\n        def on_slave(con = nil, &block)\n          proxy_scope.on_slave(con, self, &block)\n        end\n\n        def on_master(&block)\n          proxy_scope.on_master(self, &block)\n        end\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails3/abstract_adapter/connection_name.rb",
    "content": "module DbCharmer\n  module AbstractAdapter\n    module ConnectionName\n\n      # We use this proxy to push connection name down to instrumenters w/o monkey-patching the log method itself\n      class InstrumenterDecorator < ActiveSupport::BasicObject\n        def initialize(adapter, instrumenter)\n          @adapter = adapter\n          @instrumenter = instrumenter\n        end\n\n        def instrument(name, payload = {}, &block)\n          payload[:connection_name] ||= @adapter.connection_name\n          @instrumenter.instrument(name, payload, &block)\n        end\n\n        def method_missing(meth, *args, &block)\n          @instrumenter.send(meth, *args, &block)\n        end\n      end\n\n      def self.included(base)\n        base.alias_method_chain :initialize, :connection_name\n      end\n\n      def connection_name\n        raise \"Can't find connection configuration!\" unless @config\n        @config[:connection_name]\n      end\n\n      def initialize_with_connection_name(*args)\n        initialize_without_connection_name(*args)\n        @instrumenter = InstrumenterDecorator.new(self, @instrumenter)\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails3/active_record/log_subscriber.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module LogSubscriber\n\n      def self.included(base)\n        base.send(:attr_accessor, :connection_name)\n        base.alias_method_chain :sql, :connection_name\n        base.alias_method_chain :debug, :connection_name\n      end\n\n      def sql_with_connection_name(event)\n        self.connection_name = event.payload[:connection_name]\n        sql_without_connection_name(event)\n      end\n\n      def debug_with_connection_name(msg)\n        conn = connection_name ? color(\"  [#{connection_name}]\", ActiveSupport::LogSubscriber::BLUE, true) : ''\n        debug_without_connection_name(conn + msg)\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails3/active_record/master_slave_routing.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module MasterSlaveRouting\n\n      module ClassMethods\n        SLAVE_METHODS = [ :find_by_sql, :count_by_sql ]\n        MASTER_METHODS = [ ] # I don't know any methods in AR::Base that change data directly w/o going to the relation object\n\n        SLAVE_METHODS.each do |slave_method|\n          class_eval <<-EOF, __FILE__, __LINE__ + 1\n            def #{slave_method}(*args, &block)\n              first_level_on_slave do\n                super(*args, &block)\n              end\n            end\n          EOF\n        end\n\n        MASTER_METHODS.each do |master_method|\n          class_eval <<-EOF, __FILE__, __LINE__ + 1\n            def #{master_method}(*args, &block)\n              on_master do\n                super(*args, &block)\n              end\n            end\n          EOF\n        end\n      end\n\n      module InstanceMethods\n        MASTER_METHODS = [ :reload ]\n\n        MASTER_METHODS.each do |master_method|\n          class_eval <<-EOF, __FILE__, __LINE__ + 1\n            def #{master_method}(*args, &block)\n              self.class.on_master do\n                super(*args, &block)\n              end\n            end\n          EOF\n        end\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails3/active_record/relation/connection_routing.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module Relation\n      module ConnectionRouting\n\n        # All the methods that could be querying the database\n        SLAVE_METHODS = [ :calculate, :exists? ]\n        MASTER_METHODS = [ :delete, :delete_all, :destroy, :destroy_all, :reload, :update, :update_all ]\n        ALL_METHODS = SLAVE_METHODS + MASTER_METHODS\n\n        DB_CHARMER_ATTRIBUTES = [ :db_charmer_connection, :db_charmer_connection_is_forced, :db_charmer_enable_slaves ]\n\n        # Define the default relation connection + override all the query methods here\n        def self.included(base)\n          init_attributes(base)\n          init_routing(base)\n        end\n\n        # Define our attributes + spawn methods shit needs to be changed to make sure our accessors are copied over to the new instances\n        def self.init_attributes(base)\n          DB_CHARMER_ATTRIBUTES.each do |attr|\n            base.send(:attr_accessor, attr)\n          end\n\n          # Override spawn methods\n          base.alias_method_chain :except, :db_charmer\n          base.alias_method_chain :only, :db_charmer\n        end\n\n        # Override all query methods\n        def self.init_routing(base)\n          ALL_METHODS.each do |meth|\n            base.alias_method_chain meth, :db_charmer\n          end\n\n          # Special case: for normal selects we go to the slave, but for selects with a lock we should use master\n          base.alias_method_chain :to_a, :db_charmer\n        end\n\n        # Copy db_charmer attributes in addition to what they're copying\n        def except_with_db_charmer(*args)\n          except_without_db_charmer(*args).tap do |result|\n            copy_db_charmer_options(self, result)\n          end\n        end\n\n        # Copy db_charmer attributes in addition to what they're copying\n        def only_with_db_charmer(*args)\n          only_without_db_charmer(*args).tap do |result|\n            copy_db_charmer_options(self, result)\n          end\n        end\n\n        # Copy our accessors from one instance to another\n        def copy_db_charmer_options(src, dst)\n          DB_CHARMER_ATTRIBUTES.each do |attr|\n            dst.send(\"#{attr}=\".to_sym, src.send(attr))\n          end\n        end\n\n        # Connection switching (changes the default relation connection)\n        def on_db(con, &block)\n          if block_given?\n            @klass.on_db(con, &block)\n          else\n            clone.tap do |result|\n              result.db_charmer_connection = con\n              result.db_charmer_connection_is_forced = true\n            end\n          end\n        end\n\n        # Make sure we get the right connection here\n        def connection\n          @klass.on_db(db_charmer_connection).connection\n        end\n\n        # Selects preferred destination (master/slave/default) for a query\n        def select_destination(method, recommendation = :default)\n          # If this relation was created within a forced connection block (e.g Model.on_db(:foo).relation)\n          # Then we should use that connection everywhere except cases when a model is slave-enabled\n          # in those cases DML queries go to the master\n          if db_charmer_connection_is_forced\n            return :master if db_charmer_enable_slaves && MASTER_METHODS.member?(method)\n            return :default\n          end\n\n          # If this relation is created from a slave-enabled model, let's do the routing if possible\n          if db_charmer_enable_slaves\n            return :slave if SLAVE_METHODS.member?(method)\n            return :master if MASTER_METHODS.member?(method)\n          else\n            # Make sure we do not use recommended destination\n            recommendation = :default\n          end\n\n          # If nothing else came up, let's use the default or recommended connection\n          return recommendation\n        end\n\n        # Switch the model to default relation connection\n        def switch_connection_for_method(method, recommendation = nil)\n          # Choose where to send the query\n          destination ||= select_destination(method, recommendation)\n\n          # What method to use\n          on_db_method = [ :on_db, db_charmer_connection ]\n          on_db_method = :on_master if destination == :master\n          on_db_method = :first_level_on_slave if destination == :slave\n\n          # Perform the query\n          @klass.send(*on_db_method) do\n            yield\n          end\n        end\n\n        # For normal selects we go to the slave, but for selects with a lock we should use master\n        def to_a_with_db_charmer(*args, &block)\n          preferred_destination = :slave\n          preferred_destination = :master if lock_value\n\n          switch_connection_for_method(:to_a, preferred_destination) do\n            to_a_without_db_charmer(*args, &block)\n          end\n        end\n\n        # Need this to mimick alias_method_chain name generation (exists? => exists_with_db_charmer?)\n        def self.aliased_method_name(target, with)\n          aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1\n          \"#{aliased_target}_#{with}_db_charmer#{punctuation}\"\n        end\n\n        # Override all the query methods here\n        ALL_METHODS.each do |method|\n          class_eval <<-EOF, __FILE__, __LINE__ + 1\n            def #{aliased_method_name method, :with}(*args, &block)\n              switch_connection_for_method(:#{method.to_s}) do\n                #{aliased_method_name method, :without}(*args, &block)\n              end\n            end\n          EOF\n        end\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails3/active_record/relation_method.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module RelationMethod\n\n      def self.extended(base)\n        class << base\n          alias_method_chain :relation, :db_charmer\n          alias_method_chain :arel_engine, :db_charmer\n        end\n      end\n\n      # Create a relation object and initialize its default connection\n      def relation_with_db_charmer(*args, &block)\n        relation_without_db_charmer(*args, &block).tap do |rel|\n          rel.db_charmer_connection = self.connection\n          rel.db_charmer_enable_slaves = self.db_charmer_slaves.any?\n          rel.db_charmer_connection_is_forced = !db_charmer_top_level_connection?\n        end\n      end\n\n      # Use the model itself an engine for Arel, do not fall back to AR::Base\n      def arel_engine_with_db_charmer(*)\n        self\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails31/active_record/migration/command_recorder.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module Migration\n      module CommandRecorder\n        def invert_on_db(args)\n          [:replay_commands_on_db, [args.first, args[1].inverse]]\n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/db_charmer/rails31/active_record/preloader/association.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module Preloader\n      module Association\n        extend ActiveSupport::Concern\n        included do\n          alias_method_chain :build_scope, :db_magic\n        end\n\n        def build_scope_with_db_magic\n          if model.db_charmer_top_level_connection? || reflection.options[:polymorphic] ||\n              model.db_charmer_default_connection != klass.db_charmer_default_connection\n            build_scope_without_db_magic\n          else\n            build_scope_without_db_magic.on_db(model)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/rails31/active_record/preloader/has_and_belongs_to_many.rb",
    "content": "module DbCharmer\n  module ActiveRecord\n    module Preloader\n      module HasAndBelongsToMany\n        extend ActiveSupport::Concern\n        included do\n          alias_method_chain :records_for, :db_magic\n        end\n\n        def records_for_with_db_magic(ids)\n          if model.db_charmer_top_level_connection? || reflection.options[:polymorphic] ||\n              model.db_charmer_default_connection != klass.db_charmer_default_connection\n            records_for_without_db_magic(ids)\n          else\n            klass.on_db(model) do\n              records_for_without_db_magic(ids)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/railtie.rb",
    "content": "module DbCharmer\n  class Railtie < Rails::Railtie\n\n    rake_tasks do\n      load \"db_charmer/tasks/databases.rake\"\n    end\n\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/sharding/connection.rb",
    "content": "module DbCharmer\n  module Sharding\n    class Connection\n      attr_accessor :config, :sharder\n\n      def initialize(config)\n        @config = config\n        @sharder = self.instantiate_sharder\n      end\n\n      def instantiate_sharder\n        raise ArgumentError, \"No :method passed!\" unless config[:method]\n        sharder_class_name = \"DbCharmer::Sharding::Method::#{config[:method].to_s.classify}\"\n        sharder_class = sharder_class_name.constantize\n        sharder_class.new(config)\n      end\n\n      def shard_connections\n        sharder.respond_to?(:shard_connections) ? sharder.shard_connections : nil\n      end\n\n      def support_default_shard?\n        sharder.respond_to?(:support_default_shard?) && sharder.support_default_shard?\n      end\n\n      def default_connection\n        @default_connection ||= DbCharmer::Sharding::StubConnection.new(self)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/sharding/method/db_block_group_map.rb",
    "content": "# This is a more sophisticated sharding method based on a two layer database-backed\n# blocks map that holds block-shard associations. Record blocks are mapped to tablegroups\n# and groups are mapped to shards.\n#\n# It automatically creates new blocks for new keys and assigns them to existing groups.\n# Warning: make sure to create at least one shard and one group before inserting any records.\n#\nmodule DbCharmer\n  module Sharding\n    module Method\n      class DbBlockGroupMap\n        # Shard connection info model\n        class Shard < ::ActiveRecord::Base\n          validates_presence_of :db_host\n          validates_presence_of :db_port\n          validates_presence_of :db_user\n          validates_presence_of :db_pass\n          validates_presence_of :db_name_prefix\n\n          has_many :groups, :class_name => 'DbCharmer::Sharding::Method::DbBlockGroupMap::Group'\n        end\n\n        # Table group info model\n        class Group < ::ActiveRecord::Base\n          validates_presence_of :shard_id\n          belongs_to :shard, :class_name => 'DbCharmer::Sharding::Method::DbBlockGroupMap::Shard'\n        end\n\n        #---------------------------------------------------------------------------------------------------------------\n        # Sharder name\n        attr_accessor :name\n\n        # Mapping db connection\n        attr_accessor :connection, :connection_name\n\n        # Mapping table name\n        attr_accessor :map_table\n\n        # Tablegroups table name\n        attr_accessor :groups_table\n\n        # Shards table name\n        attr_accessor :shards_table\n\n        # Sharding keys block size\n        attr_accessor :block_size\n\n        def initialize(config)\n          @name = config[:name] or raise(ArgumentError, \"Missing required :name parameter!\")\n          @connection = DbCharmer::ConnectionFactory.connect(config[:connection], true)\n          @block_size = (config[:block_size] || 10000).to_i\n\n          @map_table = config[:map_table] or raise(ArgumentError, \"Missing required :map_table parameter!\")\n          @groups_table = config[:groups_table] or raise(ArgumentError, \"Missing required :groups_table parameter!\")\n          @shards_table = config[:shards_table] or raise(ArgumentError, \"Missing required :shards_table parameter!\")\n\n          # Local caches\n          @shard_info_cache = {}\n          @group_info_cache = {}\n\n          @blocks_cache = Rails.cache\n          @blocks_cache_prefix = config[:blocks_cache_prefix] || \"#{@name}_block:\"\n        end\n\n        #---------------------------------------------------------------------------------------------------------------\n        def shard_for_key(key)\n          block = block_for_key(key)\n\n          # Auto-allocate new blocks\n          block ||= allocate_new_block_for_key(key)\n          raise ArgumentError, \"Invalid key value, no shards found for this key and could not create a new block!\" unless block\n\n          # Load shard\n          group_id = block['group_id'].to_i\n          shard_info = shard_info_by_group_id(group_id)\n\n          # Get config\n          shard_connection_config(shard_info, group_id)\n        end\n\n        #---------------------------------------------------------------------------------------------------------------\n        # Returns a block for a key\n        def block_for_key(key, cache = true)\n          # Cleanup the cache if asked to\n          key_range = [ block_start_for_key(key), block_end_for_key(key) ]\n          block_cache_key = \"%d-%d\" % key_range\n\n          if cache\n            cached_block = get_cached_block(block_cache_key)\n            return cached_block if cached_block\n          end\n\n          # Fetch cached value or load from db\n          block = begin\n            sql = \"SELECT * FROM #{map_table} WHERE start_id = #{key_range.first} AND end_id = #{key_range.last} LIMIT 1\"\n            connection.select_one(sql, 'Find a shard block')\n          end\n\n          set_cached_block(block_cache_key, block)\n\n          return block\n        end\n\n        #---------------------------------------------------------------------------------------------------------------\n        def get_cached_block(block_cache_key)\n          @blocks_cache.read(\"#{@blocks_cache_prefix}#{block_cache_key}\")\n        end\n\n        def set_cached_block(block_cache_key, block)\n          @blocks_cache.write(\"#{@blocks_cache_prefix}#{block_cache_key}\", block)\n        end\n\n        #---------------------------------------------------------------------------------------------------------------\n        # Load group info\n        def group_info_by_id(group_id, cache = true)\n          # Cleanup the cache if asked to\n          @group_info_cache[group_id] = nil unless cache\n\n          # Either load from cache or from db\n          @group_info_cache[group_id] ||= begin\n            prepare_shard_models\n            Group.find_by_id(group_id)\n          end\n        end\n\n        # Load shard info\n        def shard_info_by_id(shard_id, cache = true)\n          # Cleanup the cache if asked to\n          @shard_info_cache[shard_id] = nil unless cache\n\n          # Either load from cache or from db\n          @shard_info_cache[shard_id] ||= begin\n            prepare_shard_models\n            Shard.find_by_id(shard_id)\n          end\n        end\n\n        # Load shard info using mapping info for a group\n        def shard_info_by_group_id(group_id)\n          # Load group\n          group_info = group_info_by_id(group_id)\n          raise ArgumentError, \"Invalid group_id: #{group_id}\" unless group_info\n\n          shard_info = shard_info_by_id(group_info.shard_id)\n          raise ArgumentError, \"Invalid shard_id: #{group_info.shard_id}\" unless shard_info\n\n          return shard_info\n        end\n\n        #---------------------------------------------------------------------------------------------------------------\n        def allocate_new_block_for_key(key)\n          # Can't find any groups to use for blocks allocation!\n          return nil unless group = least_loaded_group\n\n          # Figure out block limits\n          start_id = block_start_for_key(key)\n          end_id = block_end_for_key(key)\n\n          # Try to insert a new mapping (ignore duplicate key errors)\n          sql = <<-SQL\n            INSERT IGNORE INTO #{map_table}\n                           SET start_id = #{start_id},\n                               end_id = #{end_id},\n                               group_id = #{group.id},\n                               block_size = #{block_size},\n                               created_at = NOW(),\n                               updated_at = NOW()\n          SQL\n          connection.execute(sql, \"Allocate new block\")\n\n          # Increment the blocks counter on the shard\n          Group.update_counters(group.id, :blocks_count => +1)\n\n          # Retry block search after creation\n          block_for_key(key)\n        end\n\n        def least_loaded_group\n          prepare_shard_models\n\n          # Select group\n          group = Group.first(:conditions => { :enabled => true, :open => true }, :order => 'blocks_count ASC')\n          raise \"Can't find any tablegroups to use for blocks allocation!\" unless group\n          return group\n        end\n\n        #---------------------------------------------------------------------------------------------------------------\n        def block_start_for_key(key)\n          block_size.to_i * (key.to_i / block_size.to_i)\n        end\n\n        def block_end_for_key(key)\n          block_size.to_i + block_start_for_key(key)\n        end\n\n        #---------------------------------------------------------------------------------------------------------------\n        # Create configuration (use mapping connection as a template)\n        def shard_connection_config(shard, group_id)\n          # Format connection name\n          shard_name = \"db_charmer_db_block_group_map_#{name}_s%d_g%d\" % [ shard.id, group_id]\n\n          # Here we get the mapping connection's configuration\n          # They do not expose configs so we hack in and get the instance var\n          # FIXME: Find a better way, maybe move config method to our ar extenstions\n          connection.instance_variable_get(:@config).clone.merge(\n            # Name for the connection factory\n            :connection_name => shard_name,\n            # Connection params\n            :host => shard.db_host,\n            :port => shard.db_port,\n            :username => shard.db_user,\n            :password => shard.db_pass,\n            :database => group_database_name(shard, group_id)\n          )\n        end\n\n        def group_database_name(shard, group_id)\n          \"%s_%05d\" % [ shard.db_name_prefix, group_id ]\n        end\n\n        #---------------------------------------------------------------------------------------------------------------\n        def create_shard(params)\n          params = params.symbolize_keys\n          [ :db_host, :db_port, :db_user, :db_pass, :db_name_prefix ].each do |arg|\n            raise ArgumentError, \"Missing required parameter: #{arg}\" unless params[arg]\n          end\n\n          # Prepare model\n          prepare_shard_models\n\n          # Create the record\n          Shard.create! do |shard|\n            shard.db_host = params[:db_host]\n            shard.db_port = params[:db_port]\n            shard.db_user = params[:db_user]\n            shard.db_pass = params[:db_pass]\n            shard.db_name_prefix = params[:db_name_prefix]\n          end\n        end\n\n        def shard_connections\n          # Find all groups\n          prepare_shard_models\n          groups = Group.all(:conditions => { :enabled => true }, :include => :shard)\n          # Map them to shards\n          groups.map { |group| shard_connection_config(group.shard, group.id) }\n        end\n\n        # Prepare model for working with our shards table\n        def prepare_shard_models\n          Shard.set_table_name(shards_table)\n          Shard.switch_connection_to(connection)\n\n          Group.set_table_name(groups_table)\n          Group.switch_connection_to(connection)\n        end\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/sharding/method/db_block_map.rb",
    "content": "# This is a more sophisticated sharding method based on a database-backed\n# blocks map that holds block-shard associations. It automatically\n# creates new blocks for new keys and assigns them to shards.\n#\nmodule DbCharmer\n  module Sharding\n    module Method\n      class DbBlockMap\n        # Sharder name\n        attr_accessor :name\n\n        # Mapping db connection\n        attr_accessor :connection, :connection_name\n\n        # Mapping table name\n        attr_accessor :map_table\n\n        # Shards table name\n        attr_accessor :shards_table\n\n        # Sharding keys block size\n        attr_accessor :block_size\n\n        def initialize(config)\n          @name = config[:name] or raise(ArgumentError, \"Missing required :name parameter!\")\n          @connection = DbCharmer::ConnectionFactory.connect(config[:connection], true)\n          @block_size = (config[:block_size] || 10000).to_i\n\n          @map_table = config[:map_table] or raise(ArgumentError, \"Missing required :map_table parameter!\")\n          @shards_table = config[:shards_table] or raise(ArgumentError, \"Missing required :shards_table parameter!\")\n\n          # Local caches\n          @shard_info_cache = {}\n\n          @blocks_cache = Rails.cache\n          @blocks_cache_prefix = config[:blocks_cache_prefix] || \"#{@name}_block:\"\n        end\n\n        def shard_for_key(key)\n          block = block_for_key(key)\n\n          begin\n            # Auto-allocate new blocks\n            block ||= allocate_new_block_for_key(key)\n          rescue ::ActiveRecord::StatementInvalid => e\n            raise unless e.message.include?('Duplicate entry')\n            block = block_for_key(key)\n          end\n\n          raise ArgumentError, \"Invalid key value, no shards found for this key and could not create a new block!\" unless block\n\n          # Bail if no shard found\n          shard_id = block['shard_id'].to_i\n          shard_info = shard_info_by_id(shard_id)\n          raise ArgumentError, \"Invalid shard_id: #{shard_id}\" unless shard_info\n\n          # Get config\n          shard_connection_config(shard_info)\n        end\n\n        class ShardInfo < ::ActiveRecord::Base\n          validates_presence_of :db_host\n          validates_presence_of :db_port\n          validates_presence_of :db_user\n          validates_presence_of :db_pass\n          validates_presence_of :db_name\n        end\n\n        # Returns a block for a key\n        def block_for_key(key, cache = true)\n          # Cleanup the cache if asked to\n          key_range = [ block_start_for_key(key), block_end_for_key(key) ]\n          block_cache_key = \"%d-%d\" % key_range\n\n          if cache\n            cached_block = get_cached_block(block_cache_key)\n            return cached_block if cached_block\n          end\n\n          # Fetch cached value or load from db\n          block = begin\n            sql = \"SELECT * FROM #{map_table} WHERE start_id = #{key_range.first} AND end_id = #{key_range.last} LIMIT 1\"\n            connection.select_one(sql, 'Find a shard block')\n          end\n\n          set_cached_block(block_cache_key, block)\n\n          return block\n        end\n\n        def get_cached_block(block_cache_key)\n          @blocks_cache.read(\"#{@blocks_cache_prefix}#{block_cache_key}\")\n        end\n\n        def set_cached_block(block_cache_key, block)\n          @blocks_cache.write(\"#{@blocks_cache_prefix}#{block_cache_key}\", block)\n        end\n\n        # Load shard info\n        def shard_info_by_id(shard_id, cache = true)\n          # Cleanup the cache if asked to\n          @shard_info_cache[shard_id] = nil unless cache\n\n          # Either load from cache or from db\n          @shard_info_cache[shard_id] ||= begin\n            prepare_shard_model\n            ShardInfo.find_by_id(shard_id)\n          end\n        end\n\n        def allocate_new_block_for_key(key)\n          # Can't find any shards to use for blocks allocation!\n          return nil unless shard = least_loaded_shard\n\n          # Figure out block limits\n          start_id = block_start_for_key(key)\n          end_id = block_end_for_key(key)\n\n          # Try to insert a new mapping (ignore duplicate key errors)\n          sql = <<-SQL\n            INSERT INTO #{map_table}\n                   SET start_id = #{start_id},\n                       end_id = #{end_id},\n                       shard_id = #{shard.id},\n                       block_size = #{block_size},\n                       created_at = NOW(),\n                       updated_at = NOW()\n          SQL\n          connection.execute(sql, \"Allocate new block\")\n\n          # Increment the blocks counter on the shard\n          ShardInfo.update_counters(shard.id, :blocks_count => +1)\n\n          # Retry block search after creation\n          block_for_key(key)\n        end\n\n        def least_loaded_shard\n          prepare_shard_model\n\n          # Select shard\n          shard = ShardInfo.all(:conditions => { :enabled => true, :open => true }, :order => 'blocks_count ASC', :limit => 1).first\n          raise \"Can't find any shards to use for blocks allocation!\" unless shard\n          return shard\n        end\n\n        def block_start_for_key(key)\n          block_size.to_i * (key.to_i / block_size.to_i)\n        end\n\n        def block_end_for_key(key)\n          block_size.to_i + block_start_for_key(key)\n        end\n\n        # Create configuration (use mapping connection as a template)\n        def shard_connection_config(shard)\n          # Format connection name\n          shard_name = \"db_charmer_db_block_map_#{name}_shard_%05d\" % shard.id\n\n          # Here we get the mapping connection's configuration\n          # They do not expose configs so we hack in and get the instance var\n          # FIXME: Find a better way, maybe move config method to our ar extenstions\n          connection.instance_variable_get(:@config).clone.merge(\n            # Name for the connection factory\n            :connection_name => shard_name,\n            # Connection params\n            :host => shard.db_host,\n            :port => shard.db_port,\n            :username => shard.db_user,\n            :password => shard.db_pass,\n            :database => shard.db_name\n          )\n        end\n\n        def create_shard(params)\n          params = params.symbolize_keys\n          [ :db_host, :db_port, :db_user, :db_pass, :db_name ].each do |arg|\n            raise ArgumentError, \"Missing required parameter: #{arg}\" unless params[arg]\n          end\n\n          # Prepare model\n          prepare_shard_model\n\n          # Create the record\n          ShardInfo.create! do |shard|\n            shard.db_host = params[:db_host]\n            shard.db_port = params[:db_port]\n            shard.db_user = params[:db_user]\n            shard.db_pass = params[:db_pass]\n            shard.db_name = params[:db_name]\n          end\n        end\n\n        def shard_connections\n          # Find all shards\n          prepare_shard_model\n          shards = ShardInfo.all(:conditions => { :enabled => true })\n          # Map them to connections\n          shards.map { |shard| shard_connection_config(shard) }\n        end\n\n        # Prepare model for working with our shards table\n        def prepare_shard_model\n          ShardInfo.table_name = shards_table\n          ShardInfo.switch_connection_to(connection)\n        end\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/sharding/method/hash_map.rb",
    "content": "module DbCharmer\n  module Sharding\n    module Method\n      class HashMap\n        attr_accessor :map\n\n        def initialize(config)\n          @map = config[:map].clone or raise ArgumentError, \"No :map defined!\"\n        end\n\n        def shard_for_key(key)\n          res = map[key] || map[:default]\n          raise ArgumentError, \"Invalid key value, no shards found for this key!\" unless res\n          return res\n        end\n\n        def support_default_shard?\n          map.has_key?(:default)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/sharding/method/range.rb",
    "content": "module DbCharmer\n  module Sharding\n    module Method\n      class Range\n        attr_accessor :ranges\n\n        def initialize(config)\n          @ranges = config[:ranges] ? config[:ranges].clone : raise(ArgumentError, \"No :ranges defined!\")\n        end\n\n        def shard_for_key(key)\n          return ranges[:default] if key == :default\n\n          ranges.each do |range, shard|\n            next if range == :default\n            return shard if range.member?(key.to_i)\n          end\n\n          return ranges[:default] if ranges[:default]\n          raise ArgumentError, \"Invalid key value, no shards found for this key!\"\n        end\n\n        def support_default_shard?\n          ranges.has_key?(:default)\n        end\n\n        def shard_connections\n          ranges.values.uniq\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/sharding/method.rb",
    "content": "module DbCharmer\n  module Sharding\n    module Method\n      autoload :Range, 'db_charmer/sharding/method/range'\n      autoload :HashMap, 'db_charmer/sharding/method/hash_map'\n      autoload :DbBlockMap, 'db_charmer/sharding/method/db_block_map'\n      autoload :DbBlockGroupMap, 'db_charmer/sharding/method/db_block_group_map'\n    end\n  end\nend"
  },
  {
    "path": "lib/db_charmer/sharding/stub_connection.rb",
    "content": "# This is a simple proxy class used as a default connection on sharded models\n#\n# The idea is to proxy all utility method calls to a real connection (set by\n# the +set_real_connection+ method when we switch shards) and fail on real\n# database querying calls forcing users to switch shard connections.\n#\nmodule DbCharmer\n  module Sharding\n    class StubConnection\n      attr_accessor :sharded_connection\n\n      def initialize(sharded_connection)\n        @sharded_connection = sharded_connection\n        @real_conn = nil\n      end\n\n      def set_real_connection(real_conn)\n        @real_conn = real_conn\n      end\n\n      def db_charmer_connection_name\n        \"StubConnection\"\n      end\n\n      def real_connection\n        # Return memoized real connection\n        return @real_conn if @real_conn\n\n        # If sharded connection supports shards enumeration, get the first shard\n        conn = sharded_connection.shard_connections.try(:first)\n\n        # If we do not have real connection yet, try to use the default one (if it is supported by the sharder)\n        conn ||= sharded_connection.sharder.shard_for_key(:default) if sharded_connection.support_default_shard?\n\n        # Get connection proxy for our real connection\n        return nil unless conn\n        @real_conn = ::ActiveRecord::Base.coerce_to_connection_proxy(conn, DbCharmer.connections_should_exist?)\n      end\n\n      def respond_to?(method_name, include_all = false)\n        return true if super\n        return false if real_connection.object_id == self.object_id\n        real_connection.respond_to?(method_name, include_all)\n      end\n\n      def method_missing(meth, *args, &block)\n        # Fail on database statements\n        if ::ActiveRecord::ConnectionAdapters::DatabaseStatements.instance_methods.member?(meth.to_s)\n          raise ::ActiveRecord::ConnectionNotEstablished, \"You have to switch connection on your model before using it!\"\n        end\n\n        # Fail if no connection has been established yet\n        unless real_connection\n          raise ::ActiveRecord::ConnectionNotEstablished, \"No real connection to proxy this method to!\"\n        end\n\n        if real_connection.kind_of?(DbCharmer::Sharding::StubConnection)\n          raise ::ActiveRecord::ConnectionNotEstablished, \"You have to switch connection on your model before using it!\"\n        end\n\n        # Proxy the call to our real connection target\n        real_connection.__send__(meth, *args, &block)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/sharding.rb",
    "content": "module DbCharmer\n  module Sharding\n    autoload :Connection, 'db_charmer/sharding/connection'\n    autoload :StubConnection, 'db_charmer/sharding/stub_connection'\n    autoload :Method, 'db_charmer/sharding/method'\n\n    @@sharded_connections = {}\n\n    def self.register_connection(config)\n      name = config[:name] or raise ArgumentError, \"No :name in connection!\"\n      @@sharded_connections[name] = DbCharmer::Sharding::Connection.new(config)\n    end\n\n    def self.sharded_connection(name)\n      @@sharded_connections[name] or raise ArgumentError, \"Invalid sharded connection name!\"\n    end\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/tasks/databases.rake",
    "content": "namespace :db_charmer do\n  namespace :create do\n    desc 'Create all the local databases defined in config/database.yml'\n    task :all => \"db:load_config\" do\n      ::ActiveRecord::Base.configurations.each_value do |config|\n        # Skip entries that don't have a database key, such as the first entry here:\n        #\n        #  defaults: &defaults\n        #    adapter: mysql\n        #    username: root\n        #    password:\n        #    host: localhost\n        #\n        #  development:\n        #    database: blog_development\n        #    <<: *defaults\n        next unless config['database']\n        # Only connect to local databases\n        local_database?(config) { create_core_and_sub_database(config) }\n      end\n    end\n  end\n\n  desc 'Create the databases defined in config/database.yml for the current RAILS_ENV'\n  task :create => \"db:load_config\" do\n    create_core_and_sub_database(ActiveRecord::Base.configurations[RAILS_ENV])\n  end\n\n  def create_core_and_sub_database(config)\n    create_database(config)\n    config.each_value do | sub_config |\n      next unless sub_config.is_a?(Hash)\n      next unless sub_config['database']\n      create_database(sub_config)\n    end\n  end\n\n  namespace :drop do\n    desc 'Drops all the local databases defined in config/database.yml'\n    task :all => \"db:load_config\" do\n      ::ActiveRecord::Base.configurations.each_value do |config|\n        # Skip entries that don't have a database key\n        next unless config['database']\n        # Only connect to local databases\n        local_database?(config) { drop_core_and_sub_database(config) }\n      end\n    end\n  end\n\n  desc 'Drops the database for the current RAILS_ENV'\n  task :drop => \"db:load_config\" do\n    config = ::ActiveRecord::Base.configurations[RAILS_ENV || 'development']\n    begin\n      drop_core_and_sub_database(config)\n    rescue Exception => e\n      puts \"Couldn't drop #{config['database']} : #{e.inspect}\"\n    end\n  end\n\n\n  def local_database?(config, &block)\n    if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank?\n      yield\n    else\n      puts \"This task only modifies local databases. #{config['database']} is on a remote host.\"\n    end\n  end\nend\n\ndef drop_core_and_sub_database(config)\n  begin\n    drop_database(config)\n  rescue\n    $stderr.puts \"#{config['database']} not exists\"\n  end  \n  config.each_value do | sub_config |\n    next unless sub_config.is_a?(Hash)\n    next unless sub_config['database']\n    begin\n      drop_database(sub_config)\n    rescue\n      $stderr.puts \"#{config['database']} not exists\"\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/db_charmer/version.rb",
    "content": "module DbCharmer\n  module Version\n    MAJOR = 1\n    MINOR = 9\n    PATCH = 1\n    BUILD = nil\n\n    STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer/with_remapped_databases.rb",
    "content": "module DbCharmer\n  def self.with_remapped_databases(mappings, &proc)\n    old_mappings = ::ActiveRecord::Base.db_charmer_database_remappings\n    begin\n      ::ActiveRecord::Base.db_charmer_database_remappings = mappings\n      if mappings[:master] || mappings['master']\n        with_all_hijacked(&proc)\n      else\n        proc.call\n      end\n    ensure\n      ::ActiveRecord::Base.db_charmer_database_remappings = old_mappings\n    end\n  end\n\n  def self.hijack_new_classes?\n    !! Thread.current[:db_charmer_hijack_new_classes]\n  end\n\nprivate\n\n  def self.with_all_hijacked\n    old_hijack_new_classes = Thread.current[:db_charmer_hijack_new_classes]\n    begin\n      Thread.current[:db_charmer_hijack_new_classes] = true\n      subclasses_method = DbCharmer.rails3? ? :descendants : :subclasses\n      ::ActiveRecord::Base.send(subclasses_method).each do |subclass|\n        subclass.hijack_connection!\n      end\n      yield\n    ensure\n      Thread.current[:db_charmer_hijack_new_classes] = old_hijack_new_classes\n    end\n  end\nend\n\n#---------------------------------------------------------------------------------------------------\n# Hijack connection on all new AR classes when we're in a block with main AR connection remapped\nclass ActiveRecord::Base\n  class << self\n    def inherited_with_hijacking(subclass)\n      out = inherited_without_hijacking(subclass)\n      hijack_connection! if DbCharmer.hijack_new_classes?\n      out\n    end\n\n    alias_method_chain :inherited, :hijacking\n  end\nend\n"
  },
  {
    "path": "lib/db_charmer.rb",
    "content": "# 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' unless defined?(::ActiveRecord::VERSION::MAJOR)\nrequire 'active_support/core_ext'\n\n#---------------------------------------------------------------------------------------------------\nmodule DbCharmer\n  # Configure autoload\n  autoload :Sharding, 'db_charmer/sharding'\n  autoload :Version,  'db_charmer/version'\n  module ActionController\n    autoload :ForceSlaveReads, 'db_charmer/action_controller/force_slave_reads'\n  end\n\n  #-------------------------------------------------------------------------------------------------\n  # Used in all Rails3-specific places\n  def self.rails3?\n    ::ActiveRecord::VERSION::MAJOR > 2\n  end\n\n  # Used in all Rails3.1-specific places\n  def self.rails31?\n    rails3? && ::ActiveRecord::VERSION::MINOR >= 1\n  end\n\n  # Used in all Rails2-specific places\n  def self.rails2?\n    ::ActiveRecord::VERSION::MAJOR == 2\n  end\n\n  # Detect broken Rails version\n  def self.rails324?\n    ActiveRecord::VERSION::STRING == '3.2.4'\n  end\n\n  #-------------------------------------------------------------------------------------------------\n  # Returns true if we're running within a Rails project\n  def self.running_with_rails?\n    defined?(Rails) && Rails.respond_to?(:env)\n  end\n\n  # Returns current environment name based on Rails or Rack environment variables\n  def self.detect_environment\n    return Rails.env if running_with_rails?\n    ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'\n  end\n\n  # Try to detect current environment or use development by default\n  @@env = DbCharmer.detect_environment\n  mattr_accessor :env\n\n  #-------------------------------------------------------------------------------------------------\n  # Accessors\n  @@connections_should_exist = true\n  mattr_accessor :connections_should_exist\n\n  def self.connections_should_exist?\n    !! connections_should_exist\n  end\n\n  #-------------------------------------------------------------------------------------------------\n  def self.logger\n    return Rails.logger if running_with_rails?\n    @@logger ||= Logger.new(STDERR)\n  end\n\n  #-------------------------------------------------------------------------------------------------\n  # Extend ActionController to support forcing slave reads\n  def self.enable_controller_magic!\n    ::ActionController::Base.extend(DbCharmer::ActionController::ForceSlaveReads::ClassMethods)\n    ::ActionController::Base.send(:include, DbCharmer::ActionController::ForceSlaveReads::InstanceMethods)\n  end\nend\n\n#---------------------------------------------------------------------------------------------------\n# Print warning about the broken Rails 2.3.4\nputs \"WARNING: Rails 3.2.4 is not officially supported by DbCharmer. Please upgrade.\" if DbCharmer.rails324?\n\n#---------------------------------------------------------------------------------------------------\n# Add useful methods to global object\nrequire 'db_charmer/core_extensions'\n\nrequire 'db_charmer/connection_factory'\nrequire 'db_charmer/connection_proxy'\nrequire 'db_charmer/force_slave_reads'\nrequire 'db_charmer/with_remapped_databases'\n\nif DbCharmer.rails3?\n  require \"db_charmer/railtie\"\nend\n\n#---------------------------------------------------------------------------------------------------\n# Add our custom class-level attributes to AR models\nrequire 'db_charmer/active_record/class_attributes'\nrequire 'active_record'\nActiveRecord::Base.extend(DbCharmer::ActiveRecord::ClassAttributes)\n\n#---------------------------------------------------------------------------------------------------\n# Enable connections switching in AR\nrequire 'db_charmer/active_record/connection_switching'\nActiveRecord::Base.extend(DbCharmer::ActiveRecord::ConnectionSwitching)\n\n#---------------------------------------------------------------------------------------------------\n# Enable AR logging extensions\nif DbCharmer.rails3?\n  require 'db_charmer/rails3/abstract_adapter/connection_name'\n  require 'db_charmer/rails3/active_record/log_subscriber'\n  ActiveRecord::LogSubscriber.send(:include, DbCharmer::ActiveRecord::LogSubscriber)\n  ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, DbCharmer::AbstractAdapter::ConnectionName)\nelse\n  require 'db_charmer/rails2/abstract_adapter/log_formatting'\n  ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, DbCharmer::AbstractAdapter::LogFormatting)\nend\n\n#---------------------------------------------------------------------------------------------------\n# Enable connection proxy in AR\nrequire 'db_charmer/active_record/multi_db_proxy'\nActiveRecord::Base.extend(DbCharmer::ActiveRecord::MultiDbProxy::ClassMethods)\nActiveRecord::Base.extend(DbCharmer::ActiveRecord::MultiDbProxy::MasterSlaveClassMethods)\nActiveRecord::Base.send(:include, DbCharmer::ActiveRecord::MultiDbProxy::InstanceMethods)\n\n#---------------------------------------------------------------------------------------------------\n# Enable connection proxy for relations\nif DbCharmer.rails3?\n  require 'db_charmer/rails3/active_record/relation_method'\n  require 'db_charmer/rails3/active_record/relation/connection_routing'\n  ActiveRecord::Base.extend(DbCharmer::ActiveRecord::RelationMethod)\n  ActiveRecord::Relation.send(:include, DbCharmer::ActiveRecord::Relation::ConnectionRouting)\nend\n\n#---------------------------------------------------------------------------------------------------\n# Enable connection proxy for scopes (rails 2.x only)\nif DbCharmer.rails2?\n  require 'db_charmer/rails2/active_record/named_scope/scope_proxy'\n  ActiveRecord::NamedScope::Scope.send(:include, DbCharmer::ActiveRecord::NamedScope::ScopeProxy)\nend\n\n#---------------------------------------------------------------------------------------------------\n# Enable connection proxy for associations\n# WARNING: Inject methods to association class right here because they proxy +include+ calls\n#          somewhere else, which means we could not use +include+ method here\nassociation_proxy_class = DbCharmer.rails31? ? ActiveRecord::Associations::CollectionProxy :\n                                               ActiveRecord::Associations::AssociationProxy\nassociation_proxy_class.class_eval do\n  def proxy?\n    true\n  end\n\n  if DbCharmer.rails31?\n    def on_db(con, proxy_target = nil, &block)\n      proxy_target ||= self\n      @association.klass.on_db(con, proxy_target, &block)\n    end\n\n    def on_slave(con = nil, &block)\n      @association.klass.on_slave(con, self, &block)\n    end\n\n    def on_master(&block)\n      @association.klass.on_master(self, &block)\n    end\n  else\n    def on_db(con, proxy_target = nil, &block)\n      proxy_target ||= self\n      @reflection.klass.on_db(con, proxy_target, &block)\n    end\n\n    def on_slave(con = nil, &block)\n      @reflection.klass.on_slave(con, self, &block)\n    end\n\n    def on_master(&block)\n      @reflection.klass.on_master(self, &block)\n    end\n  end\nend\n\n#---------------------------------------------------------------------------------------------------\n# Enable multi-db migrations\nrequire 'db_charmer/active_record/migration/multi_db_migrations'\nActiveRecord::Migration.send(:include, DbCharmer::ActiveRecord::Migration::MultiDbMigrations)\n\nif DbCharmer.rails31?\n  require 'db_charmer/rails31/active_record/migration/command_recorder'\n  ActiveRecord::Migration::CommandRecorder.send(:include, DbCharmer::ActiveRecord::Migration::CommandRecorder)\nend\n\n#---------------------------------------------------------------------------------------------------\n# Enable the magic\nif DbCharmer.rails3?\n  require 'db_charmer/rails3/active_record/master_slave_routing'\nelse\n  require 'db_charmer/rails2/active_record/master_slave_routing'\nend\n\nrequire 'db_charmer/active_record/sharding'\nrequire 'db_charmer/active_record/db_magic'\nActiveRecord::Base.extend(DbCharmer::ActiveRecord::DbMagic)\n\n#---------------------------------------------------------------------------------------------------\n# Setup association preload magic\nif DbCharmer.rails31?\n  require 'db_charmer/rails31/active_record/preloader/association'\n  ActiveRecord::Associations::Preloader::Association.send(:include, DbCharmer::ActiveRecord::Preloader::Association)\n  require 'db_charmer/rails31/active_record/preloader/has_and_belongs_to_many'\n  ActiveRecord::Associations::Preloader::HasAndBelongsToMany.send(:include, DbCharmer::ActiveRecord::Preloader::HasAndBelongsToMany)\nelse\n  require 'db_charmer/active_record/association_preload'\n  ActiveRecord::Base.extend(DbCharmer::ActiveRecord::AssociationPreload)\n\n  # Open up really useful API method\n  ActiveRecord::AssociationPreload::ClassMethods.send(:public, :preload_associations)\nend\n"
  },
  {
    "path": "test-project/.gitignore",
    "content": "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",
    "content": "--colour\n--format documentation\n"
  },
  {
    "path": "test-project/Gemfile",
    "content": "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'\ngem 'rspec-rails', '< 3.0'\n\n# Load DbCharmer as a gem\nif ENV['DB_CHARMER_GEM'].to_s == ''\n  gem_path = File.expand_path(File.dirname(File.dirname(__FILE__)))\n  puts \"Using on-disk db-charmer code from '#{gem_path}'...\"\n  gem 'db-charmer', :path => gem_path, :require => 'db_charmer'\nelse\n  puts \"Using db-charmer gem: #{ENV['DB_CHARMER_GEM']}...\"\n  gem 'db-charmer', ENV['DB_CHARMER_GEM'], :require => 'db_charmer'\nend\n\n# Detect Rails version we need to use\nrails_version_file = File.expand_path(\"../.rails-version\", __FILE__)\nversion = File.exists?(rails_version_file) && File.read(rails_version_file).chomp\nversion ||= ENV['RAILS_VERSION']\nversion ||= '3-2-stable'\n\n# Require gems for selected rails version\ncase version\nwhen /master/\n  gem \"rails\", :git => \"git://github.com/rails/rails.git\"\n  gem \"arel\", :git => \"git://github.com/rails/arel.git\"\n  gem \"journey\", :git => \"git://github.com/rails/journey.git\"\nwhen /3-0-stable/\n  gem \"rails\", :git => \"git://github.com/rails/rails.git\", :branch => \"3-0-stable\"\n  gem \"arel\",  :git => \"git://github.com/rails/arel.git\", :branch => \"2-0-stable\"\nwhen /3-1-stable/\n  gem \"rails\", :git => \"git://github.com/rails/rails.git\", :branch => \"3-1-stable\"\nwhen /3-2-stable/\n  gem \"rails\", :git => \"git://github.com/rails/rails.git\", :branch => \"3-2-stable\"\nelse\n  gem \"rails\", version\nend\n"
  },
  {
    "path": "test-project/Rakefile",
    "content": "ENV['RAILS_ENV'] = 'test'\n\n# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.\n\nrequire File.expand_path('../config/application', __FILE__)\nrequire 'rake'\n\nDbCharmerSandbox::Application.load_tasks\n"
  },
  {
    "path": "test-project/TODO",
    "content": "Functionality:\n- Add a controller wrapper to force all queries to the master (thanks mascohism for the idea)\n\nDocs:\n- Document (make more obvious) multi-db migrations code with migration_connections_should_exist\n- Document the fact, that all queries in a transaction go to the master\n"
  },
  {
    "path": "test-project/app/controllers/application_controller.rb",
    "content": "class ApplicationController < ActionController::Base\n  protect_from_forgery\nend\n"
  },
  {
    "path": "test-project/app/controllers/posts_controller.rb",
    "content": "class PostsController < ApplicationController\n  force_slave_reads :only => [ :index, :show, :new ], :except => :new\n\n  # We'll use this to make sure count query would be sent to a proper server\n  before_filter do\n    Post.count\n  end\n\n  def index\n    @posts = Post.all\n  end\n\n  def show\n    @post = Post.find(params[:id])\n  end\n\n  def new\n    @post = Post.new\n  end\n\n  def create\n    post = Post.create!(params[:post])\n    redirect_to(post_url(post))\n  end\n\n  def destroy\n    Post.delete(params[:id])\n    redirect_to(:action => :index)\n  end\nend\n"
  },
  {
    "path": "test-project/app/helpers/application_helper.rb",
    "content": "module ApplicationHelper\nend\n"
  },
  {
    "path": "test-project/app/models/avatar.rb",
    "content": "class Avatar < ActiveRecord::Base\nend\n"
  },
  {
    "path": "test-project/app/models/car.rb",
    "content": "class Car < ActiveRecord::Base\n  db_magic :slave => :slave01\nend\n"
  },
  {
    "path": "test-project/app/models/categories_posts.rb",
    "content": "class CategoriesPosts < ActiveRecord::Base\n  belongs_to :category\n  belongs_to :post\nend\n"
  },
  {
    "path": "test-project/app/models/category.rb",
    "content": "class Category < ActiveRecord::Base\n  has_and_belongs_to_many :posts\nend\n"
  },
  {
    "path": "test-project/app/models/comment.rb",
    "content": "class Comment < ActiveRecord::Base\n  belongs_to :commentable, :polymorphic => true\nend\n"
  },
  {
    "path": "test-project/app/models/event.rb",
    "content": "class Event < ActiveRecord::Base\n  self.table_name = :timeline_events\n\n  db_magic :sharded => {\n    :key => :to_uid,\n    :sharded_connection => :social\n  }\nend\n"
  },
  {
    "path": "test-project/app/models/ford.rb",
    "content": "class Ford < Car\nend"
  },
  {
    "path": "test-project/app/models/house.rb",
    "content": "class House < ActiveRecord::Base\n  db_magic :slave => :slave01, :force_slave_reads => false\nend\n"
  },
  {
    "path": "test-project/app/models/log_record.rb",
    "content": "class LogRecord < ActiveRecord::Base\n  db_magic :connection => :logs\n  belongs_to :user\nend\n"
  },
  {
    "path": "test-project/app/models/post.rb",
    "content": "class Post < ActiveRecord::Base\n  DB_MAGIC_DEFAULT_PARAMS = { :slave => :slave01, :force_slave_reads => false }\n  db_magic DB_MAGIC_DEFAULT_PARAMS\n\n  belongs_to :user\n  has_and_belongs_to_many :categories\n\n  def self.define_scope(*args, &block)\n    if DbCharmer.rails3?\n      scope(*args, &block)\n    else\n      named_scope(*args, &block)\n    end\n  end\n\n  define_scope :windows_posts, :conditions => \"title like '%win%'\"\n  define_scope :dummy_scope, :conditions => '1'\nend\n"
  },
  {
    "path": "test-project/app/models/range_sharded_model.rb",
    "content": "class RangeShardedModel < ActiveRecord::Base\n  db_magic :sharded => {\n    :key => :id,\n    :sharded_connection => :texts\n  }\nend\n\n"
  },
  {
    "path": "test-project/app/models/toyota.rb",
    "content": "class Toyota < Car\nend"
  },
  {
    "path": "test-project/app/models/user.rb",
    "content": "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",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>DbCharmerSandbox</title>\n  <%= stylesheet_link_tag :all %>\n  <%= javascript_include_tag :defaults %>\n  <%= csrf_meta_tag %>\n</head>\n<body>\n\n<%= yield %>\n\n</body>\n</html>\n"
  },
  {
    "path": "test-project/app/views/posts/index.html.erb",
    "content": "<h1>Posts</h1>\n<br/>\n<% @posts.each do |post| %>\n  <p>\n    Post #<%= post.id %><br/>\n    <pre><%= post.inspect %></pre>\n  </p>\n<% end %>\n"
  },
  {
    "path": "test-project/app/views/posts/new.html.erb",
    "content": "<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",
    "content": "<h1>Posts#show</h1>\n<p>Find me in app/views/posts/show.html.erb</p>\n"
  },
  {
    "path": "test-project/config/application.rb",
    "content": "require File.expand_path('../boot', __FILE__)\n\nrequire 'rails/all'\n\n# If you have a Gemfile, require the gems listed there, including any gems\n# you've limited to :test, :development, or :production.\nBundler.require(:default, Rails.env) if defined?(Bundler)\n\nmodule DbCharmerSandbox\n  class Application < Rails::Application\n    # Settings in config/environments/* take precedence over those specified here.\n    # Application configuration should go into files in config/initializers\n    # -- all .rb files in that directory are automatically loaded.\n\n    # Custom directories with classes and modules you want to be autoloadable.\n    # config.autoload_paths += %W(#{config.root}/extras)\n\n    # Only load the plugins named here, in the order given (default is alphabetical).\n    # :all can be used as a placeholder for all plugins not explicitly named.\n    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]\n\n    # Activate observers that should always be running.\n    # config.active_record.observers = :cacher, :garbage_collector, :forum_observer\n\n    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.\n    # Run \"rake -D time\" for a list of tasks for finding time zone names. Default is UTC.\n    # config.time_zone = 'Central Time (US & Canada)'\n\n    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.\n    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]\n    # config.i18n.default_locale = :de\n\n    # JavaScript files you want as :defaults (application.js is always included).\n    # config.action_view.javascript_expansions[:defaults] = %w(jquery rails)\n\n    # Configure the default encoding used in templates for Ruby 1.9.\n    config.encoding = \"utf-8\"\n\n    # Configure sensitive parameters which will be filtered from the log file.\n    config.filter_parameters += [:password]\n  end\nend\n"
  },
  {
    "path": "test-project/config/boot.rb",
    "content": "require 'rubygems'\n\n# Set up gems listed in the Gemfile.\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)\n\nrequire 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])\n"
  },
  {
    "path": "test-project/config/database.yml.example",
    "content": "common: &common\n  adapter: mysql\n  encoding: utf8\n  reconnect: false\n  pool: 10\n  username: root\n  password:\n\n#----------------------------------------------------------------\ntest:\n  <<: *common\n  database: db_charmer_sandbox_test\n\n  # logs database\n  logs:\n    <<: *common\n    database: db_charmer_logs_test\n\n  # slave database\n  slave01:\n    <<: *common\n    username: db_charmer_ro\n    database: db_charmer_sandbox_test\n\n  user_master:\n    <<: *common\n    database: db_charmer_sandbox_test\n\n  # shard mapping db\n  social_shard_info:\n    <<: *common\n    database: db_charmer_sandbox_test\n\n  # for migrations only\n  social_shard01:\n    <<: *common\n    database: db_charmer_events_test_shard01\n\n  # for migrations only\n  social_shard02:\n    <<: *common\n    database: db_charmer_events_test_shard02\n\n#----------------------------------------------------------------\ntest22:\n  <<: *common\n  database: db_charmer_sandbox22_test\n\n  # logs database\n  logs:\n    <<: *common\n    database: db_charmer_logs22_test\n\n  # slave database\n  slave01:\n    <<: *common\n    username: db_charmer_ro\n    database: db_charmer_sandbox22_test\n\n  user_master:\n    <<: *common\n    database: db_charmer_sandbox22_test\n\n  # shard mapping db\n  social_shard_info:\n    <<: *common\n    database: db_charmer_sandbox22_test\n\n  # for migrations only\n  social_shard01:\n    <<: *common\n    database: db_charmer_events22_test_shard01\n\n  # for migrations only\n  social_shard02:\n    <<: *common\n    database: db_charmer_events22_test_shard02\n"
  },
  {
    "path": "test-project/config/environment.rb",
    "content": "# Load the rails application\nrequire File.expand_path('../application', __FILE__)\n\n# Initialize the rails application\nDbCharmerSandbox::Application.initialize!\n"
  },
  {
    "path": "test-project/config/environments/test.rb",
    "content": "DbCharmerSandbox::Application.configure do\n  # Settings specified here will take precedence over those in config/application.rb\n\n  # The test environment is used exclusively to run your application's\n  # test suite.  You never need to work with it otherwise.  Remember that\n  # your test database is \"scratch space\" for the test suite and is wiped\n  # and recreated between test runs.  Don't rely on the data there!\n  config.cache_classes = true\n\n  # Log error messages when you accidentally call methods on nil.\n  config.whiny_nils = true\n\n  # Show full error reports and disable caching\n  config.consider_all_requests_local       = true\n  config.action_controller.perform_caching = false\n\n  # Raise exceptions instead of rendering exception templates\n  config.action_dispatch.show_exceptions = false\n\n  # Disable request forgery protection in test environment\n  config.action_controller.allow_forgery_protection    = false\n\n  # Tell Action Mailer not to deliver emails to the real world.\n  # The :test delivery method accumulates sent emails in the\n  # ActionMailer::Base.deliveries array.\n  config.action_mailer.delivery_method = :test\n\n  # Use SQL instead of Active Record's schema dumper when creating the test database.\n  # This is necessary if your schema can't be completely dumped by the schema dumper,\n  # like if you have constraints or database-specific column types\n  # config.active_record.schema_format = :sql\n\n  # Print deprecation notices to the stderr\n  config.active_support.deprecation = :stderr\nend\n"
  },
  {
    "path": "test-project/config/initializers/backtrace_silencers.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.\n# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }\n\n# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.\n# Rails.backtrace_cleaner.remove_silencers!\n"
  },
  {
    "path": "test-project/config/initializers/db_charmer.rb",
    "content": "DbCharmer.connections_should_exist = false # Since we are not in production\nDbCharmer.enable_controller_magic!\n"
  },
  {
    "path": "test-project/config/initializers/secret_token.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Your secret key for verifying the integrity of signed cookies.\n# If you change this key, all old signed cookies will become invalid!\n# Make sure the secret is at least 30 characters and all random,\n# no regular words or you'll be exposed to dictionary attacks.\nDbCharmerSandbox::Application.config.secret_token = 'bf10223f7ec7f4b2f2c6f98545ee0d172d5fe052deeba6e416e34e0a7534bc2f5a9983f331b5a799ac6544bf99d906c2a5a3bee8260d4cb985f2c096527aa3ad'\n"
  },
  {
    "path": "test-project/config/initializers/session_store.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\nDbCharmerSandbox::Application.config.session_store :cookie_store, :key => '_db-charmer-sandbox_session'\n\n# Use the database for sessions instead of the cookie-based default,\n# which shouldn't be used to store highly confidential information\n# (create the session table with \"rails generate session_migration\")\n# DbCharmerSandbox::Application.config.session_store :active_record_store\n"
  },
  {
    "path": "test-project/config/initializers/sharding.rb",
    "content": "# Range-based shards for testing\n\nTEXTS_SHARDING_RANGES = {\n  0...100   => :shard1,\n  100..200  => :shard2,\n  :default  => :shard3\n}\n\nDbCharmer::Sharding.register_connection(\n  :name => :texts,\n  :method => :range,\n  :ranges => TEXTS_SHARDING_RANGES\n)\n\n#------------------------------------------------\n# Db blocks map sharding for testing\n\nSOCIAL_SHARDING = DbCharmer::Sharding.register_connection(\n  :name => :social,\n  :method => :db_block_map,\n  :block_size => 10,\n  :map_table => :event_shards_map,\n  :shards_table => :event_shards_info,\n  :connection => :social_shard_info\n)\n"
  },
  {
    "path": "test-project/config/locales/en.yml",
    "content": "# Sample localization file for English. Add more files in this directory for other locales.\n# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.\n\nen:\n  hello: \"Hello world\"\n"
  },
  {
    "path": "test-project/config/routes.rb",
    "content": "DbCharmerSandbox::Application.routes.draw do\n  # The priority is based upon order of creation:\n  # first created -> highest priority.\n\n  # Resource routes\n  resources :posts\n  resources :cars\n\n  # Sample of regular route:\n  #   match 'products/:id' => 'catalog#view'\n  # Keep in mind you can assign values other than :controller and :action\n\n  # Sample of named route:\n  #   match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase\n  # This route can be invoked with purchase_url(:id => product.id)\n\n  # Sample resource route (maps HTTP verbs to controller actions automatically):\n  #   resources :products\n\n  # Sample resource route with options:\n  #   resources :products do\n  #     member do\n  #       get 'short'\n  #       post 'toggle'\n  #     end\n  #\n  #     collection do\n  #       get 'sold'\n  #     end\n  #   end\n\n  # Sample resource route with sub-resources:\n  #   resources :products do\n  #     resources :comments, :sales\n  #     resource :seller\n  #   end\n\n  # Sample resource route with more complex sub-resources\n  #   resources :products do\n  #     resources :comments\n  #     resources :sales do\n  #       get 'recent', :on => :collection\n  #     end\n  #   end\n\n  # Sample resource route within a namespace:\n  #   namespace :admin do\n  #     # Directs /admin/products/* to Admin::ProductsController\n  #     # (app/controllers/admin/products_controller.rb)\n  #     resources :products\n  #   end\n\n  # You can have the root of your site routed with \"root\"\n  # just remember to delete public/index.html.\n  # root :to => \"welcome#index\"\n\n  # See how all your routes lay out with \"rake routes\"\n\n  # This is a legacy wild controller route that's not recommended for RESTful applications.\n  # Note: This route will make all actions in every controller accessible via GET requests.\n  match ':controller(/:action(/:id(.:format)))'\nend\n"
  },
  {
    "path": "test-project/db/create_databases.sql",
    "content": "drop database if exists db_charmer_sandbox_test;\ncreate database db_charmer_sandbox_test;\n\ndrop database if exists db_charmer_logs_test;\ncreate database db_charmer_logs_test;\n\ndrop database if exists db_charmer_events_test_shard01;\ncreate database db_charmer_events_test_shard01;\n\ndrop database if exists db_charmer_events_test_shard02;\ncreate database db_charmer_events_test_shard02;\n\ngrant all privileges on db_charmer_sandbox_test.* to 'db_charmer_ro'@'localhost';\n"
  },
  {
    "path": "test-project/db/migrate/20090810013829_create_log_records.rb",
    "content": "class CreateLogRecords < ActiveRecord::Migration\n  db_magic :connection => :logs\n\n  def self.up\n    create_table :log_records do |t|\n      t.integer :user_id\n      t.string :level\n      t.string :message\n      t.timestamps\n    end\n  end\n\n  def self.down\n    drop_table :log_records\n  end\nend\n"
  },
  {
    "path": "test-project/db/migrate/20090810013922_create_posts.rb",
    "content": "class CreatePosts < ActiveRecord::Migration\n  def self.up\n    create_table :posts do |t|\n      t.string :title\n      t.text :body\n      t.integer :user_id\n      t.timestamps\n    end\n  end\n\n  def self.down\n    drop_table :posts\n  end\nend\n"
  },
  {
    "path": "test-project/db/migrate/20090810221944_create_users.rb",
    "content": "class CreateUsers < ActiveRecord::Migration\n  def self.up\n    create_table :users do |t|\n      t.string :login\n      t.string :password\n      t.timestamps\n    end\n  end\n\n  def self.down\n    drop_table :users\n  end\nend\n"
  },
  {
    "path": "test-project/db/migrate/20100305234245_create_categories.rb",
    "content": "class CreateCategories < ActiveRecord::Migration\n  def self.up\n    create_table :categories do |t|\n      t.string :name\n\n      t.timestamps\n    end\n  end\n\n  def self.down\n    drop_table :categories\n  end\nend\n"
  },
  {
    "path": "test-project/db/migrate/20100305234340_create_categories_posts.rb",
    "content": "class CreateCategoriesPosts < ActiveRecord::Migration\n  def self.up\n    pk_in_join_table = !DbCharmer.rails3?\n    create_table :categories_posts, :id => pk_in_join_table do |t|\n      t.integer :post_id\n      t.integer :category_id\n    end\n  end\n\n  def self.down\n    drop_table :categories_posts\n  end\nend\n"
  },
  {
    "path": "test-project/db/migrate/20100305235831_create_avatars.rb",
    "content": "class CreateAvatars < ActiveRecord::Migration\n  def self.up\n    create_table :avatars do |t|\n      t.integer :user_id\n      t.string :name\n\n      t.timestamps\n    end\n  end\n\n  def self.down\n    drop_table :avatars\n  end\nend\n"
  },
  {
    "path": "test-project/db/migrate/20100328201317_create_sharding_map_tables.rb",
    "content": "class CreateShardingMapTables < ActiveRecord::Migration\n  db_magic :connection => :social_shard_info\n\n  def self.up\n    create_table :event_shards_info, :force => true do |t|\n      t.timestamps\n      t.string  :db_host, :null => false\n      t.integer :db_port, :null => false, :default => 3306\n      t.string  :db_user, :null => false, :default => 'root'\n      t.string  :db_pass, :null => false, :default => ''\n      t.string  :db_name, :null => false\n      t.boolean :open, :null => false, :default => false\n      t.boolean :enabled, :null => false, :default => false\n      t.integer :blocks_count, :null => false, :default => 0\n    end\n\n    add_index :event_shards_info, [:enabled, :open, :blocks_count], :name => \"alloc\"\n\n    create_table :event_shards_map, :id => false, :force => true do |t|\n      t.integer :start_id, :null => false\n      t.integer :end_id, :null => false\n      t.integer :shard_id, :null => false\n      t.integer :block_size, :null => false, :default => 0\n      t.timestamps\n    end\n\n    add_index :event_shards_map, [:start_id, :end_id], :unique => true\n    add_index :event_shards_map, :shard_id\n  end\n\n  def self.down\n    drop_table :event_shards_map\n    drop_table :event_shards_info\n  end\nend\n"
  },
  {
    "path": "test-project/db/migrate/20100330180517_create_event_tables.rb",
    "content": "class CreateEventTables < ActiveRecord::Migration\n  # In test environment just use database.yml-defined connections\n  if Rails.env.test?\n    db_magic :connections => [ :social_shard01, :social_shard02 ]\n  else\n    db_magic :sharded_connection => :social\n  end\n\n  def self.up\n    sql = <<-SQL\n      CREATE TABLE `timeline_events` (\n        `event_id` int(11) NOT NULL AUTO_INCREMENT,\n        `from_uid` int(11) NOT NULL,\n        `to_uid` int(11) NOT NULL,\n        `original_created_at` datetime NOT NULL,\n        `event_type` int(11) NOT NULL,\n        `event_data` text,\n        `replies_count` int(11) NOT NULL DEFAULT '0',\n        `parent_id` int(11) NOT NULL DEFAULT '0',\n        `touched_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n        `on_profile` int(1) NOT NULL DEFAULT '0',\n        PRIMARY KEY (`to_uid`,`parent_id`,`touched_at`,`event_id`),\n        UNIQUE KEY `event_id_and_to_uid_key` (`event_id`,`to_uid`),\n        KEY `on_profile_index` (`to_uid`,`on_profile`,`touched_at`)\n      ) ENGINE=InnoDB DEFAULT CHARSET=utf8\n    SQL\n    execute(sql)\n  end\n\n  def self.down\n    drop_table :timeline_events\n  end\nend\n"
  },
  {
    "path": "test-project/db/migrate/20100817191548_create_cars.rb",
    "content": "class CreateCars < ActiveRecord::Migration\n  def self.up\n    create_table :cars do |t|\n      t.string :type\n      t.string :license\n      t.timestamps\n    end\n  end\n\n  def self.down\n    drop_table :cars\n  end\nend\n"
  },
  {
    "path": "test-project/db/migrate/20111005193941_create_comments.rb",
    "content": "class CreateComments < ActiveRecord::Migration\n  def self.up\n    create_table :comments do |t|\n      t.string  :commentable_type, :null => false\n      t.integer :commentable_id,   :null => false\n      t.text    :body,             :null => false\n\n      t.timestamps\n    end\n  end\n\n  def self.down\n    drop_table :comments\n  end\nend\n"
  },
  {
    "path": "test-project/db/seeds.rb",
    "content": "# This file should contain all the record creation needed to seed the database with its default values.\n# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).\n#\n# Examples:\n#\n#   cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])\n#   Mayor.create(:name => 'Daley', :city => cities.first)\n"
  },
  {
    "path": "test-project/db/sharding.sql",
    "content": "-- MySQL dump 10.13  Distrib 5.1.44, for apple-darwin10.2.0 (i386)\n--\n-- Host: localhost    Database: db_charmer_sandbox_test\n-- ------------------------------------------------------\n-- Server version\t5.1.44\n\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n/*!40101 SET NAMES utf8 */;\n/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n/*!40103 SET TIME_ZONE='+00:00' */;\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n--\n-- Table structure for table `events_shard_info`\n--\n\nDROP TABLE IF EXISTS `events_shard_info`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `events_shard_info` (\n  `id` int(10) unsigned NOT NULL,\n  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  `db_host` varchar(255) NOT NULL,\n  `db_port` int(10) unsigned NOT NULL DEFAULT '3306',\n  `db_user` varchar(255) NOT NULL DEFAULT 'root',\n  `db_pass` varchar(255) NOT NULL DEFAULT '',\n  `open` tinyint(1) unsigned NOT NULL DEFAULT '0',\n  `enabled` tinyint(1) unsigned NOT NULL DEFAULT '0',\n  `blocks_count` int(10) unsigned NOT NULL DEFAULT '0',\n  PRIMARY KEY (`id`),\n  KEY `alloc` (`enabled`,`open`,`blocks_count`)\n) ENGINE=InnoDB DEFAULT CHARSET=latin1;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `events_shard_info`\n--\n\nLOCK TABLES `events_shard_info` WRITE;\n/*!40000 ALTER TABLE `events_shard_info` DISABLE KEYS */;\n/*!40000 ALTER TABLE `events_shard_info` ENABLE KEYS */;\nUNLOCK TABLES;\n\n--\n-- Table structure for table `events_shard_dict`\n--\n\nDROP TABLE IF EXISTS `events_shard_dict`;\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\n/*!40101 SET character_set_client = utf8 */;\nCREATE TABLE `events_shard_dict` (\n  `start_id` int(10) unsigned NOT NULL,\n  `end_id` int(10) unsigned NOT NULL,\n  `shard_id` int(10) unsigned NOT NULL,\n  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  `block_size` int(10) unsigned NOT NULL,\n  PRIMARY KEY (`start_id`,`end_id`),\n  KEY `shard_id` (`shard_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=latin1;\n/*!40101 SET character_set_client = @saved_cs_client */;\n\n--\n-- Dumping data for table `events_shard_dict`\n--\n\nLOCK TABLES `events_shard_dict` WRITE;\n/*!40000 ALTER TABLE `events_shard_dict` DISABLE KEYS */;\n/*!40000 ALTER TABLE `events_shard_dict` ENABLE KEYS */;\nUNLOCK TABLES;\n/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n-- Dump completed on 2010-03-22  1:37:30\n"
  },
  {
    "path": "test-project/spec/controllers/posts_controller_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe PostsController do\n  fixtures :posts\n\n  # Delete these examples and add some real ones\n  it \"should support db_charmer readonly actions method\" do\n    PostsController.respond_to?(:force_slave_reads).should be_true\n  end\n\n  it \"index action should force slave reads\" do\n    PostsController.force_slave_reads_action?(:index).should be_true\n  end\n\n  it \"create action should not force slave reads\" do\n    PostsController.force_slave_reads_action?(:create).should be_false\n  end\n\n  describe \"GET 'index'\" do\n    context \"slave reads enforcing (action is listed in :only)\" do\n      it \"should enable enforcing\" do\n        get 'index'\n        controller.force_slave_reads?.should be_true\n      end\n\n      it \"should actually force slave reads\" do\n        Post.connection.should_not_receive(:select_value) # no counts\n        Post.connection.should_not_receive(:select_all) # no finds\n        Post.on_slave.connection.should_receive(:select_value).and_return(1)\n        get 'index'\n      end\n    end\n  end\n\n  describe \"GET 'show'\" do\n    context \"slave reads enforcing (action is listed in :only)\" do\n      it \"should enable enforcing\" do\n        get 'show', :id => Post.first.id\n        controller.force_slave_reads?.should be_true\n      end\n\n      it \"should actually force slave reads\" do\n        post = Post.first\n        Post.connection.should_not_receive(:select_value) # no counts\n        Post.connection.should_not_receive(:select_all) # no finds\n        Post.on_slave.connection.should_receive(:select_value).and_return(1)\n        Post.on_slave.connection.should_receive(:select_all).and_return([post.attributes])\n        get 'show', :id => post.id\n      end\n    end\n  end\n\n  describe \"GET 'new'\" do\n    context \"slave reads enforcing (action is listed in :except)\" do\n      it \"should not enable enforcing\" do\n        get 'new'\n        controller.force_slave_reads?.should be_false\n      end\n\n      it \"should not do any actual enforcing\" do\n        Post.connection.should_receive(:select_value).and_return(0) # count\n        Post.on_slave.connection.should_not_receive(:select_value) # no counts\n        Post.on_slave.connection.should_not_receive(:select_all) # no selects\n        get 'new'\n      end\n    end\n  end\n\n  describe \"GET 'create'\" do\n    it \"should redirect to post url upon successful completion\" do\n      get 'create', :post => { :title => 'xxx', :user_id => 1 }\n      response.should redirect_to(post_url(Post.last))\n    end\n\n    it \"should create a Post record\" do\n      lambda {\n        get 'create', :post => { :title => 'xxx', :user_id => 1 }\n      }.should change { Post.count }.by(+1)\n    end\n\n    context \"slave reads enforcing (action is not listed in force_slave_reads params)\" do\n      it \"should not enable enforcing\" do\n        get 'create'\n        controller.force_slave_reads?.should_not be_true\n      end\n\n      it \"should not do any actual enforcing\" do\n        Post.on_slave.connection.should_not_receive(:select_value)\n        Post.connection.should_receive(:select_value).once.and_return(1)\n        get 'create'\n      end\n    end\n  end\n\n  describe \"GET 'destroy'\" do\n    it \"should redurect to index upon completion\" do\n      get 'destroy', :id => Post.first.id\n      response.should redirect_to(:action => :index)\n    end\n\n    it \"should delete a record\" do\n      lambda {\n        get 'destroy', :id => Post.first.id\n      }.should change { Post.count }.by(-1)\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/fixtures/avatars.yml",
    "content": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n\none:\n  user_id: 1\n  name: avatar1\n\ntwo:\n  user_id: 2\n  name: avatar2\n"
  },
  {
    "path": "test-project/spec/fixtures/categories.yml",
    "content": "# 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: two\n"
  },
  {
    "path": "test-project/spec/fixtures/categories_posts.yml",
    "content": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n\none_one:\n  post_id: 1\n  category_id: 1\n\none_two:\n  post_id: 1\n  category_id: 2\n\ntwo_one:\n  post_id: 2\n  category_id: 1\n\nwindoze_two:\n  post_id: 4\n  category_id: 2\n"
  },
  {
    "path": "test-project/spec/fixtures/comments.yml",
    "content": "avatar:\n  commentable: one (Avatar)\n  body: \"This is an avatar\"\n\npost:\n  commentable: one (Post)\n  body: \"This is a post\"\n\nuser:\n  commentable: one (User)\n  body: \"This is a user\"\n"
  },
  {
    "path": "test-project/spec/fixtures/event_shards_info.yml",
    "content": "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  created_at: <%= Time.now.to_s(:db) %>\n  updated_at: <%= Time.now.to_s(:db) %>\n\nshard2:\n  id: 2\n  db_host: localhost\n  db_name: db_charmer_events_test_shard02\n  open: 1\n  enabled: 1\n  blocks_count: 1\n  created_at: <%= Time.now.to_s(:db) %>\n  updated_at: <%= Time.now.to_s(:db) %>\n\nempty:\n  id: 3\n  db_host: localhost\n  db_name: db_charmer_events_test_shard01\n  open: 1\n  enabled: 1\n  blocks_count: 0\n  created_at: <%= Time.now.to_s(:db) %>\n  updated_at: <%= Time.now.to_s(:db) %>\n"
  },
  {
    "path": "test-project/spec/fixtures/event_shards_map.yml",
    "content": "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: <%= Time.now.to_s(:db) %>\n\nblock2:\n  start_id: 10\n  end_id: 20\n  shard_id: 2\n  block_size: 10\n  created_at: <%= Time.now.to_s(:db) %>\n  updated_at: <%= Time.now.to_s(:db) %>\n\nblock3:\n  start_id: 20\n  end_id: 30\n  shard_id: 1\n  block_size: 10\n  created_at: <%= Time.now.to_s(:db) %>\n  updated_at: <%= Time.now.to_s(:db) %>\n"
  },
  {
    "path": "test-project/spec/fixtures/log_records.yml",
    "content": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n\none:\n  level: MyString\n  message: MyString\n\ntwo:\n  level: MyString\n  message: MyString\n"
  },
  {
    "path": "test-project/spec/fixtures/posts.yml",
    "content": "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\nwindoze:\n  id: 3\n  title: Windows Sucks\n  body: Yeah, it does!\n  user_id: 3\n\nfoo:\n  id: 4\n  title: Foo\n  body: Foo body\n  user_id: 3\n"
  },
  {
    "path": "test-project/spec/fixtures/users.yml",
    "content": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\n\none:\n  id: 1\n  login: MyString\n  password: MyString\n\ntwo:\n  id: 2\n  login: MyString\n  password: MyString\n\nbill:\n  id: 3\n  login: bill\n  password: windoze\n"
  },
  {
    "path": "test-project/spec/integration/multi_threading_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe \"DbCharmer integration tests\" do\n  def do_test(test_seconds, thread_count)\n    start_time = Time.now.to_f\n    threads = Array.new\n\n    while threads.size < thread_count\n      threads <<  Thread.new do\n        while Time.now.to_f - start_time < test_seconds do\n          User.create!(:login => \"user#{rand}\", :password => rand)\n          User.uncached { User.on_db(:slave01).first }\n        end\n      end\n    end\n\n    # Wait for threads to finish\n    threads.each(&:join)\n  end\n\n  it \"should work in single-threaded mode\" do\n    do_test(10, 1)\n  end\n\n  it \"should work with 5 threads\" do\n    do_test(10, 5)\n  end\n\n  it \"should use default connection passed in db_magic call in all threads\" do\n    # Define a class with db magic in it\n    class TestLogRecordWithThreads < ActiveRecord::Base\n      self.table_name = :log_records\n      db_magic :connection => :logs\n    end\n\n    # Check conection in the same thread\n    TestLogRecordWithThreads.connection.db_charmer_connection_name.should == \"logs\"\n\n    # Check connection in a different thread\n    Thread.new {\n      TestLogRecordWithThreads.connection.db_charmer_connection_name.should == \"logs\"\n    }.join\n  end\n\n  it \"should use default connection passed in db_magic call when master connection is being remapped\" do\n    class TestLogRecordWithThreadsAndRemapping < ActiveRecord::Base\n      self.table_name = :log_records\n      db_magic :connection => :logs\n    end\n\n    # Test in main thread\n    expect {\n      DbCharmer.with_remapped_databases(:master => :slave01) do\n        TestLogRecordWithThreadsAndRemapping.first\n      end\n    }.to_not raise_error\n\n    # Test in another thread\n    Thread.new {\n      expect {\n        DbCharmer.with_remapped_databases(:master => :slave01) do\n          TestLogRecordWithThreadsAndRemapping.first\n        end\n      }.to_not raise_error\n    }.join\n  end\nend unless ENV['SKIP_MT_TESTS']\n"
  },
  {
    "path": "test-project/spec/models/avatar_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe Avatar do\n  before(:each) do\n    @valid_attributes = {\n      :user_id => 1,\n      :name => \"value for name\"\n    }\n  end\n\n  it \"should create a new instance given valid attributes\" do\n    Avatar.create!(@valid_attributes)\n  end\nend\n"
  },
  {
    "path": "test-project/spec/models/cars_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe Ford, \"STI model\" do\n  before(:each) do\n    @valid_attributes = {\n      :license => \"FFGH-9134\"\n    }\n  end\n\n  it \"should create a new instance given valid attributes\" do\n    Ford.create!(@valid_attributes)\n  end\n\n  it \"should properly handle slave find calls\" do\n    Ford.first.should be_valid\n  end\nend\n\ndescribe Toyota, \"STI model\" do\n  before(:each) do\n    @valid_attributes = {\n      :license => \"TFGH-9134\"\n    }\n  end\n\n  it \"should create a new instance given valid attributes\" do\n    Toyota.create!(@valid_attributes)\n  end\n\n  it \"should properly handle slave find calls\" do\n    Toyota.first.should be_valid\n  end\nend\n"
  },
  {
    "path": "test-project/spec/models/categories_posts_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe CategoriesPosts do\n  before(:each) do\n    @valid_attributes = {\n      :post_id => 1,\n      :category_id => 1\n    }\n  end\n\n  it \"should create a new instance given valid attributes\" do\n    CategoriesPosts.create!(@valid_attributes)\n  end\nend\n"
  },
  {
    "path": "test-project/spec/models/category_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe Category do\n  before(:each) do\n    @valid_attributes = {\n      :name => \"value for name\"\n    }\n  end\n\n  it \"should create a new instance given valid attributes\" do\n    Category.create!(@valid_attributes)\n  end\nend\n"
  },
  {
    "path": "test-project/spec/models/comment_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe Comment do\n  fixtures :comments, :avatars, :posts, :users\n\n  describe \"preload polymorphic association\" do\n    subject do\n      lambda {\n        Comment.find(:all, :include => :commentable)\n      }\n    end\n\n    it { should_not raise_error }\n  end\nend\n"
  },
  {
    "path": "test-project/spec/models/event_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe Event, \"sharded model\" do\n  fixtures :event_shards_info, :event_shards_map\n\n  it \"should respond to shard_for method\" do\n    Event.should respond_to(:shard_for)\n  end\n\n  it \"should correctly switch shards\" do\n    # Cleanup sharded tables\n    Event.on_each_shard { |event| event.delete_all }\n\n    # Check that they are empty\n    Event.shard_for(2).all.should be_empty\n    Event.shard_for(12).all.should be_empty\n\n    # Create some data (one record in each shard)\n    Event.shard_for(2).create!(\n      :from_uid => 1,\n      :to_uid => 2,\n      :original_created_at => Time.now,\n      :event_type => 1,\n      :event_data => 'foo'\n    )\n    Event.shard_for(12).create!(\n      :from_uid => 1,\n      :to_uid => 12,\n      :original_created_at => Time.now,\n      :event_type => 1,\n      :event_data => 'bar'\n    )\n\n    # Check sharded tables to make sure they have the data\n    Event.shard_for(2).find_all_by_from_uid(1).map(&:event_data).should == [ 'foo' ]\n    Event.shard_for(12).find_all_by_from_uid(1).map(&:event_data).should == [ 'bar' ]\n  end\n\n  it \"should allocate new blocks when needed\" do\n    # Cleanup sharded tables\n    Event.on_each_shard { |event| event.delete_all }\n\n    # Check new block, it should be empty\n    Event.shard_for(100).count.should be_zero\n\n    # Create an object\n    Event.shard_for(100).create!(\n      :from_uid => 1,\n      :to_uid => 100,\n      :original_created_at => Time.now,\n      :event_type => 1,\n      :event_data => 'blah'\n    )\n\n    # Check the new block\n    Event.shard_for(100).count.should == 1\n  end\n\n  it \"should fail to perform any database operations w/o a shard specification\" do\n    Event.stub(:column_defaults).and_return({})\n    Event.stub(:columns_hash).and_return({})\n\n    lambda { Event.first }.should raise_error(ActiveRecord::ConnectionNotEstablished)\n    lambda { Event.create }.should raise_error(ActiveRecord::ConnectionNotEstablished)\n    lambda { Event.delete_all }.should raise_error(ActiveRecord::ConnectionNotEstablished)\n  end\n\n  it \"should not fail when AR does some internal calls to the database\" do\n    # Cleanup sharded tables\n    Event.on_each_shard { |event| event.delete_all }\n\n    # Create an object\n    x = Event.shard_for(100).create!(\n      :from_uid => 1,\n      :to_uid => 100,\n      :original_created_at => Time.now,\n      :event_type => 1,\n      :event_data => 'blah'\n    )\n\n    Event.reset_column_information\n    lambda { x.inspect }.should_not raise_error\n  end\nend\n"
  },
  {
    "path": "test-project/spec/models/log_record_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe LogRecord do\n  before(:each) do\n    @valid_attributes = {\n      :level => \"value for level\",\n      :message => \"value for message\"\n    }\n  end\n\n  it \"should create a new instance given valid attributes\" do\n    LogRecord.create!(@valid_attributes)\n  end\nend\n"
  },
  {
    "path": "test-project/spec/models/post_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe Post do\n  before(:each) do\n    @valid_attributes = {\n      :title => \"value for title\",\n      :body => \"value for body\"\n    }\n  end\n\n  it \"should create a new instance given valid attributes\" do\n    Post.create!(@valid_attributes)\n  end\nend\n"
  },
  {
    "path": "test-project/spec/models/range_sharded_model_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe RangeShardedModel do\n  describe \"class method shard_for\" do\n    describe \"should correctly set shards in range-defined shards\" do\n      [ 0, 1, 50, 99].each do |id|\n        it \"for #{id}\" do\n          RangeShardedModel.shard_for(id) do |m|\n            m.connection.object_id.should == RangeShardedModel.on_db(:shard1).connection.object_id\n          end\n        end\n      end\n\n      [ 100, 101, 150, 199, 200].each do |id|\n        it \"for #{id}\" do\n          RangeShardedModel.shard_for(id) do |m|\n            m.connection.object_id.should == RangeShardedModel.on_db(:shard2).connection.object_id\n          end\n        end\n      end\n    end\n\n    describe \"should correctly set shards in default shard\" do\n      [ 201, 500].each do |id|\n        it \"for #{id}\" do\n          RangeShardedModel.shard_for(id) do |m|\n            m.connection.object_id.should == RangeShardedModel.on_db(:shard3).connection.object_id\n          end\n        end\n      end\n    end\n\n    it \"should raise an exception when there is no default shard and no ranged shards matched\" do\n      begin\n        default_shard = RangeShardedModel.sharded_connection.sharder.ranges.delete(:default)\n        lambda { RangeShardedModel.shard_for(500) }.should raise_error(ArgumentError)\n      ensure\n        RangeShardedModel.sharded_connection.sharder.ranges[:default] = default_shard\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "test-project/spec/models/user_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe User do\n  before(:each) do\n    @valid_attributes = {\n      :login => \"value for login\",\n      :password => \"value for password\"\n    }\n    User.switch_connection_to(nil)\n    User.db_charmer_default_connection = nil\n  end\n\n  it \"should create a new instance given valid attributes\" do\n    User.create!(@valid_attributes)\n  end\n\n  it \"should create a new instance in a specified db\" do\n    # Just to make sure\n    User.on_db(:user_master).connection.object_id.should_not == User.connection.object_id\n\n    # Default connection should not be touched\n    User.connection.should_not_receive(:insert)\n\n    # Only specified connection receives an insert\n    User.on_db(:user_master).connection.should_receive(:insert)\n\n    # Test!\n    User.on_db(:user_master).create!(@valid_attributes)\n  end\nend\n"
  },
  {
    "path": "test-project/spec/sharding/connection_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe DbCharmer::Sharding::Connection do\n  describe \"in constructor\" do\n    it \"should not fail if method name is correct\" do\n      lambda { DbCharmer::Sharding::Connection.new(:name => :foo, :method => :range, :ranges => {}) }.should_not raise_error\n    end\n\n    it \"should fail if method name is missing\" do\n      lambda { DbCharmer::Sharding::Connection.new(:name => :foo) }.should raise_error(ArgumentError)\n    end\n\n    it \"should fail if method name is invalid\" do\n      lambda { DbCharmer::Sharding::Connection.new(:name => :foo, :method => :foo) }.should raise_error(NameError)\n    end\n\n    it \"should instantiate a sharder class according to the :method value\" do\n      DbCharmer::Sharding::Method::Range.should_receive(:new)\n      DbCharmer::Sharding::Connection.new(:name => :foo, :method => :range, :ranges => {})\n    end\n  end\nend\n\n"
  },
  {
    "path": "test-project/spec/sharding/method/db_block_map_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe DbCharmer::Sharding::Method::DbBlockMap do\n  fixtures :event_shards_info, :event_shards_map\n\n  before(:each) do\n    @sharder = DbCharmer::Sharding::Method::DbBlockMap.new(\n      :name => :social,\n      :block_size => 10,\n      :map_table => :event_shards_map,\n      :shards_table => :event_shards_info,\n      :connection => :social_shard_info\n    )\n    @conn = DbCharmer::ConnectionFactory.connect(:social_shard_info)\n  end\n\n  describe \"standard interface\" do\n    it \"should respond to shard_for_id\" do\n      @sharder.should respond_to(:shard_for_key)\n    end\n\n    it \"should return a shard config to be used for a key\" do\n      @sharder.shard_for_key(1).should be_kind_of(Hash)\n    end\n\n    it \"should have shard_connections method and return a list of db connections\" do\n      @sharder.shard_connections.should_not be_empty\n    end\n  end\n\n  it \"should correctly return shards for all blocks defined in the mapping table\" do\n    blocks = @conn.select_all(\"SELECT * FROM event_shards_map\")\n\n    blocks.each do |blk|\n      shard = @sharder.shard_for_key(blk['start_id'])\n      shard[:connection_name].should match(/social.*#{blk['shard_id']}$/)\n\n      shard = @sharder.shard_for_key(blk['start_id'].to_i + 1)\n      shard[:connection_name].should match(/social.*#{blk['shard_id']}$/)\n\n      shard = @sharder.shard_for_key(blk['end_id'].to_i - 1)\n      shard[:connection_name].should match(/social.*#{blk['shard_id']}$/)\n    end\n  end\n\n  describe \"for non-existing blocks\" do\n    before do\n      @max_id = @conn.select_value(\"SELECT max(end_id) FROM event_shards_map\").to_i\n      Rails.cache.clear\n    end\n\n    it \"should not fail\" do\n      lambda {\n         @sharder.shard_for_key(@max_id + 1)\n      }.should_not raise_error\n    end\n\n    it \"should create a new one\" do\n      @sharder.shard_for_key(@max_id + 1).should_not be_nil\n    end\n\n    it \"should assign it to the least loaded shard\" do\n      @sharder.shard_for_key(@max_id + 1)[:connection_name].should match(/shard.*03$/)\n    end\n\n    it \"should not consider non-open shards\" do\n      @conn.execute(\"UPDATE event_shards_info SET open = 0 WHERE id = 3\")\n      @sharder.shard_for_key(@max_id + 1)[:connection_name].should_not match(/shard.*03$/)\n    end\n\n    it \"should not consider disabled shards\" do\n      @conn.execute(\"UPDATE event_shards_info SET enabled = 0 WHERE id = 3\")\n      @sharder.shard_for_key(@max_id + 1)[:connection_name].should_not match(/shard.*03$/)\n    end\n\n    it \"should increment the blocks counter on the shard\" do\n      lambda {\n        @sharder.shard_for_key(@max_id + 1)\n      }.should change {\n         @conn.select_value(\"SELECT blocks_count FROM event_shards_info WHERE id = 3\").to_i\n      }.by(+1)\n    end\n\n    it \"should raise duplicate key error when allocating same block twice\" do\n      @sharder.allocate_new_block_for_key(@max_id + 1)\n      lambda {\n        @sharder.allocate_new_block_for_key(@max_id + 1)\n      }.should raise_error(ActiveRecord::StatementInvalid)\n    end\n\n    it \"should handle duplicate key errors\" do\n      @sharder.shard_for_key(@max_id + 1)\n\n      actual_block = @sharder.block_for_key(@max_id + 1)\n      @sharder.should_receive(:block_for_key).twice.and_return(nil, actual_block)\n\n      @sharder.shard_for_key(@max_id + 1)\n    end\n  end\n\n  it \"should fail on invalid shard references\" do\n     @conn.execute(\"DELETE FROM event_shards_info\")\n     lambda { @sharder.shard_for_key(1) }.should raise_error(ArgumentError)\n  end\n\n  it \"should cache shards info\" do\n    shard = DbCharmer::Sharding::Method::DbBlockMap::ShardInfo.first\n    DbCharmer::Sharding::Method::DbBlockMap::ShardInfo.should_receive(:find_by_id).once.and_return(shard)\n    @sharder.shard_info_by_id(1)\n    @sharder.shard_info_by_id(1)\n  end\n\n  it \"should not cache shards info when explicitly asked not to\" do\n    shard = DbCharmer::Sharding::Method::DbBlockMap::ShardInfo.first\n    DbCharmer::Sharding::Method::DbBlockMap::ShardInfo.should_receive(:find_by_id).twice.and_return(shard)\n    @sharder.shard_info_by_id(1, false)\n    @sharder.shard_info_by_id(1, false)\n  end\n\n  it \"should cache blocks\" do\n    @sharder.block_for_key(1)\n    @sharder.connection.should_not_receive(:select_one)\n    @sharder.block_for_key(1)\n    @sharder.block_for_key(2)\n  end\n\n  it \"should not cache blocks if asked not to\" do\n    block = @sharder.block_for_key(1)\n    @sharder.connection.should_receive(:select_one).twice.and_return(block)\n    @sharder.block_for_key(1, false)\n    @sharder.block_for_key(2, false)\n  end\n\n\nend\n"
  },
  {
    "path": "test-project/spec/sharding/method/hash_map_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe DbCharmer::Sharding::Method::HashMap do\n  SHARDING_MAP = {\n    'US'  => :us_users,\n    'CA'  => :ca_users,\n    :default  => :other_users\n  }\n\n  before do\n    @sharder = DbCharmer::Sharding::Method::HashMap.new(:map => SHARDING_MAP)\n  end\n\n  describe \"standard interface\" do\n    it \"should respond to shard_for_id\" do\n      @sharder.should respond_to(:shard_for_key)\n    end\n\n    it \"should return a shard name to be used for an key\" do\n      @sharder.shard_for_key('US').should be_kind_of(Symbol)\n    end\n\n    it \"should support default shard\" do\n      @sharder.support_default_shard?.should be_true\n    end\n  end\n\n  describe \"should correctly return shards for all keys defined in the map\" do\n    SHARDING_MAP.except(:default).each do |key, val|\n      it \"for #{key}\" do\n        @sharder.shard_for_key(key).should == val\n      end\n    end\n  end\n\n  it \"should correctly return default shard\" do\n    @sharder.shard_for_key('UA').should == :other_users\n  end\n\n  it \"should raise an exception when there is no default shard and nothing matched\" do\n    @sharder.map.delete(:default)\n    lambda { @sharder.shard_for_key('UA') }.should raise_error(ArgumentError)\n  end\nend\n"
  },
  {
    "path": "test-project/spec/sharding/method/range_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe DbCharmer::Sharding::Method::Range do\n  SHARDING_RANGES = {\n    0...100   => :shard1,\n    100..200  => :shard2,\n    :default  => :shard3\n  }\n\n  before do\n    @sharder = DbCharmer::Sharding::Method::Range.new(:ranges => SHARDING_RANGES)\n  end\n\n  describe \"standard interface\" do\n    it \"should respond to shard_for_id\" do\n      @sharder.should respond_to(:shard_for_key)\n    end\n\n    it \"should return a shard name to be used for an key\" do\n      @sharder.shard_for_key(1).should be_kind_of(Symbol)\n    end\n\n    it \"should support default shard\" do\n      @sharder.support_default_shard?.should be_true\n    end\n  end\n\n  describe \"should correctly return shards for all ids in defined ranges\" do\n    [ 0, 1, 50, 99].each do |id|\n      it \"for #{id}\" do\n        @sharder.shard_for_key(id).should == :shard1\n      end\n    end\n\n    [ 100, 101, 150, 199, 200].each do |id|\n      it \"for #{id}\" do\n        @sharder.shard_for_key(id).should == :shard2\n      end\n    end\n  end\n\n  describe \"should correctly return shard for all ids outside the ranges if has a default\" do\n    [ 201, 500].each do |id|\n      it \"for #{id}\" do\n        @sharder.shard_for_key(id).should == :shard3\n      end\n    end\n  end\n\n  it \"should raise an exception when there is no default shard and no ranges matched\" do\n    @sharder.ranges.delete(:default)\n    lambda { @sharder.shard_for_key(500) }.should raise_error(ArgumentError)\n  end\nend\n"
  },
  {
    "path": "test-project/spec/sharding/sharding_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe \"DbCharmer::Sharding\" do\n  describe \"in register_connection method\" do\n    it \"should raise an exception if passed config has no :name parameter\" do\n      lambda {\n        DbCharmer::Sharding.register_connection(:method => :range, :ranges => { :default => :foo })\n      }.should raise_error(ArgumentError)\n    end\n\n    it \"should not raise an exception if passed config has all required params\" do\n      lambda {\n        DbCharmer::Sharding.register_connection(:method => :range, :ranges => { :default => :foo }, :name => :foo)\n      }.should_not raise_error\n    end\n  end\n\n  describe \"in sharded_connection method\" do\n    it \"should raise an error for invalid connection names\" do\n      lambda { DbCharmer::Sharding.sharded_connection(:blah) }.should raise_error(ArgumentError)\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/spec_helper.rb",
    "content": "# This file is copied to spec/ when you run 'rails generate rspec:install'\nENV[\"RAILS_ENV\"] = 'test'\nrequire File.expand_path(\"../../config/environment\", __FILE__)\nrequire 'rspec/rails'\n\n# Requires supporting ruby files with custom matchers and macros, etc,\n# in spec/support/ and its subdirectories.\nDir[Rails.root.join(\"spec/support/**/*.rb\")].each {|f| require f}\n\nRSpec.configure do |config|\n  # == Mock Framework\n  #\n  # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:\n  #\n  # config.mock_with :mocha\n  # config.mock_with :flexmock\n  # config.mock_with :rr\n  config.mock_with :rspec\n\n  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures\n  config.fixture_path = \"#{::Rails.root}/spec/fixtures\"\n\n  # If you're not using ActiveRecord, or you'd prefer not to run each of your\n  # examples within a transaction, remove the following line or assign false\n  # instead of true.\n  config.use_transactional_fixtures = false\n  config.use_instantiated_fixtures  = false\nend\n"
  },
  {
    "path": "test-project/spec/support/rails31_stub_connection.rb",
    "content": "def stub_columns_for_rails31(connection)\n  return unless DbCharmer.rails31?\n  connection.abstract_connection_class.retrieve_connection.stub(:columns).and_return([])\nend\n"
  },
  {
    "path": "test-project/spec/unit/abstract_adapter/log_formatting_spec.rb",
    "content": "require 'spec_helper'\n\nif DbCharmer.rails2?\n  describe 'AbstractAdapter' do\n    it \"should respond to connection_name accessor\" do\n      ActiveRecord::Base.connection.respond_to?(:connection_name).should be_true\n    end\n\n    it \"should have connection_name read accessor working\" do\n      DbCharmer::ConnectionFactory.generate_abstract_class('logs').connection.connection_name.should == 'logs'\n      DbCharmer::ConnectionFactory.generate_abstract_class('slave01').connection.connection_name.should == 'slave01'\n      ActiveRecord::Base.connection.connection_name.should be_nil\n    end\n\n    it \"should append connection name to log records on non-default connections\" do\n      User.switch_connection_to nil\n      default_message = User.connection.send(:format_log_entry, 'hello world')\n      switched_message = User.on_db(:slave01).connection.send(:format_log_entry, 'hello world')\n      switched_message.should_not == default_message\n      switched_message.should match(/slave01/)\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/action_controller/force_slave_reads_spec.rb",
    "content": "require 'spec_helper'\n\nclass BlahController < ActionController::Base; end\n\ndescribe ActionController, \"with force_slave_reads extension\" do\n  before do\n    BlahController.force_slave_reads({}) # cleanup status\n  end\n\n  it \"should not force slave reads when there are no actions defined as forced\" do\n    BlahController.force_slave_reads_action?(:index).should be_false\n  end\n\n  it \"should force slave reads for :only actions\" do\n    BlahController.force_slave_reads :only => :index\n    BlahController.force_slave_reads_action?(:index).should be_true\n  end\n\n  it \"should not force slave reads for non-listed actions when there is :only parameter\" do\n    BlahController.force_slave_reads :only => :index\n    BlahController.force_slave_reads_action?(:show).should be_false\n  end\n\n  it \"should not force slave reads for :except actions\" do\n    BlahController.force_slave_reads :except => :delete\n    BlahController.force_slave_reads_action?(:delete).should be_false\n  end\n\n  it \"should force slave reads for non-listed actions when there is :except parameter\" do\n    BlahController.force_slave_reads :except => :delete\n    BlahController.force_slave_reads_action?(:index).should be_true\n  end\n\n  it \"should not force slave reads for actions listed in both :except and :only lists\" do\n    BlahController.force_slave_reads :only => :delete, :except => :delete\n    BlahController.force_slave_reads_action?(:delete).should be_false\n  end\n\n  it \"should not force slave reads for non-listed actions when there are :except and :only lists present\" do\n    BlahController.force_slave_reads :only => :index, :except => :delete\n    BlahController.force_slave_reads_action?(:show).should be_false\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/active_record/association_preload_spec.rb",
    "content": "require 'spec_helper'\n\nif DbCharmer.rails2?\n  describe \"ActiveRecord preload_associations method\" do\n    it \"should be public\" do\n      ActiveRecord::Base.public_methods.collect(&:to_s).member?('preload_associations').should be_true\n    end\n  end\nend\n\ndescribe \"ActiveRecord in finder methods\" do\n  fixtures :categories, :users, :posts, :categories_posts, :avatars\n\n  before do\n    Post.db_magic :connection => nil\n    User.db_magic :connection => nil\n  end\n\n  after do\n    Post.db_magic(Post::DB_MAGIC_DEFAULT_PARAMS)\n  end\n\n  it \"should switch all belongs_to association connections when :include is used\" do\n    User.connection.should_not_receive(:select_all)\n    Post.on_db(:slave01).all(:include => :user)\n  end\n\n  it \"should switch all has_many association connections when :include is used\" do\n    Post.connection.should_not_receive(:select_all)\n    User.on_db(:slave01).all(:include => :posts)\n  end\n\n  it \"should switch all has_one association connections when :include is used\" do\n    Avatar.connection.should_not_receive(:select_all)\n    User.on_db(:slave01).all(:include => :avatar)\n  end\n\n  it \"should switch all has_and_belongs_to_many association connections when :include is used\" do\n    Post.connection.should_not_receive(:select_all)\n    Category.on_db(:slave01).all(:include => :posts)\n  end\n\n  #-------------------------------------------------------------------------------------------\n  it \"should not switch assocations when called on a top-level connection\" do\n    User.connection.should_receive(:select_all).and_return([])\n    Post.all(:include => :user)\n  end\n\n  it \"should not switch connection when association model and main model are on different servers\" do\n    LogRecord.connection.should_receive(:select_all).and_return([])\n    User.on_db(:slave01).all(:include => :log_records)\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/active_record/association_proxy_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe \"DbCharmer::AssociationProxy extending AR::Associations\" do\n  fixtures :users, :posts\n\n  it \"should add proxy? => true method\" do\n    users(:bill).posts.proxy?.should be_true\n  end\n\n  describe \"in has_many associations\" do\n    before do\n      @user = users(:bill)\n      @posts = @user.posts.all\n      Post.switch_connection_to(:logs)\n      User.switch_connection_to(:logs)\n    end\n\n    after do\n      Post.switch_connection_to(nil)\n      User.switch_connection_to(nil)\n    end\n\n    it \"should implement on_db proxy\" do\n      Post.connection.should_not_receive(:select_all)\n      User.connection.should_not_receive(:select_all)\n\n      stub_columns_for_rails31 Post.on_db(:logs).connection\n      Post.on_db(:slave01).connection.should_receive(:select_all).and_return(@posts.map { |p| p.attributes })\n      assert_equal @posts, @user.posts.on_db(:slave01)\n    end\n\n    it \"on_db should work in prefix mode\" do\n      Post.connection.should_not_receive(:select_all)\n      User.connection.should_not_receive(:select_all)\n\n      stub_columns_for_rails31 Post.on_db(:logs).connection\n      Post.on_db(:slave01).connection.should_receive(:select_all).and_return(@posts.map { |p| p.attributes })\n      @user.on_db(:slave01).posts.should == @posts\n    end\n\n    it \"should actually proxy calls to the rails association proxy\" do\n      Post.switch_connection_to(nil)\n      @user.posts.on_db(:slave01).count.should == @user.posts.count\n    end\n\n    it \"should work with named scopes\" do\n      Post.switch_connection_to(nil)\n      @user.posts.windows_posts.on_db(:slave01).count.should == @user.posts.windows_posts.count\n    end\n\n    it \"should work with chained named scopes\" do\n      Post.switch_connection_to(nil)\n      @user.posts.windows_posts.dummy_scope.on_db(:slave01).count.should == @user.posts.windows_posts.dummy_scope.count\n    end\n  end\n\n  describe \"in belongs_to associations\" do\n    before do\n      @post = posts(:windoze)\n      @user = users(:bill)\n      User.switch_connection_to(:logs)\n      User.connection.object_id.should_not == Post.connection.object_id\n    end\n\n    after do\n      User.switch_connection_to(nil)\n    end\n\n    it \"should implement on_db proxy\" do\n      pending\n      Post.connection.should_not_receive(:select_all)\n      User.connection.should_not_receive(:select_all)\n      User.on_db(:slave01).connection.should_receive(:select_all).once.and_return([ @user ])\n      @post.user.on_db(:slave01).should == @post.user\n    end\n\n    it \"on_db should work in prefix mode\" do\n      pending\n      Post.connection.should_not_receive(:select_all)\n      User.connection.should_not_receive(:select_all)\n      User.on_db(:slave01).connection.should_receive(:select_all).once.and_return([ @user ])\n      @post.on_db(:slave01).user.should == @post.user\n    end\n\n    it \"should actually proxy calls to the rails association proxy\" do\n      User.switch_connection_to(nil)\n      @post.user.on_db(:slave01).should == @post.user\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/active_record/class_attributes_spec.rb",
    "content": "require 'spec_helper'\n\nclass FooModel < ActiveRecord::Base; end\n\ndescribe DbCharmer, \"for ActiveRecord models\" do\n  context \"in db_charmer_connection_proxy methods\" do\n    before do\n      FooModel.db_charmer_connection_proxy = nil\n      FooModel.db_charmer_default_connection = nil\n    end\n\n    it \"should implement both accessor methods\" do\n      proxy = double('connection proxy')\n      FooModel.db_charmer_connection_proxy = proxy\n      FooModel.db_charmer_connection_proxy.should be(proxy)\n    end\n  end\n\n  context \"in db_charmer_default_connection methods\" do\n    before do\n      FooModel.db_charmer_default_connection = nil\n      FooModel.db_charmer_default_connection = nil\n    end\n\n    it \"should implement both accessor methods\" do\n      conn = double('connection')\n      FooModel.db_charmer_default_connection = conn\n      FooModel.db_charmer_default_connection.should be(conn)\n    end\n  end\n\n  context \"in db_charmer_opts methods\" do\n    before do\n      FooModel.db_charmer_opts = nil\n    end\n\n    it \"should implement both accessor methods\" do\n      opts = { :foo => :bar}\n      FooModel.db_charmer_opts = opts\n      FooModel.db_charmer_opts.should be(opts)\n    end\n  end\n\n  context \"in db_charmer_slaves methods\" do\n    it \"should return [] if no slaves set for a model\" do\n      FooModel.db_charmer_slaves = nil\n      FooModel.db_charmer_slaves.should == []\n    end\n\n    it \"should implement both accessor methods\" do\n      proxy = double('connection proxy')\n      FooModel.db_charmer_slaves = [ proxy ]\n      FooModel.db_charmer_slaves.should == [ proxy ]\n    end\n\n    it \"should implement random slave selection\" do\n      FooModel.db_charmer_slaves = [ :proxy1, :proxy2, :proxy3 ]\n      srand(0)\n      FooModel.db_charmer_random_slave.should == :proxy1\n      FooModel.db_charmer_random_slave.should == :proxy2\n      FooModel.db_charmer_random_slave.should == :proxy1\n      FooModel.db_charmer_random_slave.should == :proxy2\n      FooModel.db_charmer_random_slave.should == :proxy2\n      FooModel.db_charmer_random_slave.should == :proxy3\n    end\n  end\n\n  context \"in db_charmer_connection_levels methods\" do\n    it \"should return 0 by default\" do\n      FooModel.db_charmer_connection_level = nil\n      FooModel.db_charmer_connection_level.should == 0\n    end\n\n    it \"should implement both accessor methods and support inc/dec operations\" do\n      FooModel.db_charmer_connection_level = 1\n      FooModel.db_charmer_connection_level.should == 1\n      FooModel.db_charmer_connection_level += 1\n      FooModel.db_charmer_connection_level.should == 2\n      FooModel.db_charmer_connection_level -= 1\n      FooModel.db_charmer_connection_level.should == 1\n    end\n\n    it \"should implement db_charmer_top_level_connection? method\" do\n      FooModel.db_charmer_connection_level = 1\n      FooModel.should_not be_db_charmer_top_level_connection\n      FooModel.db_charmer_connection_level = 0\n      FooModel.should be_db_charmer_top_level_connection\n    end\n  end\n\n  context \"in connection method\" do\n    it \"should return AR's original connection if no connection proxy is set\" do\n      FooModel.db_charmer_connection_proxy = nil\n      FooModel.db_charmer_default_connection = nil\n      FooModel.connection.should be_kind_of(ActiveRecord::ConnectionAdapters::AbstractAdapter)\n    end\n  end\n\n  context \"in db_charmer_force_slave_reads? method\" do\n    it \"should use per-model settings when possible\" do\n      FooModel.db_charmer_force_slave_reads = true\n      DbCharmer.should_not_receive(:force_slave_reads?)\n      FooModel.db_charmer_force_slave_reads?.should be_true\n    end\n\n    it \"should use global settings when local setting is false\" do\n      FooModel.db_charmer_force_slave_reads = false\n\n      DbCharmer.should_receive(:force_slave_reads?).and_return(true)\n      FooModel.db_charmer_force_slave_reads?.should be_true\n\n      DbCharmer.should_receive(:force_slave_reads?).and_return(false)\n      FooModel.db_charmer_force_slave_reads?.should be_false\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/active_record/connection_switching_spec.rb",
    "content": "require 'spec_helper'\n\nclass FooModelForConnSwitching < ActiveRecord::Base; end\nclass BarModelForConnSwitching < ActiveRecord::Base; end\n\ndescribe DbCharmer, \"AR connection switching\" do\n  describe \"in switch_connection_to method\" do\n    before(:all) do\n      BarModelForConnSwitching.hijack_connection!\n    end\n\n    before :each do\n      @proxy = double('proxy')\n      @proxy.stub(:db_charmer_connection_name).and_return(:myproxy)\n    end\n\n    before do\n      BarModelForConnSwitching.db_charmer_connection_proxy = @proxy\n      BarModelForConnSwitching.connection.should be(@proxy)\n    end\n\n    it \"should accept nil and reset connection to default\" do\n      BarModelForConnSwitching.switch_connection_to(nil)\n      BarModelForConnSwitching.connection.should be(ActiveRecord::Base.connection)\n    end\n\n    it \"should accept a string and generate an abstract class with connection factory\" do\n      BarModelForConnSwitching.switch_connection_to('logs')\n      BarModelForConnSwitching.connection.object_id == DbCharmer::ConnectionFactory.connect('logs').object_id\n    end\n\n    it \"should accept a symbol and generate an abstract class with connection factory\" do\n      BarModelForConnSwitching.switch_connection_to(:logs)\n      BarModelForConnSwitching.connection.object_id.should == DbCharmer::ConnectionFactory.connect('logs').object_id\n    end\n\n    it \"should accept a model and use its connection proxy value\" do\n      FooModelForConnSwitching.switch_connection_to(:logs)\n      BarModelForConnSwitching.switch_connection_to(FooModelForConnSwitching)\n      BarModelForConnSwitching.connection.object_id.should == DbCharmer::ConnectionFactory.connect('logs').object_id\n    end\n\n    context \"with a hash parameter\" do\n      before do\n        @conf = {\n          :adapter => 'mysql',\n          :username => \"db_charmer_ro\",\n          :database => \"db_charmer_sandbox_test\",\n          :connection_name => 'sanbox_ro'\n        }\n      end\n\n      it \"should fail if there is no :connection_name parameter\" do\n        @conf.delete(:connection_name)\n        lambda { BarModelForConnSwitching.switch_connection_to(@conf) }.should raise_error(ArgumentError)\n      end\n\n      it \"generate an abstract class with connection factory\" do\n        BarModelForConnSwitching.switch_connection_to(@conf)\n        BarModelForConnSwitching.connection.object_id.should == DbCharmer::ConnectionFactory.connect_to_db(@conf[:connection_name], @conf).object_id\n      end\n    end\n\n    it \"should support connection switching for AR::Base\" do\n      ActiveRecord::Base.switch_connection_to(:logs)\n      ActiveRecord::Base.connection.object_id == DbCharmer::ConnectionFactory.connect('logs').object_id\n      ActiveRecord::Base.switch_connection_to(nil)\n    end\n  end\nend\n\ndescribe DbCharmer, \"for ActiveRecord models\" do\n  describe \"in establish_real_connection_if_exists method\" do\n    it \"should check connection name if requested\" do\n      lambda { FooModelForConnSwitching.establish_real_connection_if_exists(:foo, true) }.should raise_error(ArgumentError)\n    end\n\n    it \"should not check connection name if not reqested\" do\n      lambda { FooModelForConnSwitching.establish_real_connection_if_exists(:foo) }.should_not raise_error\n    end\n\n    it \"should not check connection name if reqested not to\" do\n      lambda { FooModelForConnSwitching.establish_real_connection_if_exists(:foo, false) }.should_not raise_error\n    end\n\n    it \"should establish connection when connection configuration exists\" do\n      FooModelForConnSwitching.should_receive(:establish_connection)\n      FooModelForConnSwitching.establish_real_connection_if_exists(:logs)\n    end\n\n    it \"should not establish connection even when connection configuration does not exist\" do\n      FooModelForConnSwitching.should_not_receive(:establish_connection)\n      FooModelForConnSwitching.establish_real_connection_if_exists(:blah)\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/active_record/db_magic_spec.rb",
    "content": "require 'spec_helper'\n\nclass Blah < ActiveRecord::Base; end\n\ndescribe \"In ActiveRecord models\" do\n  describe \"db_magic method\" do\n    context \"with :connection parameter\" do\n      after do\n        DbCharmer.connections_should_exist = false\n      end\n\n      it \"should change model's connection to specified one\" do\n        Blah.db_magic :connection => :logs\n        Blah.connection.object_id.should == DbCharmer::ConnectionFactory.connect(:logs).object_id\n      end\n\n      it \"should pass :should_exist paramater value to the underlying connection logic\" do\n        DbCharmer::ConnectionFactory.should_receive(:connect).with(:logs, 'blah')\n        Blah.db_magic :connection => :logs, :should_exist => 'blah'\n        DbCharmer.connections_should_exist = true\n        DbCharmer::ConnectionFactory.should_receive(:connect).with(:logs, false)\n        Blah.db_magic :connection => :logs, :should_exist => false\n      end\n\n      it \"should use global DbCharmer's connections_should_exist attribute if no :should_exist passed\" do\n        DbCharmer.connections_should_exist = true\n        DbCharmer::ConnectionFactory.should_receive(:connect).with(:logs, true)\n        Blah.db_magic :connection => :logs\n      end\n    end\n\n    context \"with :slave or :slaves parameter\" do\n      it \"should merge :slave and :slaves values\" do\n        Blah.db_charmer_slaves = []\n        Blah.db_charmer_slaves.should be_empty\n\n        Blah.db_magic :slave => :slave01\n        Blah.db_charmer_slaves.size.should == 1\n\n        Blah.db_magic :slaves => [ :slave01 ]\n        Blah.db_charmer_slaves.size.should == 1\n\n        Blah.db_magic :slaves => [ :slave01 ], :slave => :logs\n        Blah.db_charmer_slaves.size.should == 2\n      end\n\n      it \"should make db_charmer_force_slave_reads = true by default\" do\n        Blah.db_magic :slave => :slave01\n        Blah.db_charmer_force_slave_reads.should be_true\n      end\n\n      it \"should pass force_slave_reads value to db_charmer_force_slave_reads\" do\n        Blah.db_magic :slave => :slave01, :force_slave_reads => false\n        Blah.db_charmer_force_slave_reads.should be_false\n\n        Blah.db_magic :slave => :slave01, :force_slave_reads => true\n        Blah.db_charmer_force_slave_reads.should be_true\n      end\n    end\n\n    it \"should set up a hook to propagate db_magic params to all the children models\" do\n      class ParentFoo < ActiveRecord::Base\n        db_magic :foo => :bar\n      end\n      class ChildFoo < ParentFoo; end\n\n      ChildFoo.db_charmer_opts.should == ParentFoo.db_charmer_opts\n    end\n\n    context \"with :sharded parameter\" do\n      class ShardTestingFoo < ActiveRecord::Base\n        db_magic :sharded => { :key => :id, :sharded_connection => :texts }\n      end\n\n      it \"should add shard_for method to the model\" do\n        ShardTestingFoo.should respond_to(:shard_for)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/active_record/master_slave_routing_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe \"ActiveRecord slave-enabled models\" do\n  before do\n    class User < ActiveRecord::Base\n      db_magic :connection => :user_master, :slave => :slave01\n    end\n  end\n\n  describe \"in finder method\" do\n    [ :last, :first, :all ].each do |meth|\n      describe meth do\n        it \"should go to the slave if called on the first level connection\" do\n          User.on_slave.connection.should_receive(:select_all).and_return([])\n          User.send(meth)\n        end\n\n        it \"should not change connection if called in an on_db block\" do\n          stub_columns_for_rails31 User.on_db(:logs).connection\n          User.on_db(:logs).connection.should_receive(:select_all).and_return([])\n          User.on_slave.connection.should_not_receive(:select_all)\n          User.on_db(:logs).send(meth)\n        end\n\n        it \"should not change connection when it's already been changed by on_slave call\" do\n          pending \"rails3: not sure if we need this spec\" if DbCharmer.rails3?\n          User.on_slave do\n            User.on_slave.connection.should_receive(:select_all).and_return([])\n            User.should_not_receive(:on_db)\n            User.send(meth)\n          end\n        end\n\n        it \"should not change connection if called in a transaction\" do\n          User.on_db(:user_master).connection.should_receive(:select_all).and_return([])\n          User.on_slave.connection.should_not_receive(:select_all)\n          User.transaction { User.send(meth) }\n        end\n      end\n    end\n\n    it \"should go to the master if called find with :lock => true option\" do\n      User.on_db(:user_master).connection.should_receive(:select_all).and_return([])\n      User.on_slave.connection.should_not_receive(:select_all)\n      User.find(:first, :lock => true)\n    end\n\n    it \"should not go to the master if no :lock => true option passed\" do\n      User.on_db(:user_master).connection.should_not_receive(:select_all)\n      User.on_slave.connection.should_receive(:select_all).and_return([])\n      User.find(:first)\n    end\n\n    it \"should correctly pass all find params to the underlying code\" do\n      User.delete_all\n      u1 = User.create(:login => 'foo')\n      u2 = User.create(:login => 'bar')\n\n      User.find(:all, :conditions => { :login => 'foo' }).should == [ u1 ]\n      User.find(:all, :limit => 1).size.should == 1\n      User.find(:first, :conditions => { :login => 'bar' }).should == u2\n    end\n  end\n\n  describe \"in calculation method\" do\n    [ :count, :minimum, :maximum, :average ].each do |meth|\n      describe meth do\n        it \"should go to the slave if called on the first level connection\" do\n          User.on_slave.connection.should_receive(:select_value).and_return(1)\n          User.send(meth, :id).should == 1\n        end\n\n        it \"should not change connection if called in an on_db block\" do\n          User.on_db(:logs).connection.should_receive(:select_value).and_return(1)\n          User.on_slave.connection.should_not_receive(:select_value)\n          User.on_db(:logs).send(meth, :id).should == 1\n        end\n\n        it \"should not change connection when it's already been changed by an on_slave call\" do\n          pending \"rails3: not sure if we need this spec\" if DbCharmer.rails3?\n          User.on_slave do\n            User.on_slave.connection.should_receive(:select_value).and_return(1)\n            User.should_not_receive(:on_db)\n            User.send(meth, :id).should == 1\n          end\n        end\n\n        it \"should not change connection if called in a transaction\" do\n          User.on_db(:user_master).connection.should_receive(:select_value).and_return(1)\n          User.on_slave.connection.should_not_receive(:select_value)\n          User.transaction { User.send(meth, :id).should == 1 }\n        end\n      end\n    end\n  end\n\n  describe \"in data manipulation methods\" do\n    it \"should go to the master by default\" do\n      User.on_db(:user_master).connection.should_receive(:delete)\n      User.delete_all\n    end\n\n    it \"should go to the master even in slave-enabling chain calls\" do\n      User.on_db(:user_master).connection.should_receive(:delete)\n      User.on_slave.delete_all\n    end\n\n    it \"should go to the master even in slave-enabling block calls\" do\n      User.on_db(:user_master).connection.should_receive(:delete)\n      User.on_slave { |u| u.delete_all }\n    end\n  end\n\n  describe \"in instance method\" do\n    describe \"reload\" do\n      it \"should always be done on the master\" do\n        User.delete_all\n        u = User.create\n\n        User.on_db(:user_master).connection.should_receive(:select_all).and_return([{}])\n        User.on_slave.connection.should_not_receive(:select_all)\n\n        User.on_slave { u.reload }\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/active_record/migration/multi_db_migrations_spec.rb",
    "content": "require 'spec_helper'\n\nclass SpecMigration < ActiveRecord::Migration\n  def self.up\n    execute \"UPDATE log_records SET level = 'debug'\"\n  end\n\n  def self.down\n    execute \"UPDATE log_records SET level = 'blah'\"\n  end\nend\n\nclass SpecMultiDbMigration < ActiveRecord::Migration\n  db_magic :connection => :logs\n\n  def self.up\n    execute \"UPDATE log_records SET level = 'debug'\"\n  end\n\n  def self.down\n    execute \"UPDATE log_records SET level = 'blah'\"\n  end\nend\n\nclass SpecMultiDbMigration2 < ActiveRecord::Migration\n  def self.up\n    execute \"UPDATE log_records SET level = 'yo'\"\n    on_db(:logs) { execute \"UPDATE log_records SET level = 'debug'\" }\n  end\n\n  def self.down\n    execute \"UPDATE log_records SET level = 'bar'\"\n    on_db(:logs) { execute \"UPDATE log_records SET level = 'blah'\" }\n  end\nend\n\nclass SpecMultiDbMigration3 < ActiveRecord::Migration\n  db_magic :connection => [:logs, :default]\n\n  def self.up\n    execute \"UPDATE log_records SET level = 'hoho'\"\n  end\n\n  def self.down\n    execute \"UPDATE log_records SET level = 'blah'\"\n  end\nend\n\nclass SpecMultiDbMigration4 < ActiveRecord::Migration\n  db_magic :connections => [:logs, :default]\n\n  def self.up\n    execute \"UPDATE log_records SET level = 'hoho'\"\n  end\n\n  def self.down\n    execute \"UPDATE log_records SET level = 'blah'\"\n  end\nend\n\nclass SpecMultiDbMigration5 < ActiveRecord::Migration\n  db_magic :connections => [:logs, :default]\n\n  def up\n    execute \"UPDATE log_records SET level = 'hoho'\"\n  end\n\n  def down\n    execute \"UPDATE log_records SET level = 'blah'\"\n  end\nend\n\nclass SpecMultiDbMigration6 < ActiveRecord::Migration\n  def change\n    on_db(:logs) do\n      create_table :logs_rails32_test do |t|\n        t.text :t\n      end\n    end\n  end\nend\n\ndescribe \"Multi-db migractions\" do\n  before(:all) do\n    DbCharmer.connections_should_exist = true\n  end\n\n  after(:all) do\n    DbCharmer.connections_should_exist = false\n  end\n\n  def connection_with_name(name)\n    DbCharmer::ConnectionFactory.connect(name).abstract_connection_class.retrieve_connection\n  end\n\n  describe \"w/o any magic calls\" do\n    it \"should send all up requests to the default connection\" do\n      ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'debug'\")\n      SpecMigration.migrate(:up)\n    end\n\n    it \"should send all down requests to the default connection\" do\n      ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'blah'\")\n      SpecMigration.migrate(:down)\n    end\n\n    describe \"after AR::Migration db_magic call\" do\n      it \"should use default migration config\" do\n        ActiveRecord::Migration.db_magic :connection => :logs\n        ActiveRecord::Base.connection.should_not_receive(:execute)\n        connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'debug'\")\n        SpecMigration.migrate(:up)\n        ActiveRecord::Migration.db_magic :connection => :default\n      end\n    end\n  end\n\n  describe \"with db_magic calls\" do\n    it \"should send all up requests to specified connection\" do\n      ActiveRecord::Base.connection.should_not_receive(:execute)\n      connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'debug'\")\n      SpecMultiDbMigration.migrate(:up)\n    end\n\n    it \"should send all down requests to specified connection\" do\n      ActiveRecord::Base.connection.should_not_receive(:execute)\n      connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'blah'\")\n      SpecMultiDbMigration.migrate(:down)\n    end\n\n    describe \"after AR::Migration db_magic call\" do\n      it \"should use specified connection and ignore global migration config\" do\n        ActiveRecord::Migration.db_magic :connection => :slave01\n        ActiveRecord::Base.connection.should_not_receive(:execute)\n        connection_with_name(:slave01).should_not_receive(:execute)\n        connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'debug'\")\n        SpecMultiDbMigration.migrate(:up)\n        ActiveRecord::Migration.db_magic :connection => :default\n      end\n    end\n  end\n\n  describe \"with on_db blocks\" do\n    it \"should send specified up requests to specified connection\" do\n      ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'yo'\")\n      connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'debug'\")\n      SpecMultiDbMigration2.migrate(:up)\n    end\n\n    it \"should send secified down requests to specified connection\" do\n      ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'bar'\")\n      connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'blah'\")\n      SpecMultiDbMigration2.migrate(:down)\n    end\n  end\n\n  describe \"with db_magic calls\" do\n    it \"should send all up requests to specified connection\" do\n      ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'hoho'\")\n      connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'hoho'\")\n      SpecMultiDbMigration3.migrate(:up)\n    end\n\n    it \"should send all down requests to specified connection\" do\n      ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'blah'\")\n      connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'blah'\")\n      SpecMultiDbMigration3.migrate(:down)\n    end\n  end\n\n  describe \"with db_magic calls\" do\n    it \"should send all up requests to specified connection\" do\n      ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'hoho'\")\n      connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'hoho'\")\n      SpecMultiDbMigration4.migrate(:up)\n    end\n\n    it \"should send all down requests to specified connection\" do\n      ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'blah'\")\n      connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'blah'\")\n      SpecMultiDbMigration4.migrate(:down)\n    end\n  end\n\n  if DbCharmer.rails31?\n    describe 'with db_magic calls in instance methods' do\n      it \"should send all up requests to specified connection\" do\n        ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'hoho'\")\n        connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'hoho'\")\n        SpecMultiDbMigration5.migrate(:up)\n      end\n\n      it \"should send all down requests to specified connection\" do\n        ActiveRecord::Base.connection.should_receive(:execute).with(\"UPDATE log_records SET level = 'blah'\")\n        connection_with_name(:logs).should_receive(:execute).with(\"UPDATE log_records SET level = 'blah'\")\n        SpecMultiDbMigration5.migrate(:down)\n      end\n    end\n\n    describe 'with db_magic calls in recorder' do\n      it \"should send all up requests to specified connection\" do\n        ActiveRecord::Base.connection.should_not_receive(:execute)\n        connection_with_name(:logs).should_receive(:execute).with(/CREATE TABLE/)\n        SpecMultiDbMigration6.migrate(:up)\n      end\n\n      it \"should send all down requests to specified connection\" do\n        ActiveRecord::Base.connection.should_not_receive(:execute)\n        connection_with_name(:logs).should_receive(:execute).with(/DROP TABLE/)\n        SpecMultiDbMigration6.migrate(:down)\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/active_record/named_scope/named_scope_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe \"Named scopes\" do\n  fixtures :users, :posts\n\n  before(:all) do\n    Post.switch_connection_to(nil)\n    User.switch_connection_to(nil)\n  end\n\n  describe \"prefixed by on_db\" do\n    it \"should work on the proxy\" do\n      Post.on_db(:slave01).windows_posts.should == Post.windows_posts\n    end\n\n    it \"should actually run queries on the specified db\" do\n      Post.on_db(:slave01).connection.should_receive(:select_all).once.and_return([])\n      Post.on_db(:slave01).windows_posts.all\n      # Post.windows_posts.all\n    end\n\n    it \"should work with long scope chains\" do\n      Post.on_db(:slave01).connection.should_not_receive(:select_all)\n      Post.on_db(:slave01).connection.should_receive(:select_value).and_return(5)\n      Post.on_db(:slave01).windows_posts.count.should == 5\n    end\n\n    it \"should work with associations\" do\n      users(:bill).posts.on_db(:slave01).windows_posts.all.should == users(:bill).posts.windows_posts\n    end\n  end\n\n  describe \"postfixed by on_db\" do\n    it \"should work on the proxy\" do\n      Post.windows_posts.on_db(:slave01).should == Post.windows_posts\n    end\n\n    it \"should actually run queries on the specified db\" do\n      Post.on_db(:slave01).connection.object_id.should_not == Post.connection.object_id\n      Post.on_db(:slave01).connection.should_receive(:select_all).and_return([])\n      Post.windows_posts.on_db(:slave01).all\n      Post.windows_posts.all\n    end\n\n    it \"should work with long scope chains\" do\n      Post.on_db(:slave01).connection.should_not_receive(:select_all)\n      Post.on_db(:slave01).connection.should_receive(:select_value).and_return(5)\n      Post.windows_posts.on_db(:slave01).count.should == 5\n    end\n\n    it \"should work with associations\" do\n      users(:bill).posts.windows_posts.on_db(:slave01).all.should == users(:bill).posts.windows_posts\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/active_record/relation_spec.rb",
    "content": "require 'spec_helper'\n\nif DbCharmer.rails3?\n  describe \"ActiveRecord::Relation for a model with db_magic\" do\n    before do\n      class RelTestModel < ActiveRecord::Base\n        db_magic :connection => nil\n        self.table_name = :users\n      end\n    end\n\n    it \"should be created with correct default connection\" do\n      rel = RelTestModel.on_db(:user_master).where(\"1=1\")\n      rel.db_charmer_connection.object_id.should == RelTestModel.on_db(:user_master).connection.object_id\n    end\n\n    it \"should switch the default connection when on_db called\" do\n      rel = RelTestModel.where(\"1=1\")\n      rel_master = rel.on_db(:user_master)\n      rel_master.db_charmer_connection.object_id.should_not == rel.db_charmer_connection.object_id\n    end\n\n    it \"should keep default connection value when relation is cloned in chained calls\" do\n      rel = RelTestModel.on_db(:user_master).where(\"1=1\")\n      rel.where(\"2=2\").db_charmer_connection.object_id.should == rel.db_charmer_connection.object_id\n    end\n\n    it \"should execute select queries on the default connection\" do\n      rel = RelTestModel.on_db(:user_master).where(\"1=1\")\n\n      RelTestModel.on_db(:user_master).connection.should_receive(:select_all).and_return([])\n      RelTestModel.connection.should_not_receive(:select_all)\n\n      rel.first\n    end\n\n    it \"should execute delete queries on the default connection\" do\n      rel = RelTestModel.on_db(:user_master).where(\"1=1\")\n\n      RelTestModel.on_db(:user_master).connection.should_receive(:delete)\n      RelTestModel.connection.should_not_receive(:delete)\n\n      rel.delete_all\n    end\n\n    it \"should execute update_all queries on the default connection\" do\n      rel = RelTestModel.on_db(:user_master).where(\"1=1\")\n\n      RelTestModel.on_db(:user_master).connection.should_receive(:update)\n      RelTestModel.connection.should_not_receive(:update)\n\n      rel.update_all(\"login = login + 'new'\")\n    end\n\n    it \"should execute update queries on the default connection\" do\n      rel = RelTestModel.on_db(:user_master).where(\"1=1\")\n      user = RelTestModel.create!(:login => 'login')\n\n      RelTestModel.on_db(:user_master).connection.should_receive(:update)\n      RelTestModel.connection.should_not_receive(:update)\n\n      rel.update(user.id, :login => \"foobar\")\n    end\n\n    it \"should return correct connection\" do\n      rel = RelTestModel.on_db(:user_master).where(\"1=1\")\n      rel.connection.object_id.should == rel.db_charmer_connection.object_id\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/connection_factory_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe DbCharmer::ConnectionFactory do\n  context \"in generate_abstract_class method\" do\n    it \"should fail if requested connection config does not exists\" do\n      lambda { DbCharmer::ConnectionFactory.generate_abstract_class('foo') }.should raise_error(ArgumentError)\n    end\n\n    it \"should not fail if requested connection config does not exists and should_exist = false\" do\n      lambda { DbCharmer::ConnectionFactory.generate_abstract_class('foo', false) }.should_not raise_error\n    end\n\n    it \"should fail if requested connection config does not exists and should_exist = true\" do\n      lambda { DbCharmer::ConnectionFactory.generate_abstract_class('foo', true) }.should raise_error(ArgumentError)\n    end\n\n    it \"should generate abstract connection classes\" do\n      klass = DbCharmer::ConnectionFactory.generate_abstract_class('foo', false)\n      klass.superclass.should be(ActiveRecord::Base)\n    end\n\n    it \"should work with weird connection names\" do\n      klass = DbCharmer::ConnectionFactory.generate_abstract_class('foo.bar@baz#blah', false)\n      klass.superclass.should be(ActiveRecord::Base)\n    end\n  end\n\n  context \"in generate_empty_abstract_ar_class method\" do\n    it \"should generate an abstract connection class\" do\n      klass = DbCharmer::ConnectionFactory.generate_empty_abstract_ar_class('::MyFooAbstractClass')\n      klass.superclass.should be(ActiveRecord::Base)\n    end\n  end\n\n  context \"in establish_connection method\" do\n    it \"should generate an abstract class\" do\n      klass = mock('AbstractClass')\n      conn = mock('connection1')\n      klass.stub!(:retrieve_connection).and_return(conn)\n      DbCharmer::ConnectionFactory.should_receive(:generate_abstract_class).and_return(klass)\n      DbCharmer::ConnectionFactory.establish_connection(:foo).should be(conn)\n    end\n\n    it \"should create and return a connection proxy for the abstract class\" do\n      klass = mock('AbstractClass')\n      DbCharmer::ConnectionFactory.should_receive(:generate_abstract_class).and_return(klass)\n      DbCharmer::ConnectionProxy.should_receive(:new).with(klass, :foo)\n      DbCharmer::ConnectionFactory.establish_connection(:foo)\n    end\n  end\n\n  context \"in establish_connection_to_db method\" do\n    it \"should generate an abstract class\" do\n      klass = mock('AbstractClass')\n      conn =  mock('connection2')\n      klass.stub!(:establish_connection)\n      klass.stub!(:retrieve_connection).and_return(conn)\n      DbCharmer::ConnectionFactory.should_receive(:generate_empty_abstract_ar_class).and_return(klass)\n      DbCharmer::ConnectionFactory.establish_connection_to_db(:foo, :username => :foo).should be(conn)\n    end\n\n    it \"should create and return a connection proxy for the abstract class\" do\n      klass = mock('AbstractClass')\n      klass.stub!(:establish_connection)\n      DbCharmer::ConnectionFactory.should_receive(:generate_empty_abstract_ar_class).and_return(klass)\n      DbCharmer::ConnectionProxy.should_receive(:new).with(klass, :foo)\n      DbCharmer::ConnectionFactory.establish_connection_to_db(:foo, :username => :foo)\n    end\n  end\n\n  context \"in connect method\" do\n    before do\n      DbCharmer::ConnectionFactory.reset!\n    end\n\n    it \"should return a connection proxy\" do\n      DbCharmer::ConnectionFactory.connect(:logs).should be_kind_of(ActiveRecord::ConnectionAdapters::AbstractAdapter)\n    end\n\n# should_receive is evil on a singletone classes\n#    it \"should memoize proxies\" do\n#      conn = mock('connection3')\n#      DbCharmer::ConnectionFactory.should_receive(:establish_connection).with('foo', false).once.and_return(conn)\n#      DbCharmer::ConnectionFactory.connect(:foo)\n#      DbCharmer::ConnectionFactory.connect(:foo)\n#    end\n  end\n\n  context \"in connect_to_db method\" do\n    before do\n      DbCharmer::ConnectionFactory.reset!\n      @conf = {\n        :adapter => 'mysql',\n        :username => \"db_charmer_ro\",\n        :database => \"db_charmer_sandbox_test\",\n        :connection_name => 'sanbox_ro'\n      }\n    end\n\n    it \"should return a connection proxy\" do\n      DbCharmer::ConnectionFactory.connect_to_db(@conf[:connection_name], @conf).should be_kind_of(ActiveRecord::ConnectionAdapters::AbstractAdapter)\n    end\n\n# should_receive is evil on a singletone classes\n#    it \"should memoize proxies\" do\n#      conn = mock('connection4')\n#      DbCharmer::ConnectionFactory.should_receive(:establish_connection_to_db).with(@conf[:connection_name], @conf).once.and_return(conn)\n#      DbCharmer::ConnectionFactory.connect_to_db(@conf[:connection_name], @conf)\n#      DbCharmer::ConnectionFactory.connect_to_db(@conf[:connection_name], @conf)\n#    end\n  end\n\nend\n"
  },
  {
    "path": "test-project/spec/unit/connection_proxy_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe DbCharmer::ConnectionProxy do\n  before(:each) do\n    class ProxyTest; end\n    @conn = mock('connection')\n    @proxy = DbCharmer::ConnectionProxy.new(ProxyTest, :foo)\n  end\n\n  it \"should retrieve connection from an underlying class\" do\n    ProxyTest.should_receive(:retrieve_connection).and_return(@conn)\n    @proxy.inspect\n  end\n\n  it \"should be a blankslate for the connection\" do\n    ProxyTest.stub!(:retrieve_connection).and_return(@conn)\n    @proxy.should be(@conn)\n  end\n\n  it \"should proxy methods with a block parameter\" do\n    module MockConnection\n      def self.foo\n        raise \"No block given!\" unless block_given?\n        yield\n      end\n    end\n    ProxyTest.stub!(:retrieve_connection).and_return(MockConnection)\n    res = @proxy.foo { :foo }\n    res.should == :foo\n  end\n\n  it \"should proxy all calls to the underlying class connections\" do\n    ProxyTest.stub!(:retrieve_connection).and_return(@conn)\n    @conn.should_receive(:foo)\n    @proxy.foo\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/db_charmer_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe DbCharmer do\n  after do\n    DbCharmer.current_controller = nil\n    DbCharmer.connections_should_exist = false\n  end\n\n  it \"should define version constants\" do\n    DbCharmer::Version::STRING.should match(/^\\d+\\.\\d+\\.\\d+/)\n  end\n\n  it \"should have connections_should_exist accessors\" do\n    DbCharmer.connections_should_exist.should_not be_nil\n    DbCharmer.connections_should_exist = :foo\n    DbCharmer.connections_should_exist.should == :foo\n  end\n\n  it \"should have connections_should_exist? method\" do\n    DbCharmer.connections_should_exist = true\n    DbCharmer.connections_should_exist?.should be_true\n    DbCharmer.connections_should_exist = false\n    DbCharmer.connections_should_exist?.should be_false\n    DbCharmer.connections_should_exist = \"shit\"\n    DbCharmer.connections_should_exist?.should be_true\n    DbCharmer.connections_should_exist = nil\n    DbCharmer.connections_should_exist?.should be_false\n  end\n\n  it \"should have current_controller accessors\" do\n    DbCharmer.respond_to?(:current_controller).should be_true\n    DbCharmer.current_controller = :foo\n    DbCharmer.current_controller.should == :foo\n    DbCharmer.current_controller = nil\n  end\n\n  context \"in force_slave_reads? method\" do\n    it \"should return true if force_slave_reads=true\" do\n      DbCharmer.force_slave_reads?.should be_false\n\n      DbCharmer.force_slave_reads do\n        DbCharmer.force_slave_reads?.should be_true\n      end\n\n      DbCharmer.force_slave_reads?.should be_false\n    end\n\n    it \"should return false if no controller defined and global force_slave_reads=false\" do\n      DbCharmer.current_controller = nil\n      DbCharmer.force_slave_reads?.should be_false\n    end\n\n    it \"should consult with the controller about forcing slave reads if possible\" do\n      DbCharmer.current_controller = mock(\"controller\")\n\n      DbCharmer.current_controller.should_receive(:force_slave_reads?).and_return(true)\n      DbCharmer.force_slave_reads?.should be_true\n\n      DbCharmer.current_controller.should_receive(:force_slave_reads?).and_return(false)\n      DbCharmer.force_slave_reads?.should be_false\n    end\n  end\n\n  context \"in with_controller method\" do\n    it \"should fail if no block given\" do\n      lambda { DbCharmer.with_controller(:foo) }.should raise_error(ArgumentError)\n    end\n\n    it \"should switch controller while running the block\" do\n      DbCharmer.current_controller = nil\n      DbCharmer.current_controller.should be_nil\n\n      DbCharmer.with_controller(:foo) do\n        DbCharmer.current_controller.should == :foo\n      end\n\n      DbCharmer.current_controller.should be_nil\n    end\n\n    it \"should ensure current controller is reverted to nil in case of errors\" do\n      lambda {\n        DbCharmer.with_controller(:foo) { raise \"fuck\" }\n      }.should raise_error\n      DbCharmer.current_controller.should be_nil\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/multi_db_proxy_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe \"ActiveRecord model with db_magic\" do\n  before do\n    class Blah < ActiveRecord::Base\n      self.table_name = :posts\n      db_magic :connection => nil\n    end\n  end\n\n  describe \"(instance)\" do\n    before do\n      @blah = Blah.new\n    end\n\n    describe \"in on_db method\" do\n      describe \"with a block\" do\n        it \"should switch connection to specified one and yield the block\" do\n          Blah.db_charmer_connection_proxy.should be_nil\n          @blah.on_db(:logs) do\n            Blah.db_charmer_connection_proxy.should_not be_nil\n          end\n        end\n\n        it \"should switch connection back after the block finished its work\" do\n          Blah.db_charmer_connection_proxy.should be_nil\n          @blah.on_db(:logs) {}\n          Blah.db_charmer_connection_proxy.should be_nil\n        end\n\n        it \"should manage connection level values\" do\n          Blah.db_charmer_connection_level.should == 0\n          @blah.on_db(:logs) do |m|\n            m.class.db_charmer_connection_level.should == 1\n          end\n          Blah.db_charmer_connection_level.should == 0\n        end\n      end\n\n      describe \"as a chain call\" do\n        it \"should switch connection for all chained calls\" do\n          Blah.db_charmer_connection_proxy.should be_nil\n          @blah.on_db(:logs).should_not be_nil\n        end\n\n        it \"should switch connection for non-chained calls\" do\n          Blah.db_charmer_connection_proxy.should be_nil\n          @blah.on_db(:logs).to_s\n          Blah.db_charmer_connection_proxy.should be_nil\n        end\n\n        it \"should restore connection\" do\n          User.first\n          User.connection.object_id.should == User.on_master.connection.object_id\n\n          User.on_db(:slave01).first\n          User.connection.object_id.should == User.on_master.connection.object_id\n        end\n\n        it \"should restore connection after error\" do\n          pending \"Disabled in RSpec prior to version 2 because of lack of .any_instance support\" unless Object.respond_to?(:any_instance)\n\n          User.on_db(:slave01).first\n          User.first\n          ActiveRecord::Base.connection_handler.clear_all_connections!\n          ActiveRecord::ConnectionAdapters::MysqlAdapter.any_instance.stub(:connect) { raise Mysql::Error, 'Connection error' }\n          expect { User.on_db(:slave01).first }.to raise_error(Mysql::Error)\n          ActiveRecord::ConnectionAdapters::MysqlAdapter.any_instance.unstub(:connect)\n          User.connection.connection_name.should == User.on_master.connection.connection_name\n        end\n      end\n    end\n  end\n\n  describe \"(class)\" do\n    describe \"in on_db method\" do\n      describe \"with a block\" do\n        it \"should switch connection to specified one and yield the block\" do\n          Blah.db_charmer_connection_proxy.should be_nil\n          Blah.on_db(:logs) do\n            Blah.db_charmer_connection_proxy.should_not be_nil\n          end\n        end\n\n        it \"should switch connection back after the block finished its work\" do\n          Blah.db_charmer_connection_proxy.should be_nil\n          Blah.on_db(:logs) {}\n          Blah.db_charmer_connection_proxy.should be_nil\n        end\n\n        it \"should manage connection level values\" do\n          Blah.db_charmer_connection_level.should == 0\n          Blah.on_db(:logs) do |m|\n            m.db_charmer_connection_level.should == 1\n          end\n          Blah.db_charmer_connection_level.should == 0\n        end\n      end\n\n      describe \"as a chain call\" do\n        it \"should switch connection for all chained calls\" do\n          Blah.db_charmer_connection_proxy.should be_nil\n          Blah.on_db(:logs).should_not be_nil\n        end\n\n        it \"should switch connection for non-chained calls\" do\n          Blah.db_charmer_connection_proxy.should be_nil\n          Blah.on_db(:logs).to_s\n          Blah.db_charmer_connection_proxy.should be_nil\n        end\n      end\n    end\n\n    describe \"in on_slave method\" do\n      before do\n        Blah.db_magic :slaves => [ :slave01 ]\n      end\n\n      it \"should use one tof the model's slaves if no slave given\" do\n        Blah.on_slave.db_charmer_connection_proxy.object_id.should == Blah.coerce_to_connection_proxy(:slave01).object_id\n      end\n\n      it \"should use given slave\" do\n        Blah.on_slave(:logs).db_charmer_connection_proxy.object_id.should == Blah.coerce_to_connection_proxy(:logs).object_id\n      end\n\n      it 'should support block calls' do\n        Blah.on_slave do |m|\n          m.db_charmer_connection_proxy.object_id.should == Blah.coerce_to_connection_proxy(:slave01).object_id\n        end\n      end\n    end\n\n    describe \"in on_master method\" do\n      before do\n        Blah.db_magic :slaves => [ :slave01 ]\n      end\n\n      it \"should run queries on the master\" do\n        Blah.on_master.db_charmer_connection_proxy.should be_nil\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test-project/spec/unit/with_remapped_databases_spec.rb",
    "content": "require 'spec_helper'\n\ndescribe \"DbCharmer#with_remapped_databases\" do\n  before(:all) do\n    DbCharmer.connections_should_exist = false\n  end\n\n  let(:logs_connection) { DbCharmer::ConnectionFactory.connect(:logs) }\n  let(:slave_connection) { DbCharmer::ConnectionFactory.connect(:slave01) }\n  let(:master_connection) { Avatar.connection }\n\n  before :each do\n    class User < ActiveRecord::Base\n      db_magic :connection => :slave01\n    end\n  end\n\n  def should_have_connection(model_class, connection)\n    model_class.connection.object_id.should == connection.object_id\n  end\n\n  it \"should remap the right connection\" do\n    should_have_connection(LogRecord, logs_connection)\n    DbCharmer.with_remapped_databases(:logs => :slave01) do\n      should_have_connection(LogRecord, slave_connection)\n    end\n    should_have_connection(LogRecord, logs_connection)\n  end\n\n  it \"should not remap other connections\" do\n    should_have_connection(Avatar, master_connection)\n    should_have_connection(User, slave_connection)\n    DbCharmer.with_remapped_databases(:logs => :slave01) do\n      should_have_connection(Avatar, master_connection)\n      should_have_connection(User, slave_connection)\n    end\n    should_have_connection(Avatar, master_connection)\n    should_have_connection(User, slave_connection)\n  end\n\n  it \"should allow remapping multiple databases\" do\n    should_have_connection(Avatar, master_connection)\n    should_have_connection(LogRecord, logs_connection)\n    DbCharmer.with_remapped_databases(:master => :logs, :logs => :slave01) do\n      should_have_connection(Avatar, logs_connection)\n      should_have_connection(LogRecord, slave_connection)\n    end\n    should_have_connection(Avatar, master_connection)\n    should_have_connection(LogRecord, logs_connection)\n  end\n\n  it \"should remap the master connection when asked to, but not other connections\" do\n    should_have_connection(Avatar, master_connection)\n    should_have_connection(User, slave_connection)\n    should_have_connection(LogRecord, logs_connection)\n    DbCharmer.with_remapped_databases(:master => :slave01) do\n      should_have_connection(Avatar, slave_connection)\n      should_have_connection(User, slave_connection)\n      should_have_connection(LogRecord, logs_connection)\n    end\n    should_have_connection(Avatar, master_connection)\n    should_have_connection(User, slave_connection)\n    should_have_connection(LogRecord, logs_connection)\n  end\n\n  it \"should not override connections that are explicitly specified\" do\n    DbCharmer.with_remapped_databases(:logs => :slave01) do\n      should_have_connection(LogRecord, slave_connection)\n      should_have_connection(LogRecord.on_db(:master), master_connection)\n      LogRecord.on_db(:master) do\n        should_have_connection(LogRecord, master_connection)\n      end\n      should_have_connection(LogRecord.on_db(:logs), logs_connection)\n      LogRecord.on_db(:logs) do\n        should_have_connection(LogRecord, logs_connection)\n      end\n      should_have_connection(LogRecord, slave_connection)\n    end\n  end\n\n  it \"should successfully run selects on the right database\" do\n    # We need this call to make sure rails would fetch columns info from the logs server before we mess its connection up\n    LogRecord.all\n\n    # Remap LogRecord connection to slave01 and make sure selects would go there (even though we do not have the table there)\n    DbCharmer.with_remapped_databases(:logs => :slave01) do\n      logs_connection.should_not_receive(:select_all)\n      slave_connection.should_receive(:select_all).and_return([])\n      stub_columns_for_rails31 slave_connection\n      LogRecord.all.should be_empty\n    end\n  end\n\n  def unhijack!(klass)\n    if klass.respond_to?(:connection_with_magic)\n      klass.class_eval <<-END\n        class << self\n          undef_method(:connection_with_magic)\n          alias_method(:connection, :connection_without_magic)\n          undef_method(:connection_without_magic)\n\n          undef_method(:connection_pool_with_magic)\n          alias_method(:connection_pool, :connection_pool_without_magic)\n          undef_method(:connection_pool_without_magic)\n        end\n      END\n    end\n\n    raise \"Unable to unhijack #{klass.name}\" if klass.respond_to?(:connection_with_magic)\n  end\n\n  it \"should hijack connections only when necessary\" do\n    unhijack!(Category)\n\n    Category.respond_to?(:connection_with_magic).should be_false\n    DbCharmer.with_remapped_databases(:logs => :slave01) do\n      Category.respond_to?(:connection_with_magic).should be_false\n    end\n    Category.respond_to?(:connection_with_magic).should be_false\n\n    DbCharmer.with_remapped_databases(:master => :slave01) do\n      Category.respond_to?(:connection_with_magic).should be_true\n      should_have_connection(Category, slave_connection)\n    end\n  end\nend\n"
  },
  {
    "path": "test-project-2.x/Gemfile",
    "content": "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-rails', '1.3.4'\n\n# Load DbCharmer as a gem\ngem 'db-charmer', :path => '..', :require => 'db_charmer'\n"
  },
  {
    "path": "test-project-2.x/Rakefile",
    "content": "# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.\n\nrequire(File.join(File.dirname(__FILE__), 'config', 'boot'))\n\nrequire 'rake'\nrequire 'rake/testtask'\nrequire 'rake/rdoctask'\n\nrequire 'tasks/rails'\n"
  },
  {
    "path": "test-project-2.x/config/boot.rb",
    "content": "# We only have test environment here\nENV['RAILS_ENV'] = 'test'\n\n# Don't change this file!\n# Configure your app in config/environment.rb and config/environments/*.rb\n\nRAILS_ROOT = \"#{File.dirname(__FILE__)}/..\" unless defined?(RAILS_ROOT)\n\nmodule Rails\n  class << self\n    def boot!\n      unless booted?\n        preinitialize\n        pick_boot.run\n      end\n    end\n\n    def booted?\n      defined? Rails::Initializer\n    end\n\n    def pick_boot\n      (vendor_rails? ? VendorBoot : GemBoot).new\n    end\n\n    def vendor_rails?\n      File.exist?(\"#{RAILS_ROOT}/vendor/rails\")\n    end\n\n    def preinitialize\n      load(preinitializer_path) if File.exist?(preinitializer_path)\n    end\n\n    def preinitializer_path\n      \"#{RAILS_ROOT}/config/preinitializer.rb\"\n    end\n  end\n\n  class Boot\n    def run\n      load_initializer\n\n      Rails::Initializer.class_eval do\n        def load_gems\n          @bundler_loaded ||= Bundler.require :default, Rails.env\n        end\n      end\n\n      Rails::Initializer.run(:set_load_path)\n    end\n  end\n\n  class VendorBoot < Boot\n    def load_initializer\n      require \"#{RAILS_ROOT}/vendor/rails/railties/lib/initializer\"\n      Rails::Initializer.run(:install_gem_spec_stubs)\n      Rails::GemDependency.add_frozen_gem_path\n    end\n  end\n\n  class GemBoot < Boot\n    def load_initializer\n      self.class.load_rubygems\n      load_rails_gem\n      require 'initializer'\n    end\n\n    def load_rails_gem\n      if version = self.class.gem_version\n        gem 'rails', version\n      else\n        gem 'rails'\n      end\n    rescue Gem::LoadError => load_error\n      $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)\n      exit 1\n    end\n\n    class << self\n      def rubygems_version\n        Gem::RubyGemsVersion rescue nil\n      end\n\n      def gem_version\n        if defined? RAILS_GEM_VERSION\n          RAILS_GEM_VERSION\n        elsif ENV.include?('RAILS_GEM_VERSION')\n          ENV['RAILS_GEM_VERSION']\n        else\n          parse_gem_version(read_environment_rb)\n        end\n      end\n\n      def load_rubygems\n        require 'rubygems'\n        min_version = '1.3.1'\n        unless rubygems_version >= min_version\n          $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)\n          exit 1\n        end\n\n      rescue LoadError\n        $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)\n        exit 1\n      end\n\n      def parse_gem_version(text)\n        $1 if text =~ /^[^#]*RAILS_GEM_VERSION\\s*=\\s*[\"']([!~<>=]*\\s*[\\d.]+)[\"']/\n      end\n\n      private\n        def read_environment_rb\n          File.read(\"#{RAILS_ROOT}/config/environment.rb\")\n        end\n    end\n  end\nend\n\n# All that for this:\nRails.boot!\n"
  },
  {
    "path": "test-project-2.x/config/database.yml.example",
    "content": "common: &common\n  adapter: mysql\n  encoding: utf8\n  reconnect: false\n  pool: 1\n  username: root\n  password:\n\n#----------------------------------------------------------------\ntest:\n  <<: *common\n  database: db_charmer_sandbox_test\n\n  # logs database\n  logs:\n    <<: *common\n    database: db_charmer_logs_test\n\n  # slave database\n  slave01:\n    <<: *common\n    username: db_charmer_ro\n    database: db_charmer_sandbox_test\n\n  user_master:\n    <<: *common\n    database: db_charmer_sandbox_test\n\n  # shard mapping db\n  social_shard_info:\n    <<: *common\n    database: db_charmer_sandbox_test\n\n  # for migrations only\n  social_shard01:\n    <<: *common\n    database: db_charmer_events_test_shard01\n\n  # for migrations only\n  social_shard02:\n    <<: *common\n    database: db_charmer_events_test_shard02\n\n#----------------------------------------------------------------\ntest22:\n  <<: *common\n  database: db_charmer_sandbox22_test\n\n  # logs database\n  logs:\n    <<: *common\n    database: db_charmer_logs22_test\n\n  # slave database\n  slave01:\n    <<: *common\n    username: db_charmer_ro\n    database: db_charmer_sandbox22_test\n\n  user_master:\n    <<: *common\n    database: db_charmer_sandbox22_test\n\n  # shard mapping db\n  social_shard_info:\n    <<: *common\n    database: db_charmer_sandbox22_test\n\n  # for migrations only\n  social_shard01:\n    <<: *common\n    database: db_charmer_events22_test_shard01\n\n  # for migrations only\n  social_shard02:\n    <<: *common\n    database: db_charmer_events22_test_shard02\n"
  },
  {
    "path": "test-project-2.x/config/environment.rb",
    "content": "# Specifies gem version of Rails to use when vendor/rails is not present\nRAILS_GEM_VERSION = '2.3.18' unless defined? RAILS_GEM_VERSION\n\n# Bootstrap the Rails environment, frameworks, and default configuration\nrequire File.join(File.dirname(__FILE__), 'boot')\n\nRails::Initializer.run do |config|\n  config.time_zone = 'UTC'\nend\n\n"
  },
  {
    "path": "test-project-2.x/config/environments/test.rb",
    "content": "# Settings specified here will take precedence over those in config/environment.rb\n\n# The test environment is used exclusively to run your application's\n# test suite.  You never need to work with it otherwise.  Remember that\n# your test database is \"scratch space\" for the test suite and is wiped\n# and recreated between test runs.  Don't rely on the data there!\nconfig.cache_classes = true\n\n# Log error messages when you accidentally call methods on nil.\nconfig.whiny_nils = true\n\n# Show full error reports and disable caching\nconfig.action_controller.consider_all_requests_local = true\nconfig.action_controller.perform_caching             = false\nconfig.action_view.cache_template_loading            = true\n\n# Disable request forgery protection in test environment\nconfig.action_controller.allow_forgery_protection    = false\n\n# Tell Action Mailer not to deliver emails to the real world.\n# The :test delivery method accumulates sent emails in the\n# ActionMailer::Base.deliveries array.\nconfig.action_mailer.delivery_method = :test\n\n# Use SQL instead of Active Record's schema dumper when creating the test database.\n# This is necessary if your schema can't be completely dumped by the schema dumper,\n# like if you have constraints or database-specific column types\n# config.active_record.schema_format = :sql\n"
  },
  {
    "path": "test-project-2.x/config/initializers/backtrace_silencers.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.\n# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }\n\n# You can also remove all the silencers if you're trying do debug a problem that might steem from framework code.\n# Rails.backtrace_cleaner.remove_silencers!"
  },
  {
    "path": "test-project-2.x/config/initializers/db_charmer.rb",
    "content": "DbCharmer.connections_should_exist = false # Since we are not in production\nDbCharmer.enable_controller_magic!"
  },
  {
    "path": "test-project-2.x/config/initializers/inflections.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules using the following format \n# (all these examples are active by default):\n# ActiveSupport::Inflector.inflections do |inflect|\n#   inflect.plural /^(ox)$/i, '\\1en'\n#   inflect.singular /^(ox)en/i, '\\1'\n#   inflect.irregular 'person', 'people'\n#   inflect.uncountable %w( fish sheep )\n# end\n"
  },
  {
    "path": "test-project-2.x/config/initializers/mime_types.rb",
    "content": "# 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::Type.register \"text/richtext\", :rtf\n# Mime::Type.register_alias \"text/html\", :iphone\n"
  },
  {
    "path": "test-project-2.x/config/initializers/new_rails_defaults.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# These settings change the behavior of Rails 2 apps and will be defaults\n# for Rails 3. You can remove this initializer when Rails 3 is released.\n\nif defined?(ActiveRecord)\n  # Include Active Record class name as root for JSON serialized output.\n  ActiveRecord::Base.include_root_in_json = true\n\n  # Store the full class name (including module namespace) in STI type column.\n  ActiveRecord::Base.store_full_sti_class = true\nend\n\n# Use ISO 8601 format for JSON serialized times and dates.\nActiveSupport.use_standard_json_time_format = true\n\n# Don't escape HTML entities in JSON, leave that for the #json_escape helper.\n# if you're including raw json in an HTML page.\nActiveSupport.escape_html_entities_in_json = false"
  },
  {
    "path": "test-project-2.x/config/initializers/session_store.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Your secret key for verifying cookie session data integrity.\n# If you change this key, all old sessions will become invalid!\n# Make sure the secret is at least 30 characters and all random, \n# no regular words or you'll be exposed to dictionary attacks.\nActionController::Base.session = {\n  :key         => '_db_charmer_sandbox_session',\n  :secret      => '9b67feed7aa8a2741d9f0ac6efde543d726f7a017c8a635346be733f287fd479fbd8521c1e8a06e91af7920de1fb50b942bdf24b6ecee1569ed947c13f6697af'\n}\n\n# Use the database for sessions instead of the cookie-based default,\n# which shouldn't be used to store highly confidential information\n# (create the session table with \"rake db:sessions:create\")\n# ActionController::Base.session_store = :active_record_store\n"
  },
  {
    "path": "test-project-2.x/config/initializers/sharding.rb",
    "content": "# Range-based shards for testing\n\nTEXTS_SHARDING_RANGES = {\n  0...100   => :shard1,\n  100..200  => :shard2,\n  :default  => :shard3\n}\n\nDbCharmer::Sharding.register_connection(\n  :name => :texts,\n  :method => :range,\n  :ranges => TEXTS_SHARDING_RANGES\n)\n\n#------------------------------------------------\n# Db blocks map sharding for testing\n\nSOCIAL_SHARDING = DbCharmer::Sharding.register_connection(\n  :name => :social,\n  :method => :db_block_map,\n  :block_size => 10,\n  :map_table => :event_shards_map,\n  :shards_table => :event_shards_info,\n  :connection => :social_shard_info\n)\n"
  },
  {
    "path": "test-project-2.x/config/locales/en.yml",
    "content": "# Sample localization file for English. Add more files in this directory for other locales.\n# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.\n\nen:\n  hello: \"Hello world\""
  },
  {
    "path": "test-project-2.x/config/preinitializer.rb",
    "content": "begin\n  require \"rubygems\"\n  require \"bundler\"\nrescue LoadError\n  raise \"Could not load the bundler gem. Install it with `gem install bundler`.\"\nend\n\nif Gem::Version.new(Bundler::VERSION) <= Gem::Version.new(\"0.9.24\")\n  raise RuntimeError, \"Your bundler version is too old for Rails 2.3.\" +\n   \"Run `gem install bundler` to upgrade.\"\nend\n\nbegin\n  # Set up load paths for all bundled gems\n  ENV[\"BUNDLE_GEMFILE\"] = File.expand_path(\"../../Gemfile\", __FILE__)\n  Bundler.setup\nrescue Bundler::GemNotFound\n  raise RuntimeError, \"Bundler couldn't find some gems.\" +\n    \"Did you run `bundle install`?\"\nend\n"
  },
  {
    "path": "test-project-2.x/config/routes.rb",
    "content": "ActionController::Routing::Routes.draw do |map|\n  # Resource routes\n  map.resources :posts\n  map.resources :cars\n\n  # Install the default routes as the lowest priority.\n  # Note: These default routes make all actions in every controller accessible via GET requests. You should\n  # consider removing or commenting them out if you're using named routes and resources.\n  map.connect ':controller/:action/:id'\n  map.connect ':controller/:action/:id.:format'\nend\n"
  },
  {
    "path": "test-project-2.x/script/console",
    "content": "#!/usr/bin/env ruby\nrequire File.dirname(__FILE__) + '/../config/boot'\nrequire 'commands/console'\n"
  },
  {
    "path": "test-project-2.x/spec/spec.opts",
    "content": "--colour\n--format specdoc\n"
  },
  {
    "path": "test-project-2.x/spec/spec_helper.rb",
    "content": "# This file is copied to ~/spec when you run 'ruby script/generate rspec'\n# from the project root directory.\nENV[\"RAILS_ENV\"] = 'test'\nrequire File.expand_path(File.join(File.dirname(__FILE__),'..','config','environment'))\nrequire 'spec/autorun'\nrequire 'spec/rails'\n\n# Requires supporting files with custom matchers and macros, etc,\n# in ./support/ and its subdirectories.\nDir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}\n\nSpec::Runner.configure do |config|\n  # If you're not using ActiveRecord you should remove these\n  # lines, delete config/database.yml and disable :active_record\n  # in your config/boot.rb\n  config.use_transactional_fixtures = false\n  config.use_instantiated_fixtures  = false\n  config.fixture_path = RAILS_ROOT + '/spec/fixtures/'\n\n  # == Fixtures\n  #\n  # You can declare fixtures for each example_group like this:\n  #   describe \"....\" do\n  #     fixtures :table_a, :table_b\n  #\n  # Alternatively, if you prefer to declare them only once, you can\n  # do so right here. Just uncomment the next line and replace the fixture\n  # names with your fixtures.\n  #\n  # config.global_fixtures = :table_a, :table_b\n  #\n  # If you declare global fixtures, be aware that they will be declared\n  # for all of your examples, even those that don't use them.\n  #\n  # You can also declare which fixtures to use (for example fixtures for test/fixtures):\n  #\n  # config.fixture_path = RAILS_ROOT + '/spec/fixtures/'\n  #\n  # == Mock Framework\n  #\n  # RSpec uses its own mocking framework by default. If you prefer to\n  # use mocha, flexmock or RR, uncomment the appropriate line:\n  #\n  # config.mock_with :mocha\n  # config.mock_with :flexmock\n  # config.mock_with :rr\n  #\n  # == Notes\n  #\n  # For more information take a look at Spec::Runner::Configuration and Spec::Runner\nend\n"
  }
]