kovyrin-db-charmer 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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 code is covered with tests that were placed in a separate staging rails project located at http://github.com/kovyrin/db-charmer-sandbox. The project has unit tests for all or at least the most of the parts of plugin's code.
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.3.3. After the initial testing phase we're going to deploy this code in production.
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 other people to use. All the code in this package has been developed by Alexey Kovyrin for Scribd.com and is released under the GPLv2 license. For more details, see the LICENSE file.
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.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.1"
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-08-26}
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
@@ -1,4 +1 @@
1
- # Placeholder to satisfy Rails.
2
- #
3
- # Do NOT add any require statements to this file. Doing
4
- # so will cause Rails to load this plugin all of the time.
1
+ require 'db_charmer'
@@ -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.to_s] = opts
16
+ @@db_charmer_opts[self.name] = opts
17
17
  end
18
18
 
19
19
  def db_charmer_opts
20
- @@db_charmer_opts[self.to_s] || {}
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.to_s] = proxy
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.to_s]
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.to_s] = slaves
36
+ @@db_charmer_slaves[self.name] = slaves
37
37
  end
38
38
 
39
39
  def db_charmer_slaves
40
- @@db_charmer_slaves[self.to_s] || []
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.to_s] = level
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.to_s] || 0
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
@@ -5,7 +5,6 @@ module DbCharmer
5
5
  end
6
6
 
7
7
  def method_missing(meth, *args, &block)
8
- DbCharmer.logger.debug("Proxying #{meth} call to #{@abstract_connection_class}")
9
8
  @abstract_connection_class.retrieve_connection.send(meth, *args, &block)
10
9
  end
11
10
  end
@@ -9,7 +9,7 @@ module DbCharmer
9
9
  def hijack_connection!
10
10
  class << self
11
11
  def connection
12
- puts "DEBUG: Retrieving migration connection"
12
+ # puts "DEBUG: Retrieving migration connection"
13
13
  MigrationAbstractClass.connection
14
14
  end
15
15
  end
@@ -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(self, con) unless block_given?
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(self)
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/db_magic'
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.1
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-08-26 00:00:00 -07:00
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.2.0
76
+ rubygems_version: 1.3.5
75
77
  signing_key:
76
78
  specification_version: 3
77
79
  summary: db-charmer 1.0.1