activerecord-turntable 4.1.0 → 4.2.0

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 (36) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile +5 -2
  5. data/README.md +1 -1
  6. data/Rakefile +1 -1
  7. data/activerecord-turntable.gemspec +4 -4
  8. data/gemfiles/rails5_0_0.gemfile +2 -0
  9. data/gemfiles/rails5_0_1.gemfile +3 -0
  10. data/gemfiles/rails5_0_2.gemfile +3 -0
  11. data/gemfiles/rails5_0_3.gemfile +3 -0
  12. data/gemfiles/rails5_0_4.gemfile +3 -0
  13. data/gemfiles/rails5_0_5.gemfile +3 -0
  14. data/gemfiles/rails5_0_6.gemfile +3 -0
  15. data/gemfiles/rails5_0_7.gemfile +3 -0
  16. data/gemfiles/rails5_1_0.gemfile +3 -0
  17. data/gemfiles/rails5_1_1.gemfile +3 -0
  18. data/gemfiles/rails5_1_2.gemfile +3 -0
  19. data/gemfiles/rails5_1_3.gemfile +3 -0
  20. data/gemfiles/rails5_1_4.gemfile +3 -0
  21. data/gemfiles/rails5_1_5.gemfile +3 -0
  22. data/gemfiles/rails5_1_6.gemfile +3 -0
  23. data/gemfiles/rails5_2_0.gemfile +9 -0
  24. data/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +22 -0
  25. data/lib/active_record/turntable/active_record_ext/association.rb +8 -2
  26. data/lib/active_record/turntable/active_record_ext/association_preloader.rb +16 -6
  27. data/lib/active_record/turntable/active_record_ext/fixtures.rb +47 -45
  28. data/lib/active_record/turntable/active_record_ext/locking_optimistic.rb +14 -7
  29. data/lib/active_record/turntable/active_record_ext/persistence.rb +69 -26
  30. data/lib/active_record/turntable/active_record_ext/query_cache.rb +3 -0
  31. data/lib/active_record/turntable/migration.rb +42 -1
  32. data/lib/active_record/turntable/pool_proxy.rb +5 -1
  33. data/lib/active_record/turntable/sharding_condition.rb +6 -3
  34. data/lib/active_record/turntable/util.rb +16 -1
  35. data/lib/active_record/turntable/version.rb +1 -1
  36. metadata +16 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 31aa02feae321af087a80d9a1f9177c0ff7c139a
4
- data.tar.gz: dbb3b7404067e3a2b756b96eaa5f76a51e27450d
2
+ SHA256:
3
+ metadata.gz: 4cced005d4106f1fe4e91d38fa233de92139928169754bb96303ab14e11e731b
4
+ data.tar.gz: 80e4e77bcc89380430968ee18b5831667db76ca0872c734879456f9b9aacccdf
5
5
  SHA512:
6
- metadata.gz: 3bb4919921852779beb4b1d31f67f524e5985921c5d00d613799417a769c80eeaf3eec5cd51deaa5ea061cdc0869b8295b785806a5febb2ca7979924482ac79b
7
- data.tar.gz: e5f313cc055e68af9520db17c29edcb717b8459b3ccb65819fe9d17e08010937a938277fc2baafa469b4fb8555a7f8f88a1344cf89064eff3a6d259e2cd6fe12
6
+ metadata.gz: '04769f9f47f94395e4bb5fda699e4807ca992283f5cf2c11abab2cb498757bd8e07ff6062d4cf8f130f6ec3244f65c844347f95adbb5e967555560bca07b4b9d'
7
+ data.tar.gz: 272bcec55c63d01b7488f5c480d0ce7dd77e0bfe57de18e3222736b5d838a53e460bee872e7040a29c6521541201fcfc70fda298bc636f02cf547cf98d995f98
@@ -27,6 +27,7 @@ gemfile:
27
27
  - gemfiles/rails5_1_4.gemfile
28
28
  - gemfiles/rails5_1_5.gemfile
29
29
  - gemfiles/rails5_1_6.gemfile
30
+ - gemfiles/rails5_2_0.gemfile
30
31
  - gemfiles/rails_edge.gemfile
31
32
 
32
33
  env:
@@ -1,3 +1,9 @@
1
+ ## activerecord-turntable 4.2.0 ##
2
+
3
+ ### Major Changes
4
+
5
+ * Support activerecord v5.2.0
6
+
1
7
  ## activerecord-turntable 4.1.0 ##
2
8
 
3
9
  ### Major Changes
data/Gemfile CHANGED
@@ -2,5 +2,8 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem "activerecord", "~> 5.1.6"
6
- gem "activesupport", "~> 5.1.6"
5
+ gem "rails", "5.2.0"
6
+
7
+ gem "actionview", "5.2.0"
8
+ gem "activerecord", "5.2.0"
9
+ gem "activesupport", "5.2.0"
data/README.md CHANGED
@@ -27,7 +27,7 @@ MySQL only.
27
27
  Add to Gemfile:
28
28
 
29
29
  ```ruby
30
- gem 'activerecord-turntable', '~> 4.1.0'
30
+ gem 'activerecord-turntable', '~> 4.2.0'
31
31
  ```
32
32
 
33
33
  Run a bundle install:
data/Rakefile CHANGED
@@ -76,7 +76,7 @@ namespace :turntable do
76
76
  system(*%w|git submodule update --init|)
77
77
  system(*%w|git submodule foreach git fetch origin|)
78
78
  Dir.chdir("tmp/rails") do
79
- system(*%W|git checkout #{ENV['ARVERSION']}|)
79
+ system(*%W|git checkout #{ENV["ARVERSION"]}|)
80
80
  end
81
81
  FileUtils.rm_r("test") if File.directory?("test")
82
82
  FileUtils.cp_r("tmp/rails/activerecord/test", ".")
@@ -3,7 +3,7 @@ require "active_record/turntable/version"
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "activerecord-turntable"
5
5
  spec.version = ActiveRecord::Turntable::VERSION
6
- spec.authors = %w(gussan sue445)
6
+ spec.authors = %w[gussan sue445]
7
7
  spec.homepage = "https://github.com/drecom/activerecord-turntable"
8
8
  spec.summary = "ActiveRecord sharding extension"
9
9
  spec.description = "ActiveRecord sharding extension"
@@ -38,7 +38,7 @@ Gem::Specification.new do |spec|
38
38
  spec.add_development_dependency "guard-rspec"
39
39
  spec.add_development_dependency "guard-rubocop"
40
40
  spec.add_development_dependency "httpclient", ">= 0"
41
- spec.add_development_dependency "mysql2"
41
+ spec.add_development_dependency "mysql2", "~> 0.4.4"
42
42
  spec.add_development_dependency "onkcop"
43
43
  spec.add_development_dependency "pry"
44
44
  spec.add_development_dependency "pry-byebug"
@@ -58,7 +58,7 @@ Gem::Specification.new do |spec|
58
58
  # activerecord testing dependencies
59
59
  spec.add_development_dependency "actionview"
60
60
  spec.add_development_dependency "bcrypt", "~> 3.1.11"
61
- spec.add_development_dependency "minitest", "< 5.3.4"
62
- spec.add_development_dependency "mocha", "~> 0.14"
61
+ spec.add_development_dependency "minitest"
62
+ spec.add_development_dependency "mocha"
63
63
  spec.add_development_dependency "sqlite3", "~> 1.3.6"
64
64
  end
@@ -5,4 +5,6 @@ gem "activesupport", "5.0.0"
5
5
 
6
6
  gem "mysql2", "~> 0.4.4"
7
7
 
8
+ gem "minitest", "< 5.3.4"
9
+
8
10
  gemspec :path => '../'
@@ -5,4 +5,7 @@ gem "activesupport", "5.0.1"
5
5
 
6
6
  gem "mysql2", "~> 0.4.4"
7
7
 
8
+ gem "minitest", "< 5.3.4"
9
+ gem "mocha", "~> 0.14", require: false
10
+
8
11
  gemspec :path => '../'
@@ -5,4 +5,7 @@ gem "activesupport", "5.0.2"
5
5
 
6
6
  gem "mysql2", "~> 0.4.4"
7
7
 
8
+ gem "minitest", "< 5.3.4"
9
+ gem "mocha", "~> 0.14", require: false
10
+
8
11
  gemspec :path => '../'
@@ -5,4 +5,7 @@ gem "activesupport", "5.0.3"
5
5
 
6
6
  gem "mysql2", "~> 0.4.4"
7
7
 
8
+ gem "minitest", "< 5.3.4"
9
+ gem "mocha", "~> 0.14", require: false
10
+
8
11
  gemspec :path => '../'
@@ -5,4 +5,7 @@ gem "activesupport", "5.0.4"
5
5
 
6
6
  gem "mysql2", "~> 0.4.4"
7
7
 
8
+ gem "minitest", "< 5.3.4"
9
+ gem "mocha", "~> 0.14", require: false
10
+
8
11
  gemspec :path => '../'
@@ -5,4 +5,7 @@ gem "activesupport", "5.0.5"
5
5
 
6
6
  gem "mysql2", "~> 0.4.4"
7
7
 
8
+ gem "minitest", "< 5.3.4"
9
+ gem "mocha", "~> 0.14", require: false
10
+
8
11
  gemspec :path => '../'
@@ -5,4 +5,7 @@ gem "activesupport", "5.0.6"
5
5
 
6
6
  gem "mysql2", "~> 0.4.4"
7
7
 
8
+ gem "minitest", "< 5.3.4"
9
+ gem "mocha", "~> 0.14", require: false
10
+
8
11
  gemspec :path => '../'
@@ -3,4 +3,7 @@ source "https://rubygems.org"
3
3
  gem "activerecord", "5.0.7"
4
4
  gem "activesupport", "5.0.7"
5
5
 
6
+ gem "minitest", "< 5.3.4"
7
+ gem "mocha", "~> 0.14", require: false
8
+
6
9
  gemspec :path => '../'
@@ -6,4 +6,7 @@ gem "actionview", "5.1.0"
6
6
 
7
7
  gem "mysql2", "~> 0.4.4"
8
8
 
9
+ gem "minitest", "< 5.3.4"
10
+ gem "mocha", "~> 0.14", require: false
11
+
9
12
  gemspec :path => '../'
@@ -6,4 +6,7 @@ gem "actionview", "5.1.1"
6
6
 
7
7
  gem "mysql2", "~> 0.4.4"
8
8
 
9
+ gem "minitest", "< 5.3.4"
10
+ gem "mocha", "~> 0.14", require: false
11
+
9
12
  gemspec :path => '../'
@@ -6,4 +6,7 @@ gem "actionview", "5.1.2"
6
6
 
7
7
  gem "mysql2", "~> 0.4.4"
8
8
 
9
+ gem "minitest", "< 5.3.4"
10
+ gem "mocha", "~> 0.14", require: false
11
+
9
12
  gemspec :path => '../'
@@ -6,4 +6,7 @@ gem "actionview", "5.1.3"
6
6
 
7
7
  gem "mysql2", "~> 0.4.4"
8
8
 
9
+ gem "minitest", "< 5.3.4"
10
+ gem "mocha", "~> 0.14", require: false
11
+
9
12
  gemspec :path => '../'
@@ -6,4 +6,7 @@ gem "actionview", "5.1.4"
6
6
 
7
7
  gem "mysql2", "~> 0.4.4"
8
8
 
9
+ gem "minitest", "< 5.3.4"
10
+ gem "mocha", "~> 0.14", require: false
11
+
9
12
  gemspec :path => '../'
@@ -6,4 +6,7 @@ gem "actionview", "5.1.5"
6
6
 
7
7
  gem "mysql2", "~> 0.4.4"
8
8
 
9
+ gem "minitest", "< 5.3.4"
10
+ gem "mocha", "~> 0.14", require: false
11
+
9
12
  gemspec :path => '../'
@@ -4,4 +4,7 @@ gem "activerecord", "5.1.6"
4
4
  gem "activesupport", "5.1.6"
5
5
  gem "actionview", "5.1.6"
6
6
 
7
+ gem "minitest", "< 5.3.4"
8
+ gem "mocha", "~> 0.14", require: false
9
+
7
10
  gemspec :path => '../'
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "5.2.0"
4
+ gem "railties", "5.2.0"
5
+ gem "activerecord", "5.2.0"
6
+ gem "activesupport", "5.2.0"
7
+ gem "actionview", "5.2.0"
8
+
9
+ gemspec :path => '../'
@@ -23,6 +23,28 @@ module ActiveRecord::Turntable
23
23
 
24
24
  # @note override for append current shard name
25
25
  # rubocop:disable Style/HashSyntax, Style/MultilineMethodCallBraceLayout
26
+ module V5_2
27
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil)
28
+ @instrumenter.instrument(
29
+ "sql.active_record",
30
+ sql: sql,
31
+ name: name,
32
+ binds: binds,
33
+ type_casted_binds: type_casted_binds,
34
+ statement_name: statement_name,
35
+ connection_id: object_id,
36
+ turntable_shard_name: turntable_shard_name) do
37
+ begin
38
+ @lock.synchronize do
39
+ yield
40
+ end
41
+ rescue => e
42
+ raise translate_exception_class(e, sql)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
26
48
  module V5_1
27
49
  def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil)
28
50
  @instrumenter.instrument(
@@ -24,8 +24,14 @@ module ActiveRecord::Turntable
24
24
 
25
25
  private
26
26
 
27
- def skip_statement_cache?
28
- super || should_use_shard_key?
27
+ if Util.ar52_or_later?
28
+ def skip_statement_cache?(scope)
29
+ super || should_use_shard_key?
30
+ end
31
+ else
32
+ def skip_statement_cache?
33
+ super || should_use_shard_key?
34
+ end
29
35
  end
30
36
  end
31
37
  end
@@ -4,14 +4,24 @@ module ActiveRecord::Turntable
4
4
  module ActiveRecordExt
5
5
  module AssociationPreloader
6
6
  include ShardingCondition
7
+ if Util.ar52_or_later?
8
+ def build_scope
9
+ returning_scope = super
10
+ if should_use_shard_key?
11
+ returning_scope = returning_scope.where(klass.turntable_shard_key => owners.map(&foreign_shard_key.to_sym).uniq)
12
+ end
13
+ returning_scope
7
14
 
8
- # @note Override to add sharding condition on preload
9
- def records_for(ids)
10
- returning_scope = super
11
- if should_use_shard_key?
12
- returning_scope = returning_scope.where(klass.turntable_shard_key => owners.map(&foreign_shard_key.to_sym).uniq)
13
15
  end
14
- returning_scope
16
+ else
17
+ # @note Override to add sharding condition on preload
18
+ def records_for(ids)
19
+ returning_scope = super
20
+ if should_use_shard_key?
21
+ returning_scope = returning_scope.where(klass.turntable_shard_key => owners.map(&foreign_shard_key.to_sym).uniq)
22
+ end
23
+ returning_scope
24
+ end
15
25
  end
16
26
  end
17
27
  end
@@ -9,63 +9,65 @@ module ActiveRecord
9
9
  extend ActiveRecord::Turntable::Util
10
10
 
11
11
  # rubocop:disable Style/MultilineMethodCallBraceLayout
12
- def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
13
- fixture_set_names = Array(fixture_set_names).map(&:to_s)
14
- class_names = ClassCache.new class_names, config
15
-
16
- # FIXME: Apparently JK uses this.
17
- connection = block_given? ? yield : ActiveRecord::Base.connection
18
-
19
- files_to_read = fixture_set_names.reject { |fs_name|
20
- fixture_is_cached?(connection, fs_name)
21
- }
22
-
23
- unless files_to_read.empty?
24
- connection.disable_referential_integrity do
25
- fixtures_map = {}
26
-
27
- fixture_sets = files_to_read.map do |fs_name|
28
- klass = class_names[fs_name]
29
- conn = klass ? klass.connection : connection
30
- fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
31
- conn,
32
- fs_name,
33
- klass,
34
- ::File.join(fixtures_directory, fs_name))
35
- end
12
+ unless ar52_or_later?
13
+ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
14
+ fixture_set_names = Array(fixture_set_names).map(&:to_s)
15
+ class_names = ClassCache.new class_names, config
16
+
17
+ # FIXME: Apparently JK uses this.
18
+ connection = block_given? ? yield : ActiveRecord::Base.connection
19
+
20
+ files_to_read = fixture_set_names.reject { |fs_name|
21
+ fixture_is_cached?(connection, fs_name)
22
+ }
23
+
24
+ unless files_to_read.empty?
25
+ connection.disable_referential_integrity do
26
+ fixtures_map = {}
27
+
28
+ fixture_sets = files_to_read.map do |fs_name|
29
+ klass = class_names[fs_name]
30
+ conn = klass ? klass.connection : connection
31
+ fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
32
+ conn,
33
+ fs_name,
34
+ klass,
35
+ ::File.join(fixtures_directory, fs_name))
36
+ end
36
37
 
37
- update_all_loaded_fixtures fixtures_map
38
+ update_all_loaded_fixtures fixtures_map
38
39
 
39
- ActiveRecord::Base.force_transaction_all_shards!(requires_new: true) do
40
- deleted_tables = Hash.new { |h, k| h[k] = Set.new }
41
- fixture_sets.each do |fs|
42
- conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
43
- table_rows = fs.table_rows
40
+ ActiveRecord::Base.force_transaction_all_shards!(requires_new: true) do
41
+ deleted_tables = Hash.new { |h, k| h[k] = Set.new }
42
+ fixture_sets.each do |fs|
43
+ conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
44
+ table_rows = fs.table_rows
44
45
 
45
- table_rows.each_key do |table|
46
- unless deleted_tables[conn].include? table
47
- conn.delete "DELETE FROM #{conn.quote_table_name(table)}", "Fixture Delete"
46
+ table_rows.each_key do |table|
47
+ unless deleted_tables[conn].include? table
48
+ conn.delete "DELETE FROM #{conn.quote_table_name(table)}", "Fixture Delete"
49
+ end
50
+ deleted_tables[conn] << table
48
51
  end
49
- deleted_tables[conn] << table
50
- end
51
52
 
52
- table_rows.each do |fixture_set_name, rows|
53
- rows.each do |row|
54
- conn.insert_fixture(row, fixture_set_name)
53
+ table_rows.each do |fixture_set_name, rows|
54
+ rows.each do |row|
55
+ conn.insert_fixture(row, fixture_set_name)
56
+ end
55
57
  end
56
- end
57
58
 
58
- # Cap primary key sequences to max(pk).
59
- if connection.respond_to?(:reset_pk_sequence!)
60
- connection.reset_pk_sequence!(fs.table_name)
59
+ # Cap primary key sequences to max(pk).
60
+ if connection.respond_to?(:reset_pk_sequence!)
61
+ connection.reset_pk_sequence!(fs.table_name)
62
+ end
61
63
  end
62
64
  end
63
- end
64
65
 
65
- cache_fixtures(connection, fixtures_map)
66
+ cache_fixtures(connection, fixtures_map)
67
+ end
66
68
  end
69
+ cached_fixtures(connection, fixture_set_names)
67
70
  end
68
- cached_fixtures(connection, fixture_set_names)
69
71
  end
70
72
  # rubocop:enable Style/MultilineMethodCallLayout
71
73
  end
@@ -4,6 +4,7 @@ module ActiveRecord::Turntable
4
4
  if Util.ar_version_equals_or_later?("5.1.6")
5
5
  ::ActiveRecord::Locking::Optimistic.class_eval <<-EOD
6
6
  private
7
+
7
8
  def _update_row(attribute_names, attempted_action = "update")
8
9
  return super unless locking_enabled?
9
10
 
@@ -22,10 +23,17 @@ module ActiveRecord::Turntable
22
23
  constraints[self.class.turntable_shard_key] = self[self.class.turntable_shard_key]
23
24
  end
24
25
 
25
- affected_rows = self.class.unscoped._update_record(
26
- arel_attributes_with_values(attribute_names),
27
- constraints,
28
- )
26
+ if Util.ar52_or_later?
27
+ affected_rows = self.class._update_record(
28
+ attributes_with_values(attribute_names),
29
+ constraints,
30
+ )
31
+ else
32
+ affected_rows = self.class.unscoped._update_record(
33
+ arel_attributes_with_values(attribute_names),
34
+ constraints,
35
+ )
36
+ end
29
37
 
30
38
  if affected_rows != 1
31
39
  raise ActiveRecord::StaleObjectError.new(self, attempted_action)
@@ -40,8 +48,7 @@ module ActiveRecord::Turntable
40
48
  end
41
49
  end
42
50
  EOD
43
-
44
- elsif Util.ar51_or_later?
51
+ elsif Util.ar51?
45
52
  ::ActiveRecord::Locking::Optimistic.class_eval <<-EOD
46
53
  private
47
54
  # @note Override to add sharding condition on optimistic locking
@@ -91,7 +98,7 @@ module ActiveRecord::Turntable
91
98
  end
92
99
  end
93
100
  EOD
94
- else
101
+ elsif Util.earlier_than_ar51?
95
102
  ::ActiveRecord::Locking::Optimistic.class_eval <<-EOD
96
103
  private
97
104
  # @note Override to add sharding condition on optimistic locking
@@ -2,6 +2,7 @@ module ActiveRecord::Turntable
2
2
  module ActiveRecordExt
3
3
  module Persistence
4
4
  extend ActiveSupport::Concern
5
+ extend Compatibility
5
6
 
6
7
  ::ActiveRecord::Persistence.class_eval do
7
8
  # @note Override to add sharding scope on reloading
@@ -77,45 +78,61 @@ module ActiveRecord::Turntable
77
78
  true
78
79
  end
79
80
  end
81
+ # rubocop:enable Style/UnlessElse
80
82
  end
81
- # rubocop:enable Style/UnlessElse
82
83
 
83
84
  # @note Override to add sharding scope on `update_columns`
84
- def update_columns(attributes)
85
- raise ActiveRecord::ActiveRecordError, "cannot update a new record" if new_record?
86
- raise ActiveRecord::ActiveRecordError, "cannot update a destroyed record" if destroyed?
85
+ if Util.ar52_or_later?
86
+ def update_columns(attributes)
87
+ raise ActiveRecord::ActiveRecordError, "cannot update a new record" if new_record?
88
+ raise ActiveRecord::ActiveRecordError, "cannot update a destroyed record" if destroyed?
87
89
 
88
- attributes.each_key do |key|
89
- verify_readonly_attribute(key.to_s)
90
- end
90
+ attributes.each_key do |key|
91
+ verify_readonly_attribute(key.to_s)
92
+ end
91
93
 
92
- update_scope = if turntable_enabled? && self.class.primary_key != self.class.turntable_shard_key.to_s
93
- self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key))
94
- else
95
- self.class.unscoped
96
- end
94
+ constraints = { self.class.primary_key => id_in_database }
95
+ if self.class.sharding_condition_needed?
96
+ constraints[self.class.turntable_shard_key] = self[self.class.turntable_shard_key]
97
+ end
98
+
99
+ affected_rows = self.class._update_record(
100
+ attributes,
101
+ constraints,
102
+ )
97
103
 
98
- updated_count = update_scope.where(self.class.primary_key => id).update_all(attributes)
104
+ attributes.each do |k, v|
105
+ write_attribute_without_type_cast(k, v)
106
+ end
99
107
 
100
- attributes.each do |k, v|
101
- raw_write_attribute(k, v)
108
+ affected_rows == 1
102
109
  end
110
+ else
111
+ def update_columns(attributes)
112
+ raise ActiveRecord::ActiveRecordError, "cannot update a new record" if new_record?
113
+ raise ActiveRecord::ActiveRecordError, "cannot update a destroyed record" if destroyed?
103
114
 
104
- updated_count == 1
105
- end
115
+ attributes.each_key do |key|
116
+ verify_readonly_attribute(key.to_s)
117
+ end
106
118
 
107
- private
119
+ update_scope = if turntable_enabled? && self.class.primary_key != self.class.turntable_shard_key.to_s
120
+ self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key))
121
+ else
122
+ self.class.unscoped
123
+ end
108
124
 
109
- # @note Override to add sharding scope on destroying
110
- def relation_for_destroy
111
- klass = self.class
112
- relation = klass.unscoped.where(klass.primary_key => id)
125
+ updated_count = update_scope.where(self.class.primary_key => id).update_all(attributes)
113
126
 
114
- if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s
115
- relation = relation.where(klass.turntable_shard_key => self[klass.turntable_shard_key])
127
+ attributes.each do |k, v|
128
+ raw_write_attribute(k, v)
116
129
  end
117
- relation
130
+
131
+ updated_count == 1
118
132
  end
133
+ end
134
+
135
+ private
119
136
 
120
137
  if Util.ar_version_equals_or_later?("5.1.6")
121
138
  def _update_row(attribute_names, attempted_action = "update")
@@ -124,12 +141,38 @@ module ActiveRecord::Turntable
124
141
  constraints[self.class.turntable_shard_key] = self[self.class.turntable_shard_key]
125
142
  end
126
143
 
144
+ attributes = Util.ar52_or_later? ? attributes_with_values(attribute_names) : arel_attributes_with_values(attribute_names)
145
+
127
146
  self.class.unscoped._update_record(
128
- arel_attributes_with_values(attribute_names),
147
+ attributes,
129
148
  constraints,
130
149
  )
131
150
  end
151
+ end
152
+
153
+ if Util.ar52_or_later?
154
+ def _delete_row
155
+ constraints = { self.class.primary_key => id_in_database }
156
+ if self.class.sharding_condition_needed?
157
+ constraints[self.class.turntable_shard_key] = self[self.class.turntable_shard_key]
158
+ end
159
+
160
+ self.class._delete_record(constraints)
161
+ end
132
162
  else
163
+ # @note Override to add sharding scope on destroying
164
+ def relation_for_destroy
165
+ klass = self.class
166
+ relation = klass.unscoped.where(klass.primary_key => id)
167
+
168
+ if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s
169
+ relation = relation.where(klass.turntable_shard_key => self[klass.turntable_shard_key])
170
+ end
171
+ relation
172
+ end
173
+ end
174
+
175
+ if Util.ar_version_earlier_than?("5.1.6")
133
176
  # @note Override to add sharding scope on updating
134
177
  def _update_record(attribute_names = self.attribute_names)
135
178
  klass = self.class
@@ -10,6 +10,9 @@ module ActiveRecord::Turntable
10
10
  module ClassMethods
11
11
  extend Compatibility
12
12
 
13
+ module V5_2
14
+ end
15
+
13
16
  module V5_1
14
17
  def run
15
18
  result = super
@@ -7,7 +7,11 @@ module ActiveRecord::Turntable::Migration
7
7
  class_attribute :target_shards, :current_shard
8
8
  ::ActiveRecord::ConnectionAdapters::AbstractAdapter.include(SchemaStatementsExt)
9
9
  ::ActiveRecord::Migration::CommandRecorder.include(CommandRecorder)
10
- ::ActiveRecord::Migrator.prepend(Migrator)
10
+ if ActiveRecord::Turntable::Util.ar52_or_later?
11
+ ::ActiveRecord::MigrationContext.prepend(MigrationContext)
12
+ else
13
+ ::ActiveRecord::Migrator.prepend(Migrator)
14
+ end
11
15
  end
12
16
 
13
17
  module ShardDefinition
@@ -89,6 +93,43 @@ module ActiveRecord::Turntable::Migration
89
93
  end
90
94
  end
91
95
 
96
+ module MigrationContext
97
+ extend ActiveSupport::Concern
98
+
99
+ def up(target_version = nil)
100
+ result = super
101
+
102
+ ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected(current_environment) do |name, configuration|
103
+ puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})"
104
+ super(target_version)
105
+ end
106
+
107
+ result
108
+ end
109
+
110
+ def down(target_version = nil)
111
+ result = super
112
+
113
+ ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected(current_environment) do |name, configuration|
114
+ puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})"
115
+ super(target_version)
116
+ end
117
+
118
+ result
119
+ end
120
+
121
+ def run(direction, target_version)
122
+ result = super
123
+
124
+ ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected(current_environment) do |name, configuration|
125
+ puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})"
126
+ super(target_version)
127
+ end
128
+
129
+ result
130
+ end
131
+ end
132
+
92
133
  module Migrator
93
134
  extend ActiveSupport::Concern
94
135
 
@@ -12,7 +12,7 @@ module ActiveRecord::Turntable
12
12
  end
13
13
 
14
14
  delegate :connected?, :automatic_reconnect, :automatic_reconnect=, :checkout_timeout, :dead_connection_timeout,
15
- :spec, :connections, :size, :reaper, :table_exists?, to: :proxy
15
+ :spec, :connections, :size, :reaper, :table_exists?, :query_cache_enabled, :enable_query_cache!, to: :proxy
16
16
 
17
17
  %w(columns_hash column_defaults primary_keys).each do |name|
18
18
  define_method(name.to_sym) do
@@ -42,6 +42,10 @@ module ActiveRecord::Turntable
42
42
  end
43
43
  end
44
44
 
45
+ def discard!
46
+ # Nothing to do
47
+ end
48
+
45
49
  private
46
50
 
47
51
  def connection_pools_list
@@ -3,15 +3,18 @@ module ActiveRecord::Turntable
3
3
  private
4
4
 
5
5
  def foreign_shard_key
6
- options[:foreign_shard_key] || foreign_target_model.turntable_shard_key
6
+ reflection.options[:foreign_shard_key] || foreign_target_model.turntable_shard_key
7
7
  end
8
8
 
9
9
  def foreign_target_model
10
- respond_to?(:model) ? model : owner
10
+ return model if respond_to?(:model)
11
+ return @model if instance_variable_defined?(:@model) && @model
12
+
13
+ owner
11
14
  end
12
15
 
13
16
  def should_use_shard_key?
14
- sharded_by_same_key? || !!options[:foreign_shard_key]
17
+ sharded_by_same_key? || !!reflection.options[:foreign_shard_key]
15
18
  end
16
19
 
17
20
  def sharded_by_same_key?
@@ -19,14 +19,29 @@ module ActiveRecord::Turntable
19
19
  requirement.satisfied_by?(ar_version)
20
20
  end
21
21
 
22
+ def ar51?
23
+ ar51_or_later? && !ar52_or_later?
24
+ end
25
+
22
26
  def ar51_or_later?
23
27
  ar_version_equals_or_later?("5.1")
24
28
  end
25
29
 
30
+ def earlier_than_ar51?
31
+ ar_version_earlier_than?("5.1")
32
+ end
33
+
34
+ def ar52_or_later?
35
+ ar_version_equals_or_later?("5.2")
36
+ end
37
+
26
38
  module_function :ar_version_equals_or_later?,
27
39
  :ar_version_earlier_than?,
28
40
  :ar_version,
29
41
  :ar_version_satisfy?,
30
- :ar51_or_later?
42
+ :ar51?,
43
+ :earlier_than_ar51?,
44
+ :ar51_or_later?,
45
+ :ar52_or_later?
31
46
  end
32
47
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Turntable
3
- VERSION = "4.1.0".freeze
3
+ VERSION = "4.2.0".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-turntable
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gussan
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-04-24 00:00:00.000000000 Z
12
+ date: 2018-05-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -209,16 +209,16 @@ dependencies:
209
209
  name: mysql2
210
210
  requirement: !ruby/object:Gem::Requirement
211
211
  requirements:
212
- - - ">="
212
+ - - "~>"
213
213
  - !ruby/object:Gem::Version
214
- version: '0'
214
+ version: 0.4.4
215
215
  type: :development
216
216
  prerelease: false
217
217
  version_requirements: !ruby/object:Gem::Requirement
218
218
  requirements:
219
- - - ">="
219
+ - - "~>"
220
220
  - !ruby/object:Gem::Version
221
- version: '0'
221
+ version: 0.4.4
222
222
  - !ruby/object:Gem::Dependency
223
223
  name: onkcop
224
224
  requirement: !ruby/object:Gem::Requirement
@@ -461,30 +461,30 @@ dependencies:
461
461
  name: minitest
462
462
  requirement: !ruby/object:Gem::Requirement
463
463
  requirements:
464
- - - "<"
464
+ - - ">="
465
465
  - !ruby/object:Gem::Version
466
- version: 5.3.4
466
+ version: '0'
467
467
  type: :development
468
468
  prerelease: false
469
469
  version_requirements: !ruby/object:Gem::Requirement
470
470
  requirements:
471
- - - "<"
471
+ - - ">="
472
472
  - !ruby/object:Gem::Version
473
- version: 5.3.4
473
+ version: '0'
474
474
  - !ruby/object:Gem::Dependency
475
475
  name: mocha
476
476
  requirement: !ruby/object:Gem::Requirement
477
477
  requirements:
478
- - - "~>"
478
+ - - ">="
479
479
  - !ruby/object:Gem::Version
480
- version: '0.14'
480
+ version: '0'
481
481
  type: :development
482
482
  prerelease: false
483
483
  version_requirements: !ruby/object:Gem::Requirement
484
484
  requirements:
485
- - - "~>"
485
+ - - ">="
486
486
  - !ruby/object:Gem::Version
487
- version: '0.14'
487
+ version: '0'
488
488
  - !ruby/object:Gem::Dependency
489
489
  name: sqlite3
490
490
  requirement: !ruby/object:Gem::Requirement
@@ -538,6 +538,7 @@ files:
538
538
  - gemfiles/rails5_1_4.gemfile
539
539
  - gemfiles/rails5_1_5.gemfile
540
540
  - gemfiles/rails5_1_6.gemfile
541
+ - gemfiles/rails5_2_0.gemfile
541
542
  - gemfiles/rails_edge.gemfile
542
543
  - lib/active_record/turntable.rb
543
544
  - lib/active_record/turntable/active_record_ext.rb
@@ -635,7 +636,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
635
636
  version: '0'
636
637
  requirements: []
637
638
  rubyforge_project: activerecord-turntable
638
- rubygems_version: 2.6.14
639
+ rubygems_version: 2.7.6
639
640
  signing_key:
640
641
  specification_version: 4
641
642
  summary: ActiveRecord sharding extension