active_record_shards 3.22.0 → 4.0.0.beta1

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.
@@ -1,34 +1,16 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require 'active_record_shards/shard_support'
4
3
 
5
4
  module ActiveRecordShards
6
5
  module ConnectionSwitcher
7
- SHARD_NAMES_CONFIG_KEY = 'shard_names'
6
+ SHARD_NAMES_CONFIG_KEY = 'shard_names'.freeze
8
7
 
9
8
  def self.extended(base)
10
- if ActiveRecord::VERSION::MAJOR >= 5
11
- base.singleton_class.send(:alias_method, :load_schema_without_default_shard!, :load_schema!)
12
- base.singleton_class.send(:alias_method, :load_schema!, :load_schema_with_default_shard!)
13
- else
14
- base.singleton_class.send(:alias_method, :columns_without_default_shard, :columns)
15
- base.singleton_class.send(:alias_method, :columns, :columns_with_default_shard)
16
- end
9
+ base.singleton_class.send(:alias_method, :load_schema_without_default_shard!, :load_schema!)
10
+ base.singleton_class.send(:alias_method, :load_schema!, :load_schema_with_default_shard!)
17
11
 
18
12
  base.singleton_class.send(:alias_method, :table_exists_without_default_shard?, :table_exists?)
19
13
  base.singleton_class.send(:alias_method, :table_exists?, :table_exists_with_default_shard?)
20
-
21
- base.singleton_class.send(:alias_method, :reset_primary_key_without_default_shard, :reset_primary_key)
22
- base.singleton_class.send(:alias_method, :reset_primary_key, :reset_primary_key_with_default_shard)
23
- end
24
-
25
- def default_shard=(new_default_shard)
26
- ActiveRecordShards::ShardSelection.default_shard = new_default_shard
27
- switch_connection(shard: new_default_shard)
28
- end
29
-
30
- def on_primary_db(&block)
31
- on_shard(nil, &block)
32
14
  end
33
15
 
34
16
  def on_shard(shard)
@@ -39,9 +21,9 @@ module ActiveRecordShards
39
21
  switch_connection(old_options)
40
22
  end
41
23
 
42
- def on_first_shard(&block)
24
+ def on_first_shard
43
25
  shard_name = shard_names.first
44
- on_shard(shard_name, &block)
26
+ on_shard(shard_name) { yield }
45
27
  end
46
28
 
47
29
  def shards
@@ -62,93 +44,88 @@ module ActiveRecordShards
62
44
  switch_connection(old_options)
63
45
  end
64
46
 
65
- def on_replica_if(condition, &block)
66
- condition ? on_replica(&block) : yield
47
+ def on_slave_if(condition, &block)
48
+ condition ? on_slave(&block) : yield
67
49
  end
68
- alias_method :on_slave_if, :on_replica_if
69
50
 
70
- def on_replica_unless(condition, &block)
71
- on_replica_if(!condition, &block)
51
+ def on_slave_unless(condition, &block)
52
+ on_slave_if(!condition, &block)
72
53
  end
73
- alias_method :on_slave_unless, :on_replica_unless
74
54
 
75
- def on_primary_if(condition, &block)
76
- condition ? on_primary(&block) : yield
55
+ def on_master_if(condition, &block)
56
+ condition ? on_master(&block) : yield
77
57
  end
78
- alias_method :on_master_if, :on_primary_if
79
58
 
80
- def on_primary_unless(condition, &block)
81
- on_primary_if(!condition, &block)
59
+ def on_master_unless(condition, &block)
60
+ on_master_if(!condition, &block)
82
61
  end
83
- alias_method :on_master_unless, :on_primary_unless
84
62
 
85
- def on_primary_or_replica(which, &block)
63
+ def on_master_or_slave(which, &block)
86
64
  if block_given?
87
65
  on_cx_switch_block(which, &block)
88
66
  else
89
- PrimaryReplicaProxy.new(self, which)
67
+ MasterSlaveProxy.new(self, which)
90
68
  end
91
69
  end
92
- alias_method :on_master_or_slave, :on_primary_or_replica
93
70
 
94
- # Executes queries using the replica database. Fails over to primary if no replica is found.
95
- # if you want to execute a block of code on the replica you can go:
96
- # Account.on_replica do
71
+ # Executes queries using the slave database. Fails over to master if no slave is found.
72
+ # if you want to execute a block of code on the slave you can go:
73
+ # Account.on_slave do
97
74
  # Account.first
98
75
  # end
99
- # the first account will be found on the replica DB
76
+ # the first account will be found on the slave DB
100
77
  #
101
78
  # For one-liners you can simply do
102
- # Account.on_replica.first
103
- def on_replica(&block)
104
- on_primary_or_replica(:replica, &block)
79
+ # Account.on_slave.first
80
+ def on_slave(&block)
81
+ on_master_or_slave(:slave, &block)
105
82
  end
106
- alias_method :on_slave, :on_replica
107
83
 
108
- def on_primary(&block)
109
- on_primary_or_replica(:primary, &block)
84
+ def on_master(&block)
85
+ on_master_or_slave(:master, &block)
110
86
  end
111
- alias_method :on_master, :on_primary
112
-
113
- # just to ease the transition from replica to active_record_shards
114
- alias_method :with_slave, :on_replica
115
- alias_method :with_slave_if, :on_replica_if
116
- alias_method :with_slave_unless, :on_replica_unless
117
87
 
118
88
  def on_cx_switch_block(which, force: false, construct_ro_scope: nil, &block)
119
- @disallow_replica ||= 0
120
- @disallow_replica += 1 if [:primary, :master].include?(which)
89
+ @disallow_slave ||= 0
90
+ @disallow_slave += 1 if which == :master
121
91
 
122
- ActiveRecordShards::Deprecation.warn('the `:master` option should be replaced with `:primary`!') if which == :master
123
-
124
- switch_to_replica = force || @disallow_replica.zero?
92
+ switch_to_slave = force || @disallow_slave.zero?
125
93
  old_options = current_shard_selection.options
126
94
 
127
- switch_connection(replica: switch_to_replica)
95
+ switch_connection(slave: switch_to_slave)
128
96
 
129
97
  # we avoid_readonly_scope to prevent some stack overflow problems, like when
130
98
  # .columns calls .with_scope which calls .columns and onward, endlessly.
131
- if self == ActiveRecord::Base || !switch_to_replica || construct_ro_scope == false || ActiveRecordShards.disable_replica_readonly_records == true
99
+ if self == ActiveRecord::Base || !switch_to_slave || construct_ro_scope == false
132
100
  yield
133
101
  else
134
102
  readonly.scoping(&block)
135
103
  end
136
104
  ensure
137
- @disallow_replica -= 1 if [:primary, :master].include?(which)
105
+ @disallow_slave -= 1 if which == :master
138
106
  switch_connection(old_options) if old_options
139
107
  end
140
108
 
109
+ def connection_specification_name
110
+ name = current_shard_selection.resolve_connection_name(sharded: is_sharded?, configurations: configurations)
111
+
112
+ unless configurations[name] || name == "primary"
113
+ raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.inspect})"
114
+ end
115
+
116
+ name
117
+ end
118
+
141
119
  def supports_sharding?
142
120
  shard_names.any?
143
121
  end
144
122
 
145
- def on_replica?
146
- current_shard_selection.on_replica?
123
+ def on_slave?
124
+ current_shard_selection.on_slave?
147
125
  end
148
- alias_method :on_slave?, :on_replica?
149
126
 
150
127
  def current_shard_selection
151
- Thread.current[:shard_selection] ||= ShardSelection.new
128
+ Thread.current[:shard_selection] ||= ShardSelection.new(shard_names.first)
152
129
  end
153
130
 
154
131
  def current_shard_id
@@ -156,99 +133,78 @@ module ActiveRecordShards
156
133
  end
157
134
 
158
135
  def shard_names
159
- unless config_for_env.fetch(SHARD_NAMES_CONFIG_KEY, []).all? { |shard_name| shard_name.is_a?(Integer) }
160
- raise "All shard names must be integers: #{config_for_env[SHARD_NAMES_CONFIG_KEY].inspect}."
136
+ unless config = configurations[shard_env]
137
+ raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.inspect})"
161
138
  end
162
-
163
- config_for_env[SHARD_NAMES_CONFIG_KEY] || []
164
- end
165
-
166
- def reset_primary_key_with_default_shard
167
- with_default_shard { reset_primary_key_without_default_shard }
139
+ unless config[SHARD_NAMES_CONFIG_KEY]
140
+ raise "No shards configured for #{shard_env}"
141
+ end
142
+ unless config[SHARD_NAMES_CONFIG_KEY].all? { |shard_name| shard_name.is_a?(Integer) }
143
+ raise "All shard names must be integers: #{config[SHARD_NAMES_CONFIG_KEY].inspect}."
144
+ end
145
+ config[SHARD_NAMES_CONFIG_KEY]
168
146
  end
169
147
 
170
148
  private
171
149
 
172
- def config_for_env
173
- @_ars_config_for_env ||= {}
174
- @_ars_config_for_env[shard_env] ||= begin
175
- unless config = configurations[shard_env]
176
- raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.to_h.keys.inspect})"
177
- end
178
-
179
- config
180
- end
181
- end
182
- alias_method :check_config_for_env, :config_for_env
183
-
184
150
  def switch_connection(options)
185
151
  if options.any?
186
- if options.key?(:replica)
187
- current_shard_selection.on_replica = options[:replica]
188
- end
189
-
190
152
  if options.key?(:shard)
191
- check_config_for_env
192
-
153
+ unless config = configurations[shard_env]
154
+ raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.inspect})"
155
+ end
156
+ unless config['shard_names'].include?(options[:shard])
157
+ raise "Did not find shard #{options[:shard]} in configurations"
158
+ end
193
159
  current_shard_selection.shard = options[:shard]
194
160
  end
195
161
 
162
+ if options.key?(:slave)
163
+ current_shard_selection.on_slave = options[:slave]
164
+ end
165
+
196
166
  ensure_shard_connection
197
167
  end
198
168
  end
199
169
 
200
170
  def shard_env
201
- ActiveRecordShards.app_env
171
+ ActiveRecordShards.rails_env
202
172
  end
203
173
 
204
- # Make these few schema related methods available before having switched to
205
- # a shard.
206
- def with_default_shard(&block)
174
+ def with_default_shard
207
175
  if is_sharded? && current_shard_id.nil? && table_name != ActiveRecord::SchemaMigration.table_name
208
- on_first_shard(&block)
176
+ on_first_shard { yield }
209
177
  else
210
178
  yield
211
179
  end
212
180
  end
213
181
 
214
- if ActiveRecord::VERSION::MAJOR >= 5
215
- def load_schema_with_default_shard!
216
- with_default_shard { load_schema_without_default_shard! }
217
- end
218
- else
219
- def columns_with_default_shard
220
- with_default_shard { columns_without_default_shard }
221
- end
182
+ def load_schema_with_default_shard!
183
+ with_default_shard { load_schema_without_default_shard! }
222
184
  end
223
185
 
224
186
  def table_exists_with_default_shard?
225
187
  with_default_shard { table_exists_without_default_shard? }
226
188
  end
227
189
 
228
- class PrimaryReplicaProxy
190
+ class MasterSlaveProxy
229
191
  def initialize(target, which)
230
192
  @target = target
231
193
  @which = which
232
194
  end
233
195
 
234
- def method_missing(method, *args, &block) # rubocop:disable Style/MethodMissingSuper, Style/MissingRespondToMissing
235
- @target.on_primary_or_replica(@which) { @target.send(method, *args, &block) }
196
+ def method_missing(method, *args, &block) # rubocop:disable Style/MethodMissing
197
+ @target.on_master_or_slave(@which) { @target.send(method, *args, &block) }
236
198
  end
237
199
  end
238
-
239
- MasterSlaveProxy = PrimaryReplicaProxy
240
200
  end
241
201
  end
242
202
 
243
203
  case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
244
- when '4.2'
245
- require 'active_record_shards/connection_switcher-4-2'
246
204
  when '5.0'
247
205
  require 'active_record_shards/connection_switcher-5-0'
248
- when '5.1', '5.2'
206
+ when '5.1'
249
207
  require 'active_record_shards/connection_switcher-5-1'
250
- when '6.0'
251
- require 'active_record_shards/connection_switcher-6-0'
252
208
  else
253
209
  raise "ActiveRecordShards is not compatible with #{ActiveRecord::VERSION::STRING}"
254
210
  end
@@ -1,5 +1,136 @@
1
- ActiveRecordShards::Deprecation.warn('`DefaultSlavePatches` is deprecated, please use `DefaultReplicaPatches`.')
2
-
1
+ # frozen_string_literal: true
3
2
  module ActiveRecordShards
4
- DefaultSlavePatches = DefaultReplicaPatches
3
+ module DefaultSlavePatches
4
+ def self.wrap_method_in_on_slave(class_method, base, method)
5
+ base_methods =
6
+ if class_method
7
+ base.methods + base.private_methods
8
+ else
9
+ base.instance_methods + base.private_instance_methods
10
+ end
11
+
12
+ return unless base_methods.include?(method)
13
+ _, method, punctuation = method.to_s.match(/^(.*?)([\?\!]?)$/).to_a
14
+ base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
15
+ #{class_method ? 'class << self' : ''}
16
+ def #{method}_with_default_slave#{punctuation}(*args, &block)
17
+ on_slave_unless_tx do
18
+ #{method}_without_default_slave#{punctuation}(*args, &block)
19
+ end
20
+ end
21
+
22
+ alias_method :#{method}_without_default_slave#{punctuation}, :#{method}#{punctuation}
23
+ alias_method :#{method}#{punctuation}, :#{method}_with_default_slave#{punctuation}
24
+ #{class_method ? 'end' : ''}
25
+ RUBY
26
+ end
27
+
28
+ def columns_with_force_slave(*args, &block)
29
+ on_cx_switch_block(:slave, construct_ro_scope: false, force: true) do
30
+ columns_without_force_slave(*args, &block)
31
+ end
32
+ end
33
+
34
+ def table_exists_with_force_slave?(*args, &block)
35
+ on_cx_switch_block(:slave, construct_ro_scope: false, force: true) do
36
+ table_exists_without_force_slave?(*args, &block)
37
+ end
38
+ end
39
+
40
+ def transaction_with_slave_off(*args, &block)
41
+ if on_slave_by_default?
42
+ begin
43
+ old_val = Thread.current[:_active_record_shards_slave_off]
44
+ Thread.current[:_active_record_shards_slave_off] = true
45
+ transaction_without_slave_off(*args, &block)
46
+ ensure
47
+ Thread.current[:_active_record_shards_slave_off] = old_val
48
+ end
49
+ else
50
+ transaction_without_slave_off(*args, &block)
51
+ end
52
+ end
53
+
54
+ module InstanceMethods
55
+ # fix ActiveRecord to do the right thing, and use our aliased quote_value
56
+ def quote_value(*args, &block)
57
+ self.class.quote_value(*args, &block)
58
+ end
59
+
60
+ def reload_with_slave_off(*args, &block)
61
+ self.class.on_master { reload_without_slave_off(*args, &block) }
62
+ end
63
+ end
64
+
65
+ CLASS_SLAVE_METHODS = [:find_by_sql, :count_by_sql, :calculate, :find_one, :find_some, :find_every, :exists?].freeze
66
+
67
+ def self.extended(base)
68
+ CLASS_SLAVE_METHODS.each { |m| ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(true, base, m) }
69
+
70
+ base.class_eval do
71
+ include InstanceMethods
72
+
73
+ alias_method :reload_without_slave_off, :reload
74
+ alias_method :reload, :reload_with_slave_off
75
+
76
+ class << self
77
+ alias_method :columns_without_force_slave, :columns
78
+ alias_method :columns, :columns_with_force_slave
79
+
80
+ alias_method :table_exists_without_force_slave?, :table_exists?
81
+ alias_method :table_exists?, :table_exists_with_force_slave?
82
+
83
+ alias_method :transaction_without_slave_off, :transaction
84
+ alias_method :transaction, :transaction_with_slave_off
85
+ end
86
+ end
87
+ if ActiveRecord::Associations.const_defined?(:HasAndBelongsToManyAssociation)
88
+ ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, ActiveRecord::Associations::HasAndBelongsToManyAssociation, :construct_sql)
89
+ ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, ActiveRecord::Associations::HasAndBelongsToManyAssociation, :construct_find_options!)
90
+ end
91
+ end
92
+
93
+ def on_slave_unless_tx
94
+ if on_slave_by_default? && !Thread.current[:_active_record_shards_slave_off]
95
+ on_slave { yield }
96
+ else
97
+ yield
98
+ end
99
+ end
100
+
101
+ module ActiveRelationPatches
102
+ def self.included(base)
103
+ [:calculate, :exists?, :pluck, :find_with_associations].each do |m|
104
+ ActiveRecordShards::DefaultSlavePatches.wrap_method_in_on_slave(false, base, m)
105
+ end
106
+ end
107
+
108
+ def on_slave_unless_tx
109
+ @klass.on_slave_unless_tx { yield }
110
+ end
111
+ end
112
+
113
+ # in rails 4.1+, they create a join class that's used to pull in records for HABTM.
114
+ # this simplifies the hell out of our existence, because all we have to do is inerit on-slave-by-default
115
+ # down from the parent now.
116
+ module HasAndBelongsToManyBuilderExtension
117
+ def self.included(base)
118
+ base.class_eval do
119
+ alias_method :through_model_without_inherit_default_slave_from_lhs, :through_model
120
+ alias_method :through_model, :through_model_with_inherit_default_slave_from_lhs
121
+ end
122
+ end
123
+
124
+ def through_model_with_inherit_default_slave_from_lhs
125
+ model = through_model_without_inherit_default_slave_from_lhs
126
+ def model.on_slave_by_default?
127
+ left_reflection.klass.on_slave_by_default?
128
+ end
129
+
130
+ model.extend(ActiveRecordShards::Ext::ShardedModel) if model.left_reflection.klass.is_sharded?
131
+
132
+ model
133
+ end
134
+ end
135
+ end
5
136
  end
@@ -3,59 +3,44 @@
3
3
  module ActiveRecordShards
4
4
  module Model
5
5
  def not_sharded
6
- if self != ActiveRecord::Base && self != base_class
7
- raise "You should only call not_sharded on direct descendants of ActiveRecord::Base"
8
- end
9
-
10
- self.sharded = false
6
+ ActiveSupport::Deprecation.warn("Calling not_sharded is deprecated. "\
7
+ "Please ensure to still read from the "\
8
+ "account db slave after removing the "\
9
+ "call.")
11
10
  end
12
11
 
13
12
  def is_sharded? # rubocop:disable Naming/PredicateName
14
- if self == ActiveRecord::Base
15
- sharded != false && supports_sharding?
16
- elsif self == base_class
17
- if sharded.nil?
18
- ActiveRecord::Base.is_sharded?
19
- else
20
- sharded != false
21
- end
22
- else
23
- base_class.is_sharded?
24
- end
13
+ false
25
14
  end
26
15
 
27
- def on_replica_by_default?
16
+ def on_slave_by_default?
28
17
  if self == ActiveRecord::Base
29
18
  false
30
19
  else
31
20
  base = base_class
32
- if base.instance_variable_defined?(:@on_replica_by_default)
33
- base.instance_variable_get(:@on_replica_by_default)
21
+ if base.instance_variable_defined?(:@on_slave_by_default)
22
+ base.instance_variable_get(:@on_slave_by_default)
34
23
  end
35
24
  end
36
25
  end
37
- alias_method :on_slave_by_default?, :on_replica_by_default?
38
26
 
39
- def on_replica_by_default=(value)
27
+ def on_slave_by_default=(value)
40
28
  if self == ActiveRecord::Base
41
- raise ArgumentError, "Cannot set on_replica_by_default on ActiveRecord::Base"
29
+ raise ArgumentError, "Cannot set on_slave_by_default on ActiveRecord::Base"
42
30
  else
43
- base_class.instance_variable_set(:@on_replica_by_default, value)
31
+ base_class.instance_variable_set(:@on_slave_by_default, value)
44
32
  end
45
33
  end
46
- alias_method :on_slave_by_default=, :on_replica_by_default=
47
34
 
48
35
  module InstanceMethods
49
- def initialize_shard_and_replica
50
- @from_replica = !!self.class.current_shard_selection.options[:replica]
36
+ def initialize_shard_and_slave
37
+ @from_slave = !!self.class.current_shard_selection.options[:slave]
51
38
  @from_shard = self.class.current_shard_selection.options[:shard]
52
39
  end
53
- alias_method :initialize_shard_and_slave, :initialize_shard_and_replica
54
40
 
55
- def from_replica?
56
- @from_replica
41
+ def from_slave?
42
+ @from_slave
57
43
  end
58
- alias_method :from_slave?, :from_replica?
59
44
 
60
45
  def from_shard
61
46
  @from_shard
@@ -64,11 +49,7 @@ module ActiveRecordShards
64
49
 
65
50
  def self.extended(base)
66
51
  base.send(:include, InstanceMethods)
67
- base.after_initialize :initialize_shard_and_replica
52
+ base.after_initialize :initialize_shard_and_slave
68
53
  end
69
-
70
- private
71
-
72
- attr_accessor :sharded
73
54
  end
74
55
  end
@@ -1,91 +1,52 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module ActiveRecordShards
4
3
  class ShardSelection
5
- NO_SHARD = :_no_shard
6
- cattr_accessor :default_shard
7
-
8
- def initialize
9
- @on_replica = false
10
- @shard = nil
4
+ def initialize(shard)
5
+ @on_slave = false
6
+ self.shard = shard
11
7
  end
12
8
 
13
- if ActiveRecord::VERSION::MAJOR < 5
14
-
15
- def shard(klass = nil)
16
- if (@shard || self.class.default_shard) && (klass.nil? || klass.is_sharded?)
17
- if @shard == NO_SHARD
18
- nil
19
- else
20
- @shard || self.class.default_shard
21
- end
22
- end
23
- end
24
-
25
- def shard_name(klass = nil, try_replica = true)
26
- the_shard = shard(klass)
27
-
28
- @shard_names ||= {}
29
- @shard_names[ActiveRecordShards.app_env] ||= {}
30
- @shard_names[ActiveRecordShards.app_env][the_shard] ||= {}
31
- @shard_names[ActiveRecordShards.app_env][the_shard][try_replica] ||= {}
32
- @shard_names[ActiveRecordShards.app_env][the_shard][try_replica][@on_replica] ||= begin
33
- s = ActiveRecordShards.app_env.dup
34
- s << "_shard_#{the_shard}" if the_shard
35
- s << "_replica" if @on_replica && try_replica
36
- s
37
- end
38
- end
9
+ def shard
10
+ raise "Missing shard information on connection" unless @shard
11
+ @shard
12
+ end
39
13
 
40
- else
14
+ PRIMARY = "primary".freeze
15
+ def resolve_connection_name(sharded:, configurations:)
16
+ resolved_shard = sharded ? shard : nil
41
17
 
42
- def shard
43
- if @shard.nil? || @shard == NO_SHARD
44
- nil
45
- else
46
- @shard || self.class.default_shard
47
- end
18
+ if !resolved_shard && !@on_slave
19
+ return PRIMARY
48
20
  end
49
21
 
50
- PRIMARY = "primary"
51
- def resolve_connection_name(sharded:, configurations:)
52
- resolved_shard = sharded ? shard : nil
53
- env = ActiveRecordShards.app_env
22
+ @shard_names ||= {}
23
+ @shard_names[ActiveRecordShards.rails_env] ||= {}
24
+ @shard_names[ActiveRecordShards.rails_env][resolved_shard] ||= {}
25
+ @shard_names[ActiveRecordShards.rails_env][resolved_shard][@on_slave] ||= begin
26
+ s = ActiveRecordShards.rails_env.dup
27
+ s << "_shard_#{resolved_shard}" if resolved_shard
54
28
 
55
- @connection_names ||= {}
56
- @connection_names[env] ||= {}
57
- @connection_names[env][resolved_shard] ||= {}
58
- @connection_names[env][resolved_shard][@on_replica] ||= begin
59
- name = env.dup
60
- name << "_shard_#{resolved_shard}" if resolved_shard
61
- if @on_replica && configurations["#{name}_replica"]
62
- "#{name}_replica"
63
- else
64
- # ActiveRecord always names its default connection pool 'primary'
65
- # while everything else is named by the configuration name
66
- resolved_shard ? name : PRIMARY
67
- end
29
+ if @on_slave && configurations["#{s}_slave"] # fall back to master connection
30
+ s << "_slave"
68
31
  end
32
+ s
69
33
  end
70
-
71
34
  end
72
35
 
73
36
  def shard=(new_shard)
74
- @shard = (new_shard || NO_SHARD)
37
+ @shard = Integer(new_shard)
75
38
  end
76
39
 
77
- def on_replica?
78
- @on_replica
40
+ def on_slave?
41
+ @on_slave
79
42
  end
80
- alias_method :on_slave?, :on_replica?
81
43
 
82
- def on_replica=(new_replica)
83
- @on_replica = (new_replica == true)
44
+ def on_slave=(new_slave)
45
+ @on_slave = (new_slave == true)
84
46
  end
85
- alias_method :on_slave=, :on_replica=
86
47
 
87
48
  def options
88
- { shard: @shard, replica: @on_replica }
49
+ { shard: @shard, slave: @on_slave }
89
50
  end
90
51
  end
91
52
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module ActiveRecordShards
4
3
  class ShardSupport
5
4
  class ShardEnumerator
@@ -0,0 +1,15 @@
1
+ module ActiveRecordShards
2
+ module Ext
3
+ module ShardedModel
4
+ def is_sharded? # rubocop:disable Naming/PredicateName
5
+ true
6
+ end
7
+ end
8
+ end
9
+
10
+ class ShardedModel < ActiveRecord::Base
11
+ self.abstract_class = true
12
+
13
+ extend ActiveRecordShards::Ext::ShardedModel
14
+ end
15
+ end