connection_manager 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. data/.gitignore +2 -1
  2. data/Gemfile +0 -1
  3. data/LICENSE.txt +1 -1
  4. data/README.md +115 -55
  5. data/Rakefile +2 -0
  6. data/connection_manager.gemspec +9 -3
  7. data/lib/connection_manager/connection_builder.rb +81 -0
  8. data/lib/connection_manager/connection_manager_railtie.rb +4 -3
  9. data/lib/connection_manager/helpers/abstract_adapter_helper.rb +40 -0
  10. data/lib/connection_manager/helpers/connection_helpers.rb +105 -0
  11. data/lib/connection_manager/{cross_schema_patch.rb → patches/cross_schema_patch.rb} +2 -3
  12. data/lib/connection_manager/replication.rb +165 -0
  13. data/lib/connection_manager/shards.rb +25 -0
  14. data/lib/connection_manager/using.rb +95 -0
  15. data/lib/connection_manager/version.rb +1 -1
  16. data/lib/connection_manager.rb +19 -8
  17. data/spec/factories.rb +7 -11
  18. data/spec/helpers/database_spec_helper.rb +52 -41
  19. data/spec/helpers/models_spec_helper.rb +23 -0
  20. data/spec/jdbcmysql_database.yml +55 -0
  21. data/spec/lib/connection_builder_spec.rb +29 -0
  22. data/spec/lib/connection_helpers_spec.rb +74 -0
  23. data/spec/lib/replication_spec.rb +134 -0
  24. data/spec/lib/shards_spec.rb +40 -0
  25. data/spec/lib/using_spec.rb +77 -0
  26. data/spec/mysql2_database.yml +28 -2
  27. data/spec/spec_helper.rb +20 -6
  28. metadata +42 -39
  29. data/Gemfile.lock +0 -56
  30. data/lib/connection_manager/associations.rb +0 -28
  31. data/lib/connection_manager/connections.rb +0 -124
  32. data/lib/connection_manager/method_recorder.rb +0 -57
  33. data/lib/connection_manager/secondary_connection_builder.rb +0 -180
  34. data/spec/integration/secondary_connection_builder_spec.rb +0 -115
  35. data/spec/lib/associations_spec.rb +0 -30
  36. data/spec/lib/connections_spec.rb +0 -92
  37. data/spec/lib/method_recorder_spec.rb +0 -43
  38. data/spec/lib/secondary_connection_builder_spec.rb +0 -77
data/.gitignore CHANGED
@@ -3,4 +3,5 @@ pkg/*
3
3
  *.sqlite3
4
4
  .bundle
5
5
  .DS_Store
6
-
6
+ log/*
7
+ Gemfile.lock
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in rails-connection_manager.gemspec
4
3
  gemspec
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Joshua T. Mckinney
1
+ Copyright (c) 2011-2012 Joshua T. Mckinney
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,12 +1,22 @@
1
1
  # ConnectionManager
2
- Replication and Multi-Database ActiveRecord add on.
2
+ Multi-Database, Replication and Sharding for ActiveRecord.
3
3
 
4
- ## Goals
5
- * Take the lib I've been using finally make something out of it ;)
6
- * Use connection classes, instead of establish_connection on every model, to ensure connection pooling
7
- * Use non-adapter specific code.
8
- * Use the default database.yml as single point for all database configurations (no extra .yml files)
9
- * When slave objects are used in html helpers like link_to and form_for the created urls match those created using a master object
4
+ ## Background
5
+ ActiveRecord, for quite some time now, has supported multiple database connections
6
+ through the use of #establish_connection and connection classes [more info](http://api.rubyonrails.org/classes/ActiveRecord/Base.html)
7
+ Multiple databases, replication and shards can be implemented directly in rails without
8
+ patching, but a gem helps to reduce redundant code and ensure consistency.
9
+ ConnectionManager replaces all the connection classes and subclasses required
10
+ for multiple database support in Rails with a few class methods and simple
11
+ database.yml configuration. Since ConnectionManager does not alter
12
+ ActiveRecord's connection pool, thread safety is not a concern.
13
+
14
+ ## Upgrading to 0.3
15
+
16
+ 0.3 is a complete overhaul and will cause compatibility issues for folks who upgrade using the previous replication setup.
17
+ Fortunately, for most folks the only change they have to do is specify the their slaves
18
+ and masters in the database.yml and set build_connection_class to true to have
19
+ ActiveRecord build their connection classes. See the example database.yml below.
10
20
 
11
21
  ## Installation
12
22
 
@@ -16,119 +26,169 @@ ConnectionManager is available through [Rubygems](https://rubygems.org/gems/conn
16
26
 
17
27
  ## Rails 3 setup (No Rails 2 at this time)
18
28
 
19
- ConnectionManager assumes the primary connection for the model is the master. For standard
20
- models using the default connection this means the main Rails database connection is the master.
29
+ Add connection_manager to you gemfile:
30
+
31
+ gem 'connection_manager'
21
32
 
22
- Example database.yml
33
+ Run bundle install:
34
+
35
+ bundle install
36
+
37
+ ### Example database.yml
23
38
 
24
39
  common: &common
25
40
  adapter: mysql2
26
41
  username: root
27
42
  password: *****
28
- database_timezone: local
29
- pool: 100
43
+ pool: 20
30
44
  connect_timeout: 20
31
45
  timeout: 900
32
46
  socket: /tmp/mysql.sock
47
+ build_connection_class: true
33
48
 
34
49
  development:
35
50
  <<: *common
36
51
  database: test_app
52
+ slaves: [slave_1_test_app_development, slave_2_test_app_development]
37
53
 
38
54
  slave_1_test_app_development:
39
55
  <<: *common
40
56
  database: test_app
57
+ readonly: true
41
58
 
42
59
  slave_2_test_app_development:
43
60
  <<: *common
44
61
  database: test_app
62
+ readonly: true
45
63
 
46
64
  user_data_development
47
65
  <<: *common
48
66
  database: user_data
67
+ slaves: [slave_1_user_data_development, slave_2_user_data_development]
49
68
 
50
69
  slave_1_user_data_development
51
70
  <<: *common
52
71
  database: user_data
72
+ readonly: true
53
73
 
54
74
  slave_2_user_data_development
55
75
  <<: *common
56
76
  database: user_data
77
+ readonly: true
57
78
 
58
79
  In the above database.yml the Master databases are listed as "development" and "user_data_development".
59
- As you can see the replication database name follow a strict standard for the connection names.
60
- For slave_1_test_app_development, "slave" is the name of the replication, "1" is the count, "test_app"
61
- is the databases name and finally the "development" is the environment. (Of course in your database.yml
62
- each slave would have a different connection to is replication :)
80
+ Replication databases are defined as normally connections and are added to the 'replications:' option for
81
+ their master. The readonly option ensures all ActiveRecord objects returned from this connection are ALWAYS readonly.
63
82
 
64
83
 
65
- ## Multiple Databases
84
+ ## Building Connection Classes
66
85
 
67
- At startup ConnectionManager builds connection classes to ConnectionManager::Connections
68
- using the connections described in your database.yml based on the current rails environment.
86
+ ### Manually
87
+ ConnectionManager provides establish_managed_connection for build connection
88
+ classes and connection to multiple databases.
69
89
 
70
- You can use a different master by having the model inherit from one of your ConnectionManager::Connections.
90
+ class MyConnection < ActiveRecord::Base
91
+ establish_managed_connection("my_database_#{Rails.env}", :readonly => true)
92
+ end
93
+
94
+ class User < MyConnection
95
+ end
96
+
97
+ MyConnection => MyConnection(abstract)
98
+ @user = User.first
99
+ @user.readonly? => true
71
100
 
72
- To view your ConnectionManager::Connections, at the Rails console type:
101
+ The establish_managed_connection method, runs establish_connection with the supplied
102
+ database.yml key, sets abstract_class to true, and (since :readonly is set to true) ensures
103
+ all ActiveRecord objects build using this connection class are readonly. If readonly is set
104
+ to true in the database.yml, passing the readonly option is not necessary.
73
105
 
74
- ConnectionManager::Connections.all => ["TestAppConnection", "Slave1TestAppConnection", "Slave2TestAppConnection"]
75
106
 
76
- If your using the example database.yml your array would look like this:
77
- ["TestAppConnection", "Slave1TestAppConnection", "Slave2TestAppConnection",
78
- "UserDataConnection", "Slave1UserDataConnection", "Slave2UserDataConnection"]
107
+ ### Automatically
108
+ ActiveRecord can build all your connection classes for you.
109
+ The connection class names will be based on the database.yml keys.ActiveRecord will
110
+ build connection classes for all the entries in the database.yml where
111
+ "build_connection_class" is true, and match the current environment settings
79
112
 
113
+ ## Using
80
114
 
81
- To use one of your ConnectionManager::Connections for your models default/master database
82
- setup your model like the following
115
+ The using method allows you specify the connection class to use
116
+ for query. The return objects will have the correct model name, but the instance's
117
+ class's superclass will be the connection class and all database actions performed
118
+ on the instance will use the connection class's connection.
83
119
 
84
- class User < ConnectionManager::Connections::UserDataConnection
85
- # model code ...
86
- end
120
+ User.using("Slave1Connection").first
121
+
122
+ search = User.where(disabled => true)
123
+ @legacy_users = search.using("Shard1Connection").all #=> [<User::Shard1ConnectionDup...>,<User::Shard1ConnectionDup..]
124
+ @legacy_users.first.save #=> uses the Shard1Connection connection
125
+
126
+ @new_users = search.page(params[:page]).all => [<User...>,<User...>]
87
127
 
88
128
  ## Replication
89
129
 
90
- Simply add 'replicated' to your model beneath any defined associations
130
+ Simply add 'replicated' to your model.
91
131
 
92
- class User < ConnectionManager::Connections::UserDataConnection
132
+ class User < UserDataConnection
93
133
  has_one :job
94
134
  has_many :teams
95
135
  replicated # implement replication
96
136
  # model code ...
97
137
  end
98
138
 
99
- The replicated method addeds subclass whose names match the replication connection name and count.
100
- Based on the above example database.yml User class would now have User::Slave1 and User::Slave2.
139
+ The replicated method builds models who inherit from the main model.
140
+ User::Slave1UserDataConnectionDup.superclass => Slave1UserDataConnection(abstract)
141
+ User::Slave1UserDataDup.first => returns results from slave_1_user_data_development
142
+ User::Slave2UserDataDup.where(['created_at BETWEEN ? and ?',Time.now - 3.hours, Time.now]).all => returns results from slave_2_user_data_development
101
143
 
102
- You can treat your subclass like normal activerecord objects.
144
+ Finally, ConnectionManager creates an additional class method that shifts through your
145
+ available slave connections each time it is called using a different connection on each action.
103
146
 
104
- User::Slave1.first => returns results from slave_1_user_data_development
105
- User::Slave2.where(['created_at BETWEEN ? and ?',Time.now - 3.hours, Time.now]).all => returns results from slave_2_user_data_development
147
+ User.slaves.first => returns results from slave_1_use_data_development
148
+ User.slaves.last => => returns results from slave_2_use_data_development
149
+ User.slaves.where(['created_at BETWEEN ? and ?',Time.now - 3.hours, Time.now]).all => returns results from slave_1_user_data_development
150
+ User.slaves.where(['created_at BETWEEN ? and ?',Time.now - 5.days, Time.now]).all => returns results from slave_2_user_data_development
106
151
 
107
- For a more elegant implementation, ConnectionManager also add class methods to your main model following the
108
- same naming standard as the subclass creation.
109
-
110
- User.slave_1.first => returns results from slave_1_user_data_development
111
- User.slave_2.where(['created_at BETWEEN ? and ?',Time.now - 3.hours, Time.now]).all => returns results from slave_2_user_data_development
152
+ Replicated defaults to the slaves replication type,so if you have only masters and a combination
153
+ of masters and slaves for replication, you have set the replication type to masters
112
154
 
113
- Finally, ConnectionManager creates an addional class method that shifts through your
114
- available slave connections each time it is called using a different connection on each action.
115
-
116
- User.slave.first => returns results from slave_1_use_data_development
117
- User.slave.last => => returns results from slave_2_use_data_development
118
- User.slave.where(['created_at BETWEEN ? and ?',Time.now - 3.hours, Time.now]).all => returns results from slave_1_user_data_development
119
- User.slave.where(['created_at BETWEEN ? and ?',Time.now - 5.days, Time.now]).all => returns results from slave_2_user_data_development
155
+ class User < UserDataConnection
156
+ replicated #slaves replication
157
+ replicated :type => :masters, :name => 'masters' # masters replication
158
+ end
159
+
160
+ ## Sharding
161
+
162
+ After tinkering with some solutions for shards, I've come to a similar conclusion as [DataFabric] (https://github.com/mperham/data_fabric):
163
+ "Sharding should be implemented at the application level". The #shards method is very basic and
164
+ while it may be useful to most folks, it should really serve as an example of a possible solutions
165
+ to your shard requirements.
166
+
167
+ class LegacyUser < UserShardConnection
168
+ end
169
+
170
+ class User < ActiveRecord::Base
171
+ self.shard_class_names = ["LegacyUser"]
172
+ end
173
+
174
+ # Calls the supplied block on all the shards available to User, including the User model itself.
175
+ User.shards{ |shard| shard.where(:user_name => "some_user").all} => [<User ...>,<LegacyUser ...>]
176
+
177
+ ## Migrations
178
+
179
+ Nothing implement now to help but there are lots of potential solutions [here] (http://stackoverflow.com/questions/1404620/using-rails-migration-on-different-database-than-standard-production-or-devel)
120
180
 
121
- ## TODO's
122
- * sharding - IN 2.0 AS BETA
123
- * cross schema joins - 2.2 AS BETA tested with Mysql2 ONLY
181
+ ## TODOs
182
+ * Maybe add migration support for Rails AR implementations.
124
183
 
125
- ## Other activerecord Connection gems
184
+ ## Other ActiveRecord Connection gems
185
+ * [DataFabric] (https://github.com/mperham/data_fabric)
126
186
  * [Octopus](https://github.com/tchandy/octopus)
127
187
 
128
188
  ## Contributing to ConnectionManager
129
189
 
130
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
131
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
190
+ * Check out the latest master to make sure the feature has not been implemented or the bug hasn't been fixed yet
191
+ * Check out the issue tracker to make sure someone already has not requested it and/or contributed it
132
192
  * Fork the project
133
193
  * Start a feature/bugfix branch
134
194
  * Commit and push until you are happy with your contribution
data/Rakefile CHANGED
@@ -1 +1,3 @@
1
+ require 'rake'
1
2
  require "bundler/gem_tasks"
3
+
@@ -18,10 +18,16 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
  s.add_runtime_dependency 'activerecord', '~> 3.0'
21
- s.add_development_dependency 'sqlite3'
22
21
  s.add_development_dependency 'rspec'
23
22
  s.add_development_dependency 'autotest'
24
23
  s.add_development_dependency 'mocha'
25
24
  s.add_development_dependency 'factory_girl'
26
- s.add_development_dependency 'mysql2'
27
- end
25
+ s.add_development_dependency 'activesupport', '~> 3.0'
26
+
27
+ if(defined? RUBY_ENGINE and 'jruby' == RUBY_ENGINE)
28
+ s.add_development_dependency 'jruby-openssl'
29
+ s.add_development_dependency 'activerecord-jdbcmysql-adapter'
30
+ else
31
+ s.add_development_dependency "mysql2"
32
+ end
33
+ end
@@ -0,0 +1,81 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+ module ConnectionManager
3
+ module ConnectionBuilder
4
+
5
+ # Get the current environment if defined
6
+ # Check for Rails, check for RACK_ENV, default to 'development'
7
+ def ar_env
8
+ return Rails.env if defined?(Rails)
9
+ return RACK_ENV if defined?(RACK_ENV)
10
+ return ENV["AR_ENV"] if ENV["AR_ENV"]
11
+ "development"
12
+ end
13
+
14
+ # Grab only thoses connections that correspond to the current env. If env
15
+ # is blank it grabs all the connection keys
16
+ #
17
+ # If you current environment valid database keys can be:
18
+ # * development
19
+ # * other_database_development
20
+ # * slave_database_development
21
+ def configuration_keys
22
+ ActiveRecord::Base.configurations.keys.select{|n| n.match(ar_env_regex)}
23
+ end
24
+
25
+ def database_yml_attributes(name_from_yml)
26
+ found = ActiveRecord::Base.configurations[name_from_yml]
27
+ ActiveRecord::Base.configurations[name_from_yml].symbolize_keys if found
28
+ end
29
+
30
+ # Returns currently loaded configuations where :build_connection is true
31
+ def database_keys_for_auto_build
32
+ ab_configs = []
33
+ configuration_keys.each do |key|
34
+ ab_configs << key if (database_yml_attributes(key)[:build_connection_class] == true)
35
+ end
36
+ ab_configs
37
+ end
38
+
39
+ # Builds connection classes using the database keys provided; expects an array.
40
+ def build_connection_classes(database_keys_to_use=database_keys_for_auto_build)
41
+ database_keys_to_use.each do |key|
42
+ build_connection_class(connection_class_name(key),key)
43
+ end
44
+ end
45
+
46
+ # Build connection classes base on the supplied class name and connection
47
+ # key from database.yml
48
+ def build_connection_class(class_name,connection_key)
49
+ begin
50
+ class_name.constantize
51
+ rescue NameError
52
+ klass = Class.new(ActiveRecord::Base)
53
+ new_connection_class = Object.const_set(class_name, klass)
54
+ new_connection_class.establish_managed_connection(connection_key)
55
+ end
56
+ end
57
+
58
+ private
59
+ def ar_env_regex
60
+ return @ar_env_regex if @ar_env_regex
61
+ s = "#{ar_env}$"
62
+ @ar_env_regex = Regexp.new("(#{s})")
63
+ end
64
+
65
+ # Creates a string to be used for the class name. Removes the current env.
66
+ def clean_yml_key(name)
67
+ new_name = "#{name}".gsub(ar_env_regex,'')
68
+ new_name = "Base"if new_name.blank?
69
+ new_name.gsub(/\_$/,'')
70
+ end
71
+
72
+ # Given an connection key name from the database.yml, returns the string
73
+ # equivelent of the class name for that entry.
74
+ def connection_class_name(name_from_yml)
75
+ new_class_name = clean_yml_key(name_from_yml)
76
+ new_class_name = new_class_name.gsub(/\_/,' ').titleize.gsub(/ /,'')
77
+ new_class_name << "Connection"
78
+ new_class_name
79
+ end
80
+ end
81
+ end
@@ -1,7 +1,8 @@
1
1
  module ConnectionManager
2
2
  class ConnectionManagerRailtie < ::Rails::Railtie
3
- initializer "connection_manager.setup" do |app|
4
- ConnectionManager::Connections.initialize
3
+ initializer "connection_manager.build_connection_classes" do
4
+ ActiveRecord::Base.build_connection_classes
5
5
  end
6
6
  end
7
- end
7
+ end
8
+
@@ -0,0 +1,40 @@
1
+ module ConnectionManager
2
+ module AbstractAdapterHelper
3
+ def config
4
+ @config
5
+ end
6
+
7
+ def using_em_adapter?
8
+ (config[:adapter].match(/^em\_/) && defined?(EM) && EM::reactor_running?)
9
+ end
10
+
11
+ def readonly?
12
+ (config[:readonly] == true)
13
+ end
14
+
15
+ def replicated?
16
+ (!slave_keys.blank? || !master_keys.blank?)
17
+ end
18
+
19
+ def database_name
20
+ config[:database]
21
+ end
22
+
23
+ def replication_keys(type=:slaves)
24
+ return slave_keys if type == :slaves
25
+ master_keys
26
+ end
27
+
28
+ def slave_keys
29
+ slave_keys = []
30
+ slave_keys = config[:slaves].collect{|r| r.to_sym} if config[:slaves]
31
+ slave_keys
32
+ end
33
+
34
+ def master_keys
35
+ master_keys = []
36
+ master_keys = config[:masters].collect{|r| r.to_sym} if config[:masters]
37
+ master_keys
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,105 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+ module ConnectionManager
3
+ module ConnectionHelpers
4
+ @@managed_connections = HashWithIndifferentAccess.new
5
+
6
+ # Returns the database_name of the connection unless set otherwise
7
+ def database_name
8
+ @database_name = "#{connection.database_name.to_s}" unless @database_name
9
+ @database_name
10
+ end
11
+
12
+ alias :schema_name :database_name
13
+
14
+ # Returns true if this is a readonly only a readonly model
15
+ # If the connection.readonly? then the model that uses the connection
16
+ # must be readonly.
17
+ def readonly?
18
+ ((@readonly == true)||connection.readonly?)
19
+ end
20
+
21
+ # Allow setting of readonly at the model level
22
+ def readonly=readonly
23
+ @readonly = readonly
24
+ end
25
+
26
+ # A place to store managed connections
27
+ def managed_connections
28
+ @@managed_connections
29
+ end
30
+
31
+ def add_managed_connections(yml_key,value)
32
+ @@managed_connections[yml_key] ||= []
33
+ @@managed_connections[yml_key] << value unless @@managed_connections[yml_key].include?(value)
34
+ @@managed_connections
35
+ end
36
+
37
+ def managed_connection_classes
38
+ managed_connections.values.flatten
39
+ end
40
+
41
+ def yml_key
42
+ @yml_key
43
+ end
44
+
45
+ # Tell Active Record to use a different database/schema on this model.
46
+ # You may call #use_database when your schemas reside on the same database server
47
+ # and you do not want to create extra connection class and database.yml entries.
48
+ #
49
+ # Options:
50
+ # * :table_name_prefix - the prefix required for making cross database/schema
51
+ # joins for you database managmenet system. By default table_name_prefix is the
52
+ # database/schema name followed by a period EX: "my_database."
53
+ # * :table_name - the table name for the model if it does not match ActiveRecord
54
+ # naming conventions
55
+ #
56
+ # EX: class LegacyUser < ActiveRecord::Base
57
+ # use_database('DBUser', :table_name => 'UserData')
58
+ # end
59
+ #
60
+ # LegacyUser.limit(1).to_sql => "SELECT * FROM `BDUser`.`UserData` LIMIT 1
61
+ #
62
+ def use_database(database_name,opts={})
63
+ @database_name = database_name
64
+ opts[:table_name_prefix] ||= "#{database_name}."
65
+ opts[:table_name] ||= self.table_name.to_s.split('.').last
66
+ self.table_name = opts[:table_name]
67
+ self.table_name_prefix = opts[:table_name_prefix]
68
+ end
69
+
70
+ alias :use_schema :use_database
71
+
72
+ # Establishes and checks in a connection, noramlly for abstract classes aka connection classes.
73
+ #
74
+ # Options:
75
+ # * :abstract_class - used the set #abstract_class, default is true
76
+ # * :readonly - force all instances to readonly
77
+ # * :class_name - name of connection class name, default is current class's name
78
+ # * :table_name_prefix - prefix to append to table name for cross database joins,
79
+ # default is the "#{self.database_name}."
80
+ # EX:
81
+ # class MyConnection < ActiveRecord::Base
82
+ # establish_managed_connection :key_from_db_yml,{:readonly => true}
83
+ # end
84
+ #
85
+ def establish_managed_connection(yml_key,opts={})
86
+ @yml_key = yml_key
87
+ opts = {:class_name => self.name,
88
+ :abstract_class => true}.merge(opts)
89
+ establish_connection(yml_key)
90
+ self.abstract_class = opts[:abstract_class]
91
+ set_to_readonly if (readonly? || opts[:readonly] || self.connection.readonly?)
92
+ add_managed_connections(yml_key,opts[:class_name])
93
+ use_database(self.database_name,opts)
94
+ end
95
+
96
+ # Override ActiveRecord::Base instance method readonly? to force
97
+ # readonly connections.
98
+ def set_to_readonly
99
+ self.readonly = true
100
+ define_method(:readonly?) do
101
+ true
102
+ end
103
+ end
104
+ end
105
+ end
@@ -5,8 +5,7 @@ if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
5
5
  module ActiveRecord
6
6
  module ConnectionAdapters
7
7
  class Mysql2Adapter < AbstractAdapter
8
-
9
- def real_tables(name = nil, database = nil) #:nodoc:
8
+ def new_tables(database = nil) #:nodoc:
10
9
  sql = ["SHOW TABLES", database].compact.join(' IN ')
11
10
  execute(sql, 'SCHEMA').collect do |field|
12
11
  field.first
@@ -21,7 +20,7 @@ if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
21
20
  table = schema
22
21
  schema = nil
23
22
  end
24
- real_tables(nil, schema).include? table
23
+ new_tables(schema).include? table
25
24
  end
26
25
  end
27
26
  end