kovyrin-db-charmer 1.0.1 → 1.1.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.
- data/README.rdoc +42 -5
- data/VERSION +1 -1
- data/db-charmer.gemspec +3 -2
- data/init.rb +1 -4
- data/lib/db_charmer/active_record_extensions.rb +8 -8
- data/lib/db_charmer/association_proxy.rb +17 -0
- data/lib/db_charmer/connection_factory.rb +4 -4
- data/lib/db_charmer/connection_proxy.rb +0 -1
- data/lib/db_charmer/multi_db_migrations.rb +1 -1
- data/lib/db_charmer/multi_db_proxy.rb +9 -7
- data/lib/db_charmer.rb +16 -4
- metadata +5 -3
data/README.rdoc
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
5. Adds multiple databases migrations to ActiveRecord
|
10
10
|
|
11
11
|
|
12
|
-
== Installation
|
12
|
+
== Installation
|
13
13
|
|
14
14
|
There are two options when approaching db-charmer installation:
|
15
15
|
* using gem (recommended)
|
@@ -57,6 +57,11 @@ change would happen. This is really useful when in development mode or in tests
|
|
57
57
|
create many different databases on your local machine and just want to put all your tables in one
|
58
58
|
database.
|
59
59
|
|
60
|
+
Warning: All the connection switching calls would switch connection *only* for those classes the
|
61
|
+
method called on. You can't call the +switch_connection_to+ method and switch connection for a
|
62
|
+
base class in some hierarchy (for example, you can't switch AR::Base connection and see all your
|
63
|
+
models switched to the new connection, use classic +establish_connection+ instead).
|
64
|
+
|
60
65
|
|
61
66
|
== Multiple DB Migrations
|
62
67
|
|
@@ -190,19 +195,51 @@ well: block and proxy.
|
|
190
195
|
3) <tt>on_db(connection)</tt> - this method is what makes two previous methods possible.
|
191
196
|
It is used to switch a model's connection to some db for a short block of code
|
192
197
|
or even for one statement (two forms). It accepts the same range of values as
|
193
|
-
the +switch_connection_to+ method does.
|
198
|
+
the +switch_connection_to+ method does. Example:
|
199
|
+
|
200
|
+
Comment.on_db(:olap).count
|
201
|
+
Post.on_db(:foo).find(:first)
|
202
|
+
|
203
|
+
|
204
|
+
=== Associations Connection Management
|
205
|
+
|
206
|
+
ActiveRecord models can have associations and with their own connections and it becomes
|
207
|
+
pretty hard to manage connections in chained calls like <tt>User.posts.count</tt>. With
|
208
|
+
class-only connection switching methods this call would look like the following if we'd
|
209
|
+
want to count posts on a separate database:
|
210
|
+
|
211
|
+
Post.on_db(:olap) { User.posts.count }
|
212
|
+
|
213
|
+
Apparently this is not the best way to write the code and we've implemented <tt>on_*</tt>
|
214
|
+
methods on associations as well so you could do things like this:
|
215
|
+
|
216
|
+
@user.posts.on_db(:olap).count
|
217
|
+
@user.posts.on_slave.find(:title => 'Hello, world!')
|
218
|
+
|
219
|
+
Notice: Since ActiveRecord associations implemented as proxies for resulting
|
220
|
+
objects/collections, it is possible to use our connection switching methods even without
|
221
|
+
chained methods:
|
222
|
+
|
223
|
+
@post.user.on_slave - would return post's author
|
224
|
+
@photo.owner.on_slave - would return photo's owner
|
194
225
|
|
195
226
|
|
196
227
|
== Documentation
|
197
228
|
|
198
|
-
For more information on the plugin internals, please check out the source code. All the plugin's
|
229
|
+
For more information on the plugin internals, please check out the source code. All the plugin's
|
230
|
+
code is covered with tests that were placed in a separate staging rails project located at
|
231
|
+
http://github.com/kovyrin/db-charmer-sandbox. The project has unit tests for all or at least the
|
232
|
+
most of the parts of plugin's code.
|
199
233
|
|
200
234
|
|
201
235
|
== What Ruby and Rails implementations does it work for?
|
202
236
|
|
203
|
-
We've tested the plugin on MRI 1.8.6 with Rails 2.
|
237
|
+
We've tested the plugin on MRI 1.8.6 with Rails 2.2 and 2.3. We use it in production on Scribd.com
|
238
|
+
with MRI 1.8.6 and Rails 2.2.
|
204
239
|
|
205
240
|
|
206
241
|
== Who are the authors?
|
207
242
|
|
208
|
-
This plugin has been created in Scribd.com for our internal use and then the sources were opened for
|
243
|
+
This plugin has been created in Scribd.com for our internal use and then the sources were opened for
|
244
|
+
other people to use. All the code in this package has been developed by Alexey Kovyrin for Scribd.com
|
245
|
+
and is released under the GPLv2 license. For more details, see the LICENSE file.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.1.0
|
data/db-charmer.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{db-charmer}
|
8
|
-
s.version = "1.0
|
8
|
+
s.version = "1.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alexey Kovyrin"]
|
12
|
-
s.date = %q{2009-
|
12
|
+
s.date = %q{2009-09-18}
|
13
13
|
s.description = %q{ActiveRecord Connections Magic (slaves, multiple connections, etc)}
|
14
14
|
s.email = %q{alexey@kovyrin.net}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
"init.rb",
|
28
28
|
"lib/db_charmer.rb",
|
29
29
|
"lib/db_charmer/active_record_extensions.rb",
|
30
|
+
"lib/db_charmer/association_proxy.rb",
|
30
31
|
"lib/db_charmer/connection_factory.rb",
|
31
32
|
"lib/db_charmer/connection_proxy.rb",
|
32
33
|
"lib/db_charmer/connection_switch.rb",
|
data/init.rb
CHANGED
@@ -13,31 +13,31 @@ module DbCharmer
|
|
13
13
|
#-----------------------------------------------------------------------------
|
14
14
|
@@db_charmer_opts = {}
|
15
15
|
def db_charmer_opts=(opts)
|
16
|
-
@@db_charmer_opts[self.
|
16
|
+
@@db_charmer_opts[self.name] = opts
|
17
17
|
end
|
18
18
|
|
19
19
|
def db_charmer_opts
|
20
|
-
@@db_charmer_opts[self.
|
20
|
+
@@db_charmer_opts[self.name] || {}
|
21
21
|
end
|
22
22
|
|
23
23
|
#-----------------------------------------------------------------------------
|
24
24
|
@@db_charmer_connection_proxies = {}
|
25
25
|
def db_charmer_connection_proxy=(proxy)
|
26
|
-
@@db_charmer_connection_proxies[self.
|
26
|
+
@@db_charmer_connection_proxies[self.name] = proxy
|
27
27
|
end
|
28
28
|
|
29
29
|
def db_charmer_connection_proxy
|
30
|
-
@@db_charmer_connection_proxies[self.
|
30
|
+
@@db_charmer_connection_proxies[self.name]
|
31
31
|
end
|
32
32
|
|
33
33
|
#-----------------------------------------------------------------------------
|
34
34
|
@@db_charmer_slaves = {}
|
35
35
|
def db_charmer_slaves=(slaves)
|
36
|
-
@@db_charmer_slaves[self.
|
36
|
+
@@db_charmer_slaves[self.name] = slaves
|
37
37
|
end
|
38
38
|
|
39
39
|
def db_charmer_slaves
|
40
|
-
@@db_charmer_slaves[self.
|
40
|
+
@@db_charmer_slaves[self.name] || []
|
41
41
|
end
|
42
42
|
|
43
43
|
def db_charmer_random_slave
|
@@ -48,11 +48,11 @@ module DbCharmer
|
|
48
48
|
#-----------------------------------------------------------------------------
|
49
49
|
@@db_charmer_connection_levels = Hash.new(0)
|
50
50
|
def db_charmer_connection_level=(level)
|
51
|
-
@@db_charmer_connection_levels[self.
|
51
|
+
@@db_charmer_connection_levels[self.name] = level
|
52
52
|
end
|
53
53
|
|
54
54
|
def db_charmer_connection_level
|
55
|
-
@@db_charmer_connection_levels[self.
|
55
|
+
@@db_charmer_connection_levels[self.name] || 0
|
56
56
|
end
|
57
57
|
|
58
58
|
def db_charmer_top_level_connection?
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module DbCharmer
|
2
|
+
module AssociationProxy
|
3
|
+
module InstanceMethods
|
4
|
+
def on_db(con, &block)
|
5
|
+
@reflection.klass.on_db(con, self, &block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def on_slave(con = nil, &block)
|
9
|
+
@reflection.klass.on_slave(con, self, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_master(&block)
|
13
|
+
@reflection.klass.on_master(self, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -8,18 +8,18 @@ module DbCharmer
|
|
8
8
|
|
9
9
|
def self.connect(db_name, should_exist = false)
|
10
10
|
@@connection_classes[db_name.to_s] ||= establish_connection(db_name.to_s, should_exist)
|
11
|
-
DbCharmer.logger.warn("ConnectionFactory.connect(#{db_name}) = #{@@connection_classes[db_name.to_s]}")
|
12
|
-
return @@connection_classes[db_name.to_s]
|
11
|
+
# DbCharmer.logger.warn("ConnectionFactory.connect(#{db_name}) = #{@@connection_classes[db_name.to_s]}")
|
12
|
+
# return @@connection_classes[db_name.to_s]
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.establish_connection(db_name, should_exist = false)
|
16
|
-
DbCharmer.logger.debug("Creating a connection proxy for #{db_name}")
|
16
|
+
# DbCharmer.logger.debug("Creating a connection proxy for #{db_name}")
|
17
17
|
abstract_class = generate_abstract_class(db_name, should_exist)
|
18
18
|
DbCharmer::ConnectionProxy.new(abstract_class)
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.generate_abstract_class(db_name, should_exist = false)
|
22
|
-
DbCharmer.logger.info("Generating abstract connection class for #{db_name}: #{abstract_connection_class_name db_name}")
|
22
|
+
# DbCharmer.logger.info("Generating abstract connection class for #{db_name}: #{abstract_connection_class_name db_name}")
|
23
23
|
|
24
24
|
module_eval <<-EOF, __FILE__, __LINE__ + 1
|
25
25
|
class #{abstract_connection_class_name db_name} < ActiveRecord::Base
|
@@ -16,16 +16,18 @@ module DbCharmer
|
|
16
16
|
end
|
17
17
|
|
18
18
|
module ClassMethods
|
19
|
-
def on_db(con)
|
19
|
+
def on_db(con, proxy_target = nil)
|
20
|
+
proxy_target ||= self
|
21
|
+
|
20
22
|
# Chain call
|
21
|
-
return OnDbProxy.new(
|
23
|
+
return OnDbProxy.new(proxy_target, con) unless block_given?
|
22
24
|
|
23
25
|
# Block call
|
24
26
|
begin
|
25
27
|
self.db_charmer_connection_level += 1
|
26
28
|
old_proxy = db_charmer_connection_proxy
|
27
29
|
switch_connection_to(con, DbCharmer.migration_connections_should_exist?)
|
28
|
-
yield(
|
30
|
+
yield(proxy_target)
|
29
31
|
ensure
|
30
32
|
switch_connection_to(old_proxy)
|
31
33
|
self.db_charmer_connection_level -= 1
|
@@ -34,14 +36,14 @@ module DbCharmer
|
|
34
36
|
end
|
35
37
|
|
36
38
|
module MasterSlaveClassMethods
|
37
|
-
def on_slave(con = nil, &block)
|
39
|
+
def on_slave(con = nil, proxy_target = nil, &block)
|
38
40
|
con ||= db_charmer_random_slave
|
39
41
|
raise ArgumentError, "No slaves found in the class and no slave connection given" unless con
|
40
|
-
on_db(con, &block)
|
42
|
+
on_db(con, proxy_target, &block)
|
41
43
|
end
|
42
44
|
|
43
|
-
def on_master(&block)
|
44
|
-
on_db(nil, &block)
|
45
|
+
def on_master(proxy_target = nil, &block)
|
46
|
+
on_db(nil, proxy_target, &block)
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
data/lib/db_charmer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
puts "Loading DbCharmer..."
|
2
|
+
|
1
3
|
module DbCharmer
|
2
4
|
@@migration_connections_should_exist = Rails.env.production?
|
3
5
|
mattr_accessor :migration_connections_should_exist
|
@@ -19,14 +21,13 @@ module DbCharmer
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
24
|
+
puts "Extending AR..."
|
25
|
+
|
22
26
|
require 'db_charmer/active_record_extensions'
|
23
27
|
require 'db_charmer/connection_factory'
|
24
28
|
require 'db_charmer/connection_proxy'
|
25
29
|
require 'db_charmer/connection_switch'
|
26
|
-
require 'db_charmer/
|
27
|
-
require 'db_charmer/finder_overrides'
|
28
|
-
require 'db_charmer/multi_db_migrations'
|
29
|
-
require 'db_charmer/multi_db_proxy'
|
30
|
+
require 'db_charmer/association_proxy'
|
30
31
|
|
31
32
|
# Enable misc AR extensions
|
32
33
|
ActiveRecord::Base.extend(DbCharmer::ActiveRecordExtensions::ClassMethods)
|
@@ -36,6 +37,17 @@ ActiveRecord::Base.extend(DbCharmer::ConnectionSwitch::ClassMethods)
|
|
36
37
|
|
37
38
|
# Enable connection proxy in AR
|
38
39
|
ActiveRecord::Base.extend(DbCharmer::MultiDbProxy::ClassMethods)
|
40
|
+
#ActiveRecord::Base.send(:include, DbCharmer::MultiDbProxy::InstanceMethods)
|
41
|
+
|
42
|
+
# Enable connection proxy for associations
|
43
|
+
ActiveRecord::Associations::AssociationProxy.send(:include, DbCharmer::AssociationProxy::InstanceMethods)
|
44
|
+
|
45
|
+
puts "Doing the magic..."
|
46
|
+
|
47
|
+
require 'db_charmer/db_magic'
|
48
|
+
require 'db_charmer/finder_overrides'
|
49
|
+
require 'db_charmer/multi_db_migrations'
|
50
|
+
require 'db_charmer/multi_db_proxy'
|
39
51
|
|
40
52
|
# Enable multi-db migrations
|
41
53
|
ActiveRecord::Migration.extend(DbCharmer::MultiDbMigrations::ClassMethods)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kovyrin-db-charmer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexey Kovyrin
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-18 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,6 +42,7 @@ files:
|
|
42
42
|
- init.rb
|
43
43
|
- lib/db_charmer.rb
|
44
44
|
- lib/db_charmer/active_record_extensions.rb
|
45
|
+
- lib/db_charmer/association_proxy.rb
|
45
46
|
- lib/db_charmer/connection_factory.rb
|
46
47
|
- lib/db_charmer/connection_proxy.rb
|
47
48
|
- lib/db_charmer/connection_switch.rb
|
@@ -51,6 +52,7 @@ files:
|
|
51
52
|
- lib/db_charmer/multi_db_proxy.rb
|
52
53
|
has_rdoc: false
|
53
54
|
homepage: http://github.com/kovyrin/db-charmer
|
55
|
+
licenses:
|
54
56
|
post_install_message:
|
55
57
|
rdoc_options:
|
56
58
|
- --charset=UTF-8
|
@@ -71,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
73
|
requirements: []
|
72
74
|
|
73
75
|
rubyforge_project:
|
74
|
-
rubygems_version: 1.
|
76
|
+
rubygems_version: 1.3.5
|
75
77
|
signing_key:
|
76
78
|
specification_version: 3
|
77
79
|
summary: db-charmer 1.0.1
|