connection_manager 0.2.6 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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