replica 1.0.1 → 1.0.2

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