switchman 3.4.2 → 3.6.7

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +15 -14
  3. data/db/migrate/20180828183945_add_default_shard_index.rb +1 -1
  4. data/db/migrate/20190114212900_add_unique_name_indexes.rb +10 -4
  5. data/lib/switchman/active_record/abstract_adapter.rb +4 -2
  6. data/lib/switchman/active_record/associations.rb +89 -16
  7. data/lib/switchman/active_record/attribute_methods.rb +67 -22
  8. data/lib/switchman/active_record/base.rb +112 -22
  9. data/lib/switchman/active_record/calculations.rb +93 -37
  10. data/lib/switchman/active_record/connection_handler.rb +18 -0
  11. data/lib/switchman/active_record/connection_pool.rb +18 -14
  12. data/lib/switchman/active_record/database_configurations.rb +37 -15
  13. data/lib/switchman/active_record/finder_methods.rb +44 -14
  14. data/lib/switchman/active_record/log_subscriber.rb +11 -5
  15. data/lib/switchman/active_record/migration.rb +28 -9
  16. data/lib/switchman/active_record/pending_migration_connection.rb +17 -0
  17. data/lib/switchman/active_record/persistence.rb +22 -0
  18. data/lib/switchman/active_record/postgresql_adapter.rb +11 -10
  19. data/lib/switchman/active_record/predicate_builder.rb +2 -2
  20. data/lib/switchman/active_record/query_cache.rb +49 -20
  21. data/lib/switchman/active_record/query_methods.rb +93 -30
  22. data/lib/switchman/active_record/relation.rb +22 -11
  23. data/lib/switchman/active_record/spawn_methods.rb +2 -2
  24. data/lib/switchman/active_record/statement_cache.rb +2 -2
  25. data/lib/switchman/active_record/tasks/database_tasks.rb +6 -1
  26. data/lib/switchman/active_record/test_fixtures.rb +26 -16
  27. data/lib/switchman/active_support/cache.rb +9 -4
  28. data/lib/switchman/arel.rb +34 -18
  29. data/lib/switchman/call_super.rb +2 -8
  30. data/lib/switchman/database_server.rb +68 -21
  31. data/lib/switchman/default_shard.rb +14 -3
  32. data/lib/switchman/engine.rb +39 -19
  33. data/lib/switchman/environment.rb +2 -2
  34. data/lib/switchman/errors.rb +4 -1
  35. data/lib/switchman/guard_rail/relation.rb +1 -2
  36. data/lib/switchman/parallel.rb +5 -5
  37. data/lib/switchman/r_spec_helper.rb +11 -11
  38. data/lib/switchman/shard.rb +166 -64
  39. data/lib/switchman/sharded_instrumenter.rb +7 -3
  40. data/lib/switchman/standard_error.rb +4 -0
  41. data/lib/switchman/test_helper.rb +2 -2
  42. data/lib/switchman/version.rb +1 -1
  43. data/lib/switchman.rb +27 -15
  44. data/lib/tasks/switchman.rake +117 -51
  45. metadata +19 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28d87755bf2331cbbf2931e7d35dddd688983c168c583b27dd60ae58d78072db
4
- data.tar.gz: 500e141f914db02c5dd51cd9a595abc00306750a418641ceb09adb7cee207de7
3
+ metadata.gz: 2e86d08703a350aa5b8d3d843c51a0813f00e6ee0c681d0c95094f84863b327b
4
+ data.tar.gz: f13e438d68d996f55c9be543cc8cb89967b62f9ddd111ab4fae188da8b959096
5
5
  SHA512:
6
- metadata.gz: 94c9b870a65599c0d5775d32cd9dd1bfc3235c541eeb07127e5e8e8c773447da3ba1e0460ce8a340709354aceede546b9d6ccf8dd0360bff7e494f267a6791e1
7
- data.tar.gz: 6ea8348a8aaa9eb80ae763d2c8ccca23949e329f0f9ae2df7eef59344fdf3d4660b6e7419f479bc5d67be5e42fdd73f49abf7f0ceb853c0469c38b0899559424
6
+ metadata.gz: 7be63615d79be0b46184b9e6754bcb6091873e2eb0c4722705daea7dd81dd50320819b2238538c818637901570c2ad47a7ed62febd441c4d5b130c78391554cc
7
+ data.tar.gz: c3eb6290f9437ccac7162216840c2f258f31fc6c978121b9054c6308640bff6d522f2f61fd2247fea178c1c173a012a4d7f2c22b2e234d7b4f431ce4b8306403
data/Rakefile CHANGED
@@ -2,37 +2,38 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  begin
5
- require 'bundler/setup'
5
+ require "bundler/setup"
6
6
  rescue LoadError
7
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
8
8
  end
9
9
  begin
10
- require 'rdoc/task'
10
+ require "rdoc/task"
11
11
  rescue LoadError
12
- require 'rdoc/rdoc'
13
- require 'rake/rdoctask'
12
+ require "rdoc/rdoc"
13
+ require "rake/rdoctask"
14
14
  RDoc::Task = Rake::RDocTask
15
15
  end
16
16
 
17
17
  RDoc::Task.new(:rdoc) do |rdoc|
18
- rdoc.rdoc_dir = 'rdoc'
19
- rdoc.title = 'Switchman'
20
- rdoc.options << '--line-numbers'
21
- rdoc.rdoc_files.include('lib/**/*.rb')
18
+ rdoc.rdoc_dir = "rdoc"
19
+ rdoc.title = "Switchman"
20
+ rdoc.options << "--line-numbers"
21
+ rdoc.rdoc_files.include("lib/**/*.rb")
22
22
  end
23
23
 
24
- APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
25
- load 'rails/tasks/engine.rake'
24
+ load "./spec/tasks/coverage.rake"
25
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
26
+ load "rails/tasks/engine.rake"
26
27
 
27
28
  Bundler::GemHelper.install_tasks
28
29
 
29
- require 'rspec/core/rake_task'
30
+ require "rspec/core/rake_task"
30
31
  RSpec::Core::RakeTask.new
31
32
 
32
- require 'rubocop/rake_task'
33
+ require "rubocop/rake_task"
33
34
 
34
35
  RuboCop::RakeTask.new do |task|
35
- task.options = ['-S']
36
+ task.options = ["-S"]
36
37
  end
37
38
 
38
39
  task default: %i[spec]
@@ -5,7 +5,7 @@ class AddDefaultShardIndex < ActiveRecord::Migration[4.2]
5
5
  Switchman::Shard.where(default: nil).update_all(default: false) if Switchman::Shard.current.default?
6
6
  change_column_default :switchman_shards, :default, false
7
7
  change_column_null :switchman_shards, :default, false
8
- options = if connection.adapter_name == 'PostgreSQL'
8
+ options = if connection.adapter_name == "PostgreSQL"
9
9
  { unique: true, where: '"default"' }
10
10
  else
11
11
  {}
@@ -3,9 +3,15 @@
3
3
  class AddUniqueNameIndexes < ActiveRecord::Migration[4.2]
4
4
  def change
5
5
  add_index :switchman_shards, %i[database_server_id name], unique: true
6
- add_index :switchman_shards, :database_server_id, unique: true, where: 'name IS NULL',
7
- name: 'index_switchman_shards_unique_primary_shard'
8
- add_index :switchman_shards, '(true)', unique: true, where: 'database_server_id IS NULL AND name IS NULL',
9
- name: 'index_switchman_shards_unique_primary_db_and_shard'
6
+ add_index :switchman_shards,
7
+ :database_server_id,
8
+ unique: true,
9
+ where: "name IS NULL",
10
+ name: "index_switchman_shards_unique_primary_shard"
11
+ add_index :switchman_shards,
12
+ "(true)",
13
+ unique: true,
14
+ where: "database_server_id IS NULL AND name IS NULL",
15
+ name: "index_switchman_shards_unique_primary_db_and_shard"
10
16
  end
11
17
  end
@@ -27,8 +27,10 @@ module Switchman
27
27
  quote_table_name(name)
28
28
  end
29
29
 
30
- def schema_migration
31
- ::ActiveRecord::SchemaMigration
30
+ if ::Rails.version < "7.1"
31
+ def schema_migration
32
+ ::ActiveRecord::SchemaMigration
33
+ end
32
34
  end
33
35
 
34
36
  protected
@@ -24,11 +24,23 @@ module Switchman
24
24
 
25
25
  module CollectionAssociation
26
26
  def find_target
27
- shards = reflection.options[:multishard] && owner.respond_to?(:associated_shards) ? owner.associated_shards : [shard]
27
+ shards = if reflection.options[:multishard] && owner.respond_to?(:associated_shards)
28
+ owner.associated_shards
29
+ else
30
+ [shard]
31
+ end
28
32
  # activate both the owner and the target's shard category, so that Reflection#join_id_for,
29
33
  # when called for the owner, will be returned relative to shard the query will execute on
30
- Shard.with_each_shard(shards, [klass.connection_class_for_self, owner.class.connection_class_for_self].uniq) do
31
- super
34
+ Shard.with_each_shard(shards,
35
+ [klass.connection_class_for_self, owner.class.connection_class_for_self].uniq) do
36
+ if reflection.options[:multishard] && owner.respond_to?(:associated_shards) && reflection.has_scope?
37
+ # Prevent duplicate results when reflection has a scope (when it would use the skip_statement_cache? path)
38
+ # otherwise, the super call will set the shard_value to the object, causing it to iterate too many times
39
+ # over the associated shards
40
+ scope.shard(Shard.current(scope.klass.connection_class_for_self), :association).to_a
41
+ else
42
+ super
43
+ end
32
44
  end
33
45
  end
34
46
 
@@ -128,7 +140,12 @@ module Switchman
128
140
  Shard.lookup(shard).activate do
129
141
  scope_was = loader_query.scope
130
142
  begin
131
- loader_query.instance_variable_set(:@scope, loader_query.scope.shard(Shard.current(loader_query.scope.model.connection_class_for_self)))
143
+ loader_query.instance_variable_set(
144
+ :@scope,
145
+ loader_query.scope.shard(
146
+ Shard.current(loader_query.scope.model.connection_class_for_self)
147
+ )
148
+ )
132
149
  ret += loader_query.load_records_for_keys(keys) do |record|
133
150
  loaders.each { |l| l.set_inverse(record) }
134
151
  end
@@ -186,7 +203,7 @@ module Switchman
186
203
  # #compare_by_identity makes such owners different hash keys
187
204
  @records_by_owner = {}.compare_by_identity
188
205
 
189
- if ::Rails.version >= '7.0'
206
+ if ::Rails.version >= "7.0"
190
207
  raw_records ||= loader_query.records_for([self])
191
208
  elsif owner_keys.empty?
192
209
  raw_records ||= []
@@ -210,7 +227,8 @@ module Switchman
210
227
  relative_owner_keys = partitioned_owners.map do |owner|
211
228
  key = owner[owner_key_name]
212
229
  if key && owner.class.sharded_column?(owner_key_name)
213
- key = Shard.relative_id_for(key, owner.shard,
230
+ key = Shard.relative_id_for(key,
231
+ owner.shard,
214
232
  Shard.current(klass.connection_class_for_self))
215
233
  end
216
234
  convert_key(key)
@@ -273,18 +291,73 @@ module Switchman
273
291
  end
274
292
 
275
293
  module AutosaveAssociation
276
- def association_foreign_key_changed?(reflection, record, key)
277
- return false if reflection.through_reflection?
294
+ if ::Rails.version < "7.1"
295
+ def association_foreign_key_changed?(reflection, record, key)
296
+ return false if reflection.through_reflection?
278
297
 
279
- # have to use send instead of _read_attribute because sharding
280
- record.has_attribute?(reflection.foreign_key) && record.send(reflection.foreign_key) != key
281
- end
298
+ # have to use send instead of _read_attribute because sharding
299
+ record.has_attribute?(reflection.foreign_key) && record.send(reflection.foreign_key) != key
300
+ end
301
+
302
+ def save_belongs_to_association(reflection)
303
+ # this seems counter-intuitive, but the autosave code will assign to attribute bypassing switchman,
304
+ # after reading the id attribute _without_ bypassing switchman. So we need Shard.current for the
305
+ # category of the associated record to match Shard.current for the category of self
306
+ shard.activate(connection_class_for_self_for_reflection(reflection)) { super }
307
+ end
308
+ else
309
+ def association_foreign_key_changed?(reflection, record, key)
310
+ return false if reflection.through_reflection?
311
+
312
+ foreign_key = Array(reflection.foreign_key)
313
+ return false unless foreign_key.all? { |k| record._has_attribute?(k) }
314
+
315
+ # have to use send instead of _read_attribute because sharding
316
+ foreign_key.map { |k| record.send(k) } != Array(key)
317
+ end
282
318
 
283
- def save_belongs_to_association(reflection)
284
- # this seems counter-intuitive, but the autosave code will assign to attribute bypassing switchman,
285
- # after reading the id attribute _without_ bypassing switchman. So we need Shard.current for the
286
- # category of the associated record to match Shard.current for the category of self
287
- shard.activate(connection_class_for_self_for_reflection(reflection)) { super }
319
+ def save_belongs_to_association(reflection)
320
+ association = association_instance_get(reflection.name)
321
+ return unless association&.loaded? && !association.stale_target?
322
+
323
+ record = association.load_target
324
+ return unless record && !record.destroyed?
325
+
326
+ autosave = reflection.options[:autosave]
327
+
328
+ if autosave && record.marked_for_destruction?
329
+ foreign_key = Array(reflection.foreign_key)
330
+ foreign_key.each { |key| self[key] = nil }
331
+ record.destroy
332
+ elsif autosave != false
333
+ if record.new_record? || (autosave && record.changed_for_autosave?)
334
+ saved = record.save(validate: !autosave)
335
+ end
336
+
337
+ if association.updated?
338
+ primary_key = Array(compute_primary_key(reflection, record)).map(&:to_s)
339
+ foreign_key = Array(reflection.foreign_key)
340
+
341
+ primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
342
+ primary_key_foreign_key_pairs.each do |pk, fk|
343
+ # Notable change: add relative_id_for here
344
+ association_id = if record.class.sharded_column?(pk)
345
+ Shard.relative_id_for(
346
+ record._read_attribute(pk),
347
+ record.shard,
348
+ shard
349
+ )
350
+ else
351
+ record._read_attribute(pk)
352
+ end
353
+ self[fk] = association_id unless self[fk] == association_id
354
+ end
355
+ association.loaded!
356
+ end
357
+
358
+ saved if autosave
359
+ end
360
+ end
288
361
  end
289
362
  end
290
363
  end
@@ -31,8 +31,16 @@ module Switchman
31
31
  # and not the silly one in AR::AttributeMethods::PrimaryKey
32
32
  return unless sharded_column?(@primary_key)
33
33
 
34
- class_eval(build_sharded_getter('id', '_read_attribute(@primary_key)', "::#{connection_class_for_self.name}"), __FILE__, __LINE__)
35
- class_eval(build_sharded_setter('id', @primary_key, "::#{connection_class_for_self.name}"), __FILE__, __LINE__)
34
+ class_eval(
35
+ build_sharded_getter("id",
36
+ "_read_attribute(@primary_key)",
37
+ "::#{connection_class_for_self.name}"),
38
+ __FILE__,
39
+ __LINE__
40
+ )
41
+ class_eval(build_sharded_setter("id", @primary_key, "::#{connection_class_for_self.name}"),
42
+ __FILE__,
43
+ __LINE__)
36
44
  end
37
45
 
38
46
  protected
@@ -47,7 +55,7 @@ module Switchman
47
55
  end
48
56
 
49
57
  def define_cached_method(owner, name, namespace:, as:, &block)
50
- if ::Rails.version < '7.0'
58
+ if ::Rails.version < "7.0"
51
59
  yield owner
52
60
  owner.rename_method(as, name)
53
61
  else
@@ -57,7 +65,10 @@ module Switchman
57
65
 
58
66
  def define_method_global_attribute(attr_name, owner:)
59
67
  if sharded_column?(attr_name)
60
- define_cached_method(owner, "global_#{attr_name}", as: "sharded_global_#{attr_name}", namespace: :switchman) do |batch|
68
+ define_cached_method(owner,
69
+ "global_#{attr_name}",
70
+ as: "sharded_global_#{attr_name}",
71
+ namespace: :switchman) do |batch|
61
72
  batch << <<-RUBY
62
73
  def sharded_global_#{attr_name}
63
74
  raw_value = original_#{attr_name}
@@ -69,13 +80,16 @@ module Switchman
69
80
  RUBY
70
81
  end
71
82
  else
72
- define_method_unsharded_column(attr_name, 'global', owner)
83
+ define_method_unsharded_column(attr_name, "global", owner)
73
84
  end
74
85
  end
75
86
 
76
87
  def define_method_local_attribute(attr_name, owner:)
77
88
  if sharded_column?(attr_name)
78
- define_cached_method(owner, "local_#{attr_name}", as: "sharded_local_#{attr_name}", namespace: :switchman) do |batch|
89
+ define_cached_method(owner,
90
+ "local_#{attr_name}",
91
+ as: "sharded_local_#{attr_name}",
92
+ namespace: :switchman) do |batch|
79
93
  batch << <<-RUBY
80
94
  def sharded_local_#{attr_name}
81
95
  raw_value = original_#{attr_name}
@@ -85,7 +99,7 @@ module Switchman
85
99
  RUBY
86
100
  end
87
101
  else
88
- define_method_unsharded_column(attr_name, 'local', owner)
102
+ define_method_unsharded_column(attr_name, "local", owner)
89
103
  end
90
104
  end
91
105
 
@@ -97,7 +111,13 @@ module Switchman
97
111
  if reflection.options[:polymorphic]
98
112
  # a polymorphic association has to be discovered at runtime. This code ends up being something like
99
113
  # context_type.&.constantize&.connection_class_for_self
100
- "begin;read_attribute(:#{reflection.foreign_type})&.constantize&.connection_class_for_self;rescue NameError;::ActiveRecord::Base;end"
114
+ <<~RUBY
115
+ begin
116
+ read_attribute(:#{reflection.foreign_type})&.constantize&.connection_class_for_self
117
+ rescue NameError
118
+ ::ActiveRecord::Base
119
+ end
120
+ RUBY
101
121
  else
102
122
  # otherwise we can just return a symbol for the statically known type of the association
103
123
  "::#{reflection.klass.connection_class_for_self.name}"
@@ -111,9 +131,14 @@ module Switchman
111
131
  if sharded_column?(attr_name)
112
132
  reflection = reflection_for_integer_attribute(attr_name)
113
133
  class_name = connection_class_for_self_code_for_reflection(reflection)
114
- safe_class_name = class_name.unpack1('h*')
115
- define_cached_method(owner, attr_name, as: "sharded_#{safe_class_name}_#{attr_name}", namespace: :switchman) do |batch|
116
- batch << build_sharded_getter("sharded_#{safe_class_name}_#{attr_name}", "original_#{attr_name}", class_name)
134
+ safe_class_name = class_name.unpack1("h*")
135
+ define_cached_method(owner,
136
+ attr_name,
137
+ as: "sharded_#{safe_class_name}_#{attr_name}",
138
+ namespace: :switchman) do |batch|
139
+ batch << build_sharded_getter("sharded_#{safe_class_name}_#{attr_name}",
140
+ "original_#{attr_name}",
141
+ class_name)
117
142
  end
118
143
  else
119
144
  define_cached_method(owner, attr_name, as: "plain_#{attr_name}", namespace: :switchman) do |batch|
@@ -153,8 +178,11 @@ module Switchman
153
178
  if sharded_column?(attr_name)
154
179
  reflection = reflection_for_integer_attribute(attr_name)
155
180
  class_name = connection_class_for_self_code_for_reflection(reflection)
156
- safe_class_name = class_name.unpack1('h*')
157
- define_cached_method(owner, "#{attr_name}=", as: "sharded_#{safe_class_name}_#{attr_name}=", namespace: :switchman) do |batch|
181
+ safe_class_name = class_name.unpack1("h*")
182
+ define_cached_method(owner,
183
+ "#{attr_name}=",
184
+ as: "sharded_#{safe_class_name}_#{attr_name}=",
185
+ namespace: :switchman) do |batch|
158
186
  batch << build_sharded_setter("sharded_#{safe_class_name}_#{attr_name}", attr_name, class_name)
159
187
  end
160
188
  else
@@ -178,7 +206,10 @@ module Switchman
178
206
 
179
207
  def define_method_original_attribute(attr_name, owner:)
180
208
  if sharded_column?(attr_name)
181
- define_cached_method(owner, "original_#{attr_name}", as: "sharded_original_#{attr_name}", namespace: :switchman) do |batch|
209
+ define_cached_method(owner,
210
+ "original_#{attr_name}",
211
+ as: "sharded_original_#{attr_name}",
212
+ namespace: :switchman) do |batch|
182
213
  batch << <<-RUBY
183
214
  def sharded_original_#{attr_name}
184
215
  _read_attribute("#{attr_name}") { |n| missing_attribute(n, caller) }
@@ -186,14 +217,17 @@ module Switchman
186
217
  RUBY
187
218
  end
188
219
  else
189
- define_method_unsharded_column(attr_name, 'global', owner)
220
+ define_method_unsharded_column(attr_name, "global", owner)
190
221
  end
191
222
  end
192
223
 
193
224
  def define_method_original_attribute=(attr_name, owner:)
194
225
  return unless sharded_column?(attr_name)
195
226
 
196
- define_cached_method(owner, "original_#{attr_name}=", as: "sharded_original_#{attr_name}=", namespace: :switchman) do |batch|
227
+ define_cached_method(owner,
228
+ "original_#{attr_name}=",
229
+ as: "sharded_original_#{attr_name}=",
230
+ namespace: :switchman) do |batch|
197
231
  batch << <<-RUBY
198
232
  def sharded_original_#{attr_name}=(new_value)
199
233
  _write_attribute('#{attr_name}', new_value)
@@ -203,9 +237,12 @@ module Switchman
203
237
  end
204
238
 
205
239
  def define_method_unsharded_column(attr_name, prefix, owner)
206
- return if columns_hash["#{prefix}_#{attr_name}"] || attr_name == 'id'
240
+ return if columns_hash["#{prefix}_#{attr_name}"] || attr_name == "id"
207
241
 
208
- define_cached_method(owner, "#{prefix}_#{attr_name}", as: "unsharded_#{prefix}_#{attr_name}", namespace: :switchman) do |batch|
242
+ define_cached_method(owner,
243
+ "#{prefix}_#{attr_name}",
244
+ as: "unsharded_#{prefix}_#{attr_name}",
245
+ namespace: :switchman) do |batch|
209
246
  batch << <<-RUBY
210
247
  def unsharded_#{prefix}_#{attr_name}
211
248
  raise NoMethodError, "undefined method `#{prefix}_#{attr_name}'; are you missing an association?"
@@ -217,8 +254,8 @@ module Switchman
217
254
 
218
255
  def self.prepended(klass)
219
256
  klass.singleton_class.prepend(ClassMethods)
220
- klass.attribute_method_prefix 'global_', 'local_', 'original_'
221
- klass.attribute_method_affix prefix: 'original_', suffix: '='
257
+ klass.attribute_method_prefix "global_", "local_", "original_"
258
+ klass.attribute_method_affix prefix: "original_", suffix: "="
222
259
  end
223
260
 
224
261
  # these are called if the specific methods haven't been defined yet
@@ -226,7 +263,11 @@ module Switchman
226
263
  return super unless self.class.sharded_column?(attr_name)
227
264
 
228
265
  reflection = self.class.send(:reflection_for_integer_attribute, attr_name)
229
- ::Switchman::Shard.relative_id_for(super, shard, ::Switchman::Shard.current(connection_class_for_self_for_reflection(reflection)))
266
+ ::Switchman::Shard.relative_id_for(
267
+ super,
268
+ shard,
269
+ ::Switchman::Shard.current(connection_class_for_self_for_reflection(reflection))
270
+ )
230
271
  end
231
272
 
232
273
  def attribute=(attr_name, new_value)
@@ -236,7 +277,11 @@ module Switchman
236
277
  end
237
278
 
238
279
  reflection = self.class.send(:reflection_for_integer_attribute, attr_name)
239
- super(::Switchman::Shard.relative_id_for(new_value, ::Switchman::Shard.current(connection_class_for_self_for_reflection(reflection)), shard))
280
+ super(attr_name, ::Switchman::Shard.relative_id_for(
281
+ new_value,
282
+ ::Switchman::Shard.current(connection_class_for_self_for_reflection(reflection)),
283
+ shard
284
+ ))
240
285
  end
241
286
 
242
287
  def global_attribute(attr_name)