replica 1.0.1 → 1.0.2

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/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1
1
+ 1.0.2
data/lib/replica.rb CHANGED
@@ -11,6 +11,9 @@ module ActiveRecord # :nodoc:
11
11
  # end
12
12
  # the first account will be found on the slave DB
13
13
  #
14
+ # For one-liners you can simply do
15
+ # Account.with_slave.first
16
+ #
14
17
  # this is the same as:
15
18
  # Account.with_replica(:slave) do
16
19
  # Account.first
@@ -18,7 +21,7 @@ module ActiveRecord # :nodoc:
18
21
  def with_slave(&block)
19
22
  with_replica(:slave, &block)
20
23
  end
21
-
24
+
22
25
  # See with_slave
23
26
  def with_master(&block)
24
27
  with_replica(nil, &block)
@@ -27,11 +30,11 @@ module ActiveRecord # :nodoc:
27
30
  def with_slave_if(condition, &block)
28
31
  condition ? with_slave(&block) : with_master(&block)
29
32
  end
30
-
33
+
31
34
  def with_slave_unless(condition, &block)
32
35
  with_slave_if(!condition, &block)
33
36
  end
34
-
37
+
35
38
  # Name of the connection pool. Used by ConnectionHandler to retrieve the current connection pool.
36
39
  def connection_pool_name # :nodoc:
37
40
  replica = current_replica_name
@@ -44,7 +47,7 @@ module ActiveRecord # :nodoc:
44
47
  end
45
48
  end
46
49
 
47
- # Specify which database to use.
50
+ # Specify which database to use.
48
51
  #
49
52
  # Example:
50
53
  # database.yml
@@ -53,22 +56,31 @@ module ActiveRecord # :nodoc:
53
56
  # ...
54
57
  #
55
58
  # Account.with_replica(:slave) { Account.count }
59
+ # Account.with_replica(:slave).count
56
60
  #
57
61
  def with_replica(replica_name, &block)
62
+ if block_given?
63
+ with_replica_block(replica_name, &block)
64
+ else
65
+ Proxy.new(self, replica_name)
66
+ end
67
+ end
68
+
69
+ def with_replica_block(replica_name, &block)
58
70
  old_replica_name = current_replica_name
59
71
  begin
60
72
  self.current_replica_name = replica_name
61
73
  rescue ActiveRecord::AdapterNotSpecified => e
62
74
  self.current_replica_name = old_replica_name
63
75
  logger.warn("Failed to establish replica connection: #{e.message} - defaulting to master")
64
- end
76
+ end
65
77
  yield
66
78
  ensure
67
79
  self.current_replica_name = old_replica_name
68
80
  end
69
81
 
70
82
  private
71
-
83
+
72
84
  def current_replica_name
73
85
  Thread.current[replica_key]
74
86
  end
@@ -78,47 +90,56 @@ module ActiveRecord # :nodoc:
78
90
 
79
91
  establish_replica_connection(new_replica_name) unless connected_to_replica?
80
92
  end
81
-
93
+
82
94
  def establish_replica_connection(replica_name)
83
- name = replica_name ? "#{RAILS_ENV}_#{replica_name}" : RAILS_ENV
84
- spec = configurations[name]
85
- raise AdapterNotSpecified.new("No database defined by #{name} in database.yml") if spec.nil?
86
-
87
- connection_handler.establish_connection(connection_pool_name, ConnectionSpecification.new(spec, "#{spec['adapter']}_connection"))
95
+ name = replica_name ? "#{RAILS_ENV}_#{replica_name}" : RAILS_ENV
96
+ spec = configurations[name]
97
+ raise AdapterNotSpecified.new("No database defined by #{name} in database.yml") if spec.nil?
98
+
99
+ connection_handler.establish_connection(connection_pool_name, ConnectionSpecification.new(spec, "#{spec['adapter']}_connection"))
88
100
  end
89
-
101
+
90
102
  def connected_to_replica?
91
103
  connection_handler.connection_pools.has_key?(connection_pool_name)
92
104
  end
93
-
105
+
94
106
  def replica_key
95
107
  @replica_key ||= "#{name}_replica"
96
108
  end
97
-
109
+
110
+ class Proxy
111
+ def initialize(target, replica)
112
+ @target = target
113
+ @replica = replica
114
+ end
115
+
116
+ def method_missing(method, *args)
117
+ @target.with_replica_block(@replica) { @target.send(method, *args) }
118
+ end
119
+ end
98
120
  end
99
121
  end
100
122
  Base.extend(Base::Replica)
101
-
123
+
102
124
  # The only difference here is that we use klass.connection_pool_name
103
125
  # instead of klass.name as the pool key
104
126
  module ConnectionAdapters # :nodoc:
105
127
  class ConnectionHandler # :nodoc:
106
-
128
+
107
129
  def retrieve_connection_pool(klass)
108
130
  pool = @connection_pools[klass.connection_pool_name]
109
131
  return pool if pool
110
132
  return nil if ActiveRecord::Base == klass
111
133
  retrieve_connection_pool klass.superclass
112
134
  end
113
-
135
+
114
136
  def remove_connection(klass)
115
- pool = @connection_pools[klass.connection_pool_name]
116
- @connection_pools.delete_if { |key, value| value == pool }
117
- pool.disconnect! if pool
118
- pool.spec.config if pool
119
- end
120
-
137
+ pool = @connection_pools[klass.connection_pool_name]
138
+ @connection_pools.delete_if { |key, value| value == pool }
139
+ pool.disconnect! if pool
140
+ pool.spec.config if pool
141
+ end
142
+
121
143
  end
122
144
  end
123
145
  end
124
-
data/test/helper.rb CHANGED
@@ -20,7 +20,7 @@ load(File.dirname(__FILE__) + "/schema.rb")
20
20
 
21
21
 
22
22
  class Test::Unit::TestCase
23
-
23
+
24
24
  def assert_using_master_db(klass)
25
25
  assert_equal('replica_test', klass.connection.instance_variable_get(:@config)[:database])
26
26
  end
@@ -28,5 +28,5 @@ class Test::Unit::TestCase
28
28
  def assert_using_slave_db(klass)
29
29
  assert_equal('replica_test_slave', klass.connection.instance_variable_get(:@config)[:database])
30
30
  end
31
-
31
+
32
32
  end
data/test/replica_test.rb CHANGED
@@ -13,7 +13,7 @@ class ReplicaTest < ActiveRecord::TestCase
13
13
  should "default to the master database" do
14
14
  Account.create!
15
15
 
16
- ActiveRecord::Base.with_slave { assert_using_master_db(Account) }
16
+ ActiveRecord::Base.with_slave { assert_using_master_db(Account) }
17
17
  Account.with_slave { assert_using_master_db(Account) }
18
18
  Ticket.with_slave { assert_using_master_db(Account) }
19
19
  end
@@ -36,6 +36,7 @@ class ReplicaTest < ActiveRecord::TestCase
36
36
 
37
37
  assert_not_equal Account.count, ActiveRecord::Base.with_slave { Account.count }
38
38
  assert_not_equal Account.count, Account.with_slave { Account.count }
39
+ assert_not_equal Account.count, Account.with_slave.count
39
40
  assert_equal Account.count, Ticket.with_slave { Account.count }
40
41
  end
41
42
 
@@ -67,25 +68,25 @@ class ReplicaTest < ActiveRecord::TestCase
67
68
 
68
69
  should "support conditional methods" do
69
70
  assert_using_master_db(Account)
70
-
71
+
71
72
  Account.with_slave_if(true) do
72
73
  assert_using_slave_db(Account)
73
74
  end
74
-
75
+
75
76
  assert_using_master_db(Account)
76
77
 
77
78
  Account.with_slave_if(false) do
78
79
  assert_using_master_db(Account)
79
80
  end
80
-
81
+
81
82
  Account.with_slave_unless(true) do
82
83
  assert_using_master_db(Account)
83
84
  end
84
-
85
+
85
86
  Account.with_slave_unless(false) do
86
87
  assert_using_slave_db(Account)
87
88
  end
88
-
89
+
89
90
  end
90
91
 
91
92
  should_eventually "support nested with_* blocks" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: replica
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Chapweske
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2010-01-27 00:00:00 -08:00
13
+ date: 2010-01-28 00:00:00 -08:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency