activerecord-turntable 3.0.1 → 3.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 65f26f1f0d729de81434f01e9bcaaff91ed996e7
4
- data.tar.gz: 789697728baf93d532fdd47b711473debe693437
3
+ metadata.gz: 66d31edc8c786999ddb71e35bf5f64e3dd97978a
4
+ data.tar.gz: 5cad32e83086caff4e7fdb1ad8c89e0393286c3e
5
5
  SHA512:
6
- metadata.gz: 4ba8a9f58defbc75afc069b299d5bd27e3a7688bf176f86b7f5670a56bd129bae4d7e0988ef04d78edea863105be3445e5b07f68f306ee24e427b90c03dc842d
7
- data.tar.gz: '08c739c86e694240129f47c0f7dcd039107f2ca8630356796695c4e7faa13a8784da4d61b54be5804def5f6b7e041f55c02218ee4e64bca4260d8a3ac4338e08'
6
+ metadata.gz: 5ec384d210033d0f2831b9db8381d422a913d8d2d736ecb1422b8870ee12624ff1f0eaadf46b13c3191e2c0f5d28bf6b8fef9ea9c83deaa54866e680ccd8d441
7
+ data.tar.gz: 67c6d75b06df8ea9b3c5014d43454f3ec4ef7411123ce76b93fff053e37a2caf60ded5eea3f9eff31bc3d2e5f503514226ef82cc1180e0a01e812df05f3fe075
data/.travis.yml CHANGED
@@ -15,6 +15,8 @@ gemfile:
15
15
  - gemfiles/rails5_0_1.gemfile
16
16
  - gemfiles/rails5_0_2.gemfile
17
17
  - gemfiles/rails5_0_3.gemfile
18
+ - gemfiles/rails5_1_0.gemfile
19
+ - gemfiles/rails5_1_1.gemfile
18
20
  - gemfiles/rails_edge.gemfile
19
21
 
20
22
  env:
@@ -40,7 +42,7 @@ matrix:
40
42
  - rvm: 2.4.1
41
43
  gemfile: gemfiles/rails_edge.gemfile
42
44
  - rvm: 2.3.4
43
- gemfile: gemfiles/rails5_0_3.gemfile
45
+ gemfile: gemfiles/rails5_1_1.gemfile
44
46
  allow_failures:
45
47
  - rvm: ruby-head
46
48
  - gemfile: gemfiles/rails_edge.gemfile
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## activerecord-turntable 3.1.0 ##
2
+
3
+ ### Major Changes
4
+
5
+ * Support activerecord v5.1.x
6
+
7
+ ### Bugfix
8
+
9
+ * Fix schema dumper to dump sequence table options correctly (activerecord >= 5.0.1)
10
+
1
11
  ## activerecord-turntable 3.0.1 ##
2
12
 
3
13
  ### Minor Changes
data/Gemfile CHANGED
@@ -2,5 +2,5 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem "activerecord", "~> 5.0.1"
6
- gem "activesupport", "~> 5.0.1"
5
+ gem "activerecord", "~> 5.1.1"
6
+ gem "activesupport", "~> 5.1.1"
data/Rakefile CHANGED
@@ -48,7 +48,7 @@ namespace :turntable do
48
48
  configurations.each do |configuration|
49
49
  ActiveRecord::Base.establish_connection configuration
50
50
 
51
- ActiveRecord::Base.connection.create_table :users do |t|
51
+ ActiveRecord::Base.connection.create_table :users, comment: "comment" do |t|
52
52
  t.string :nickname
53
53
  t.string :thumbnail_url
54
54
  t.binary :blob
@@ -56,7 +56,7 @@ namespace :turntable do
56
56
  t.datetime :deleted_at
57
57
  t.timestamps
58
58
  end
59
- ActiveRecord::Base.connection.create_sequence_for :users
59
+ ActiveRecord::Base.connection.create_sequence_for :users, comment: "comment"
60
60
 
61
61
  ActiveRecord::Base.connection.create_table :user_statuses do |t|
62
62
  t.belongs_to :user, :null => false
@@ -129,7 +129,8 @@ namespace :turntable do
129
129
  namespace :activerecord do
130
130
  task(:env) do
131
131
  ENV["ARCONFIG"] ||= File.expand_path("spec/config/activerecord_config.yml", __dir__)
132
- ENV["ARVERSION"] ||= if ActiveRecord.gem_version.prerelease?
132
+ ENV["ARVERSION"] ||= if ActiveRecord.gem_version.prerelease? &&
133
+ !ActiveRecord.gem_version.segments.include?("rc")
133
134
  "origin/master"
134
135
  else
135
136
  "v#{ActiveRecord.gem_version}"
@@ -143,6 +144,7 @@ namespace :turntable do
143
144
  Dir.chdir("tmp/rails") do
144
145
  system(*%W|git checkout #{ENV['ARVERSION']}|)
145
146
  end
147
+ FileUtils.rm_r("test") if File.directory?("test")
146
148
  FileUtils.cp_r("tmp/rails/activerecord/test", ".")
147
149
  FileUtils.cp_r("tmp/rails/activerecord/Rakefile", "activerecord.rake")
148
150
  File.open("test/cases/helper.rb", "a") do |f|
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activerecord", "5.1.0"
4
+ gem "activesupport", "5.1.0"
5
+ gem "actionview", "5.1.0"
6
+
7
+ gemspec :path => '../'
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activerecord", "5.1.1"
4
+ gem "activesupport", "5.1.1"
5
+ gem "actionview", "5.1.1"
6
+
7
+ gemspec :path => '../'
@@ -24,6 +24,7 @@ module ActiveRecord::Turntable
24
24
  autoload :ClusterHelperMethods
25
25
  autoload :Config
26
26
  autoload :ConnectionProxy
27
+ autoload :Compatibility
27
28
  autoload :MasterShard
28
29
  autoload :Migration
29
30
  autoload :Mixer
@@ -1,6 +1,13 @@
1
1
  module ActiveRecord::Turntable
2
2
  module ActiveRecordExt
3
3
  module AbstractAdapter
4
+ extend Compatibility
5
+
6
+ def self.prepended(klass)
7
+ klass.prepend(self.compatible_module)
8
+ klass.class_eval { protected :log }
9
+ end
10
+
4
11
  def translate_exception_class(e, sql)
5
12
  begin
6
13
  message = "#{e.class.name}: #{e.message}: #{sql} : #{turntable_shard_name}"
@@ -12,11 +19,32 @@ module ActiveRecord::Turntable
12
19
  exception.set_backtrace e.backtrace
13
20
  exception
14
21
  end
22
+ protected :translate_exception_class
15
23
 
16
24
  # @note override for append current shard name
17
25
  # rubocop:disable Style/HashSyntax, Style/MultilineMethodCallBraceLayout
18
- if ActiveRecord::Turntable::Util.ar_version_equals_or_later?("5.0.3")
26
+ module V5_1
19
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
+ @lock.synchronize do
38
+ yield
39
+ end
40
+ end
41
+ rescue => e
42
+ raise translate_exception_class(e, sql)
43
+ end
44
+ end
45
+
46
+ module V5_0_3
47
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil) # :doc:
20
48
  @instrumenter.instrument(
21
49
  "sql.active_record",
22
50
  sql: sql,
@@ -29,7 +57,9 @@ module ActiveRecord::Turntable
29
57
  rescue => e
30
58
  raise translate_exception_class(e, sql)
31
59
  end
32
- else
60
+ end
61
+
62
+ module V5_0
33
63
  def log(sql, name = "SQL", binds = [], statement_name = nil)
34
64
  @instrumenter.instrument(
35
65
  "sql.active_record",
@@ -45,7 +75,6 @@ module ActiveRecord::Turntable
45
75
  end
46
76
  # rubocop:enable Style/HashSyntax, Style/MultilineMethodCallBraceLayout
47
77
 
48
- protected :translate_exception_class, :log
49
78
 
50
79
  def turntable_shard_name=(name)
51
80
  @turntable_shard_name = name.to_s
@@ -11,7 +11,9 @@ module ActiveRecord::Turntable
11
11
  # A connection was established in an ancestor process that must have
12
12
  # subsequently forked. We can't reuse the connection, but we can copy
13
13
  # the specification and establish a new connection with it.
14
- establish_connection(ancestor_pool.spec).tap do |pool|
14
+ spec = ancestor_pool.spec
15
+ spec = spec.to_hash if spec.respond_to?(:to_hash)
16
+ establish_connection(spec).tap do |pool|
15
17
  pool.schema_cache = ancestor_pool.schema_cache if ancestor_pool.schema_cache
16
18
  end
17
19
  else
@@ -2,6 +2,7 @@
2
2
  # force TestFixtures to begin transaction with all shards.
3
3
  #
4
4
  require "active_record/fixtures"
5
+ require "active_record/turntable/util"
5
6
 
6
7
  module ActiveRecord
7
8
  class FixtureSet
@@ -79,6 +80,7 @@ module ActiveRecord
79
80
  @fixture_cache = {}
80
81
  @fixture_connections = []
81
82
  @@already_loaded_fixtures ||= {}
83
+ @connection_subscriber = nil
82
84
 
83
85
  # Load fixtures once and begin transaction.
84
86
  if run_in_transaction?
@@ -88,11 +90,38 @@ module ActiveRecord
88
90
  @loaded_fixtures = load_fixtures(config)
89
91
  @@already_loaded_fixtures[self.class] = @loaded_fixtures
90
92
  end
93
+
94
+ # Begin transactions for connections already established
91
95
  ActiveRecord::Base.force_connect_all_shards!
92
96
  @fixture_connections = enlist_fixture_connections
93
97
  @fixture_connections.each do |connection|
94
98
  connection.begin_transaction joinable: false
99
+ if ActiveRecord::Turntable::Util.ar51_or_later?
100
+ connection.pool.lock_thread = true
101
+ end
95
102
  end
103
+
104
+ if ActiveRecord::Turntable::Util.ar51_or_later?
105
+ # When connections are established in the future, begin a transaction too
106
+ @connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
107
+ spec_name = payload[:spec_name] if payload.key?(:spec_name)
108
+
109
+ if spec_name
110
+ begin
111
+ connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name)
112
+ rescue ConnectionNotEstablished
113
+ connection = nil
114
+ end
115
+
116
+ if connection && !@fixture_connections.include?(connection)
117
+ connection.begin_transaction joinable: false
118
+ connection.pool.lock_thread = true
119
+ @fixture_connections << connection
120
+ end
121
+ end
122
+ end
123
+ end
124
+
96
125
  # Load fixtures for every test.
97
126
  else
98
127
  ActiveRecord::FixtureSet.reset_cache
@@ -1,53 +1,105 @@
1
1
  module ActiveRecord::Turntable
2
2
  module ActiveRecordExt
3
3
  module LockingOptimistic
4
- ::ActiveRecord::Locking::Optimistic.class_eval <<-EOD
5
- private
6
- # @note Override to add sharding condition on optimistic locking
7
- def _update_record(attribute_names = self.attribute_names) #:nodoc:
8
- return super unless locking_enabled?
9
- return 0 if attribute_names.empty?
10
-
11
- klass = self.class
12
- lock_col = self.class.locking_column
13
- previous_lock_value = send(lock_col).to_i
14
- increment_lock
15
-
16
- attribute_names += [lock_col]
17
- attribute_names.uniq!
18
-
19
- begin
20
- relation = self.class.unscoped
21
-
22
- condition_scope = relation.where(
23
- self.class.primary_key => id,
24
- lock_col => previous_lock_value,
25
- )
26
- if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
27
- condition_scope = condition_scope.where(
28
- klass.turntable_shard_key => self.send(klass.turntable_shard_key)
4
+ if Util.ar51_or_later?
5
+ ::ActiveRecord::Locking::Optimistic.class_eval <<-EOD
6
+ private
7
+ # @note Override to add sharding condition on optimistic locking
8
+ def _update_record(attribute_names = self.attribute_names)
9
+ return super unless locking_enabled?
10
+ return 0 if attribute_names.empty?
11
+
12
+ begin
13
+ klass = self.class
14
+
15
+ lock_col = self.class.locking_column
16
+
17
+ previous_lock_value = read_attribute_before_type_cast(lock_col)
18
+
19
+ increment_lock
20
+
21
+ attribute_names.push(lock_col)
22
+
23
+ relation = self.class.unscoped
24
+
25
+ condition_scope = relation.where(
26
+ self.class.primary_key => id,
27
+ lock_col => previous_lock_value
29
28
  )
30
- end
29
+ if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
30
+ condition_scope = condition_scope.where(
31
+ klass.turntable_shard_key => self.send(klass.turntable_shard_key)
32
+ )
33
+ end
34
+
35
+ affected_rows = condition_scope.update_all(
36
+ attributes_for_update(attribute_names).map do |name|
37
+ [name, _read_attribute(name)]
38
+ end.to_h
39
+ )
40
+
41
+ unless affected_rows == 1
42
+ raise ActiveRecord::StaleObjectError.new(self, "update")
43
+ end
31
44
 
32
- affected_rows = condition_scope.update_all(
33
- attributes_for_update(attribute_names).map do |name|
34
- [name, _read_attribute(name)]
35
- end.to_h
36
- )
45
+ affected_rows
37
46
 
38
- unless affected_rows == 1
39
- raise ActiveRecord::StaleObjectError.new(self, "update")
47
+ # If something went wrong, revert the locking_column value.
48
+ rescue Exception
49
+ send(lock_col + "=", previous_lock_value.to_i)
50
+ raise
40
51
  end
52
+ end
53
+ EOD
54
+ else
55
+ ::ActiveRecord::Locking::Optimistic.class_eval <<-EOD
56
+ private
57
+ # @note Override to add sharding condition on optimistic locking
58
+ def _update_record(attribute_names = self.attribute_names) #:nodoc:
59
+ return super unless locking_enabled?
60
+ return 0 if attribute_names.empty?
61
+
62
+ klass = self.class
63
+ lock_col = self.class.locking_column
64
+ previous_lock_value = send(lock_col).to_i
65
+ increment_lock
66
+
67
+ attribute_names += [lock_col]
68
+ attribute_names.uniq!
69
+
70
+ begin
71
+ relation = self.class.unscoped
72
+
73
+ condition_scope = relation.where(
74
+ self.class.primary_key => id,
75
+ lock_col => previous_lock_value,
76
+ )
77
+ if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
78
+ condition_scope = condition_scope.where(
79
+ klass.turntable_shard_key => self.send(klass.turntable_shard_key)
80
+ )
81
+ end
82
+
83
+ affected_rows = condition_scope.update_all(
84
+ attributes_for_update(attribute_names).map do |name|
85
+ [name, _read_attribute(name)]
86
+ end.to_h
87
+ )
41
88
 
42
- affected_rows
89
+ unless affected_rows == 1
90
+ raise ActiveRecord::StaleObjectError.new(self, "update")
91
+ end
43
92
 
44
- # If something went wrong, revert the version.
45
- rescue Exception
46
- send(lock_col + '=', previous_lock_value)
47
- raise
93
+ affected_rows
94
+
95
+ # If something went wrong, revert the version.
96
+ rescue Exception
97
+ send(lock_col + '=', previous_lock_value)
98
+ raise
99
+ end
48
100
  end
49
- end
50
- EOD
101
+ EOD
102
+ end
51
103
  end
52
104
  end
53
105
  end
@@ -29,7 +29,12 @@ module ActiveRecord::Turntable
29
29
  # @note Override to add sharding scope on `touch`
30
30
  # rubocop:disable Style/UnlessElse
31
31
  def touch(*names, time: nil)
32
- raise ActiveRecord::ActiveRecordError, "cannot touch on a new record object" unless persisted?
32
+ unless persisted?
33
+ raise ActiveRecord::ActiveRecordError, <<-MSG.squish
34
+ cannot touch on a new or destroyed record object. Consider using
35
+ persisted?, new_record?, or destroyed? before touching
36
+ MSG
37
+ end
33
38
 
34
39
  time ||= current_time_from_proper_timezone
35
40
  attributes = timestamp_attributes_for_update_in_model
@@ -43,7 +48,7 @@ module ActiveRecord::Turntable
43
48
  changes[column] = write_attribute(column, time)
44
49
  end
45
50
 
46
- clear_attribute_changes(changes.keys)
51
+ clear_attribute_changes(changes.keys) unless Util.ar51_or_later?
47
52
  primary_key = self.class.primary_key
48
53
  scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s
49
54
  self.class.unscoped.where(self.class.turntable_shard_key => _read_attribute(turntable_shard_key))
@@ -58,12 +63,14 @@ module ActiveRecord::Turntable
58
63
  changes[locking_column] = increment_lock
59
64
  end
60
65
 
66
+ clear_attribute_changes(changes.keys) if Util.ar51_or_later?
61
67
  result = scope.update_all(changes) == 1
62
68
 
63
69
  if !result && locking_enabled?
64
70
  raise ActiveRecord::StaleObjectError.new(self, "touch")
65
71
  end
66
72
 
73
+ @_trigger_update_callback = result
67
74
  result
68
75
  else
69
76
  true
@@ -113,13 +120,20 @@ module ActiveRecord::Turntable
113
120
  klass = self.class
114
121
  attributes_values = arel_attributes_with_values_for_update(attribute_names)
115
122
  if attributes_values.empty?
116
- 0
123
+ rows_affected = 0
124
+ @_trigger_update_callback = true
117
125
  else
118
126
  scope = if klass.turntable_enabled? && (klass.primary_key != klass.turntable_shard_key.to_s)
119
127
  klass.unscoped.where(klass.turntable_shard_key => self.send(turntable_shard_key))
120
128
  end
121
- klass.unscoped._update_record attributes_values, id, id_was, scope
129
+ previous_id = Util.ar51_or_later? ? id_in_database : id_was
130
+ rows_affected = klass.unscoped._update_record attributes_values, id, previous_id, scope
131
+ @_trigger_update_callback = rows_affected > 0
122
132
  end
133
+
134
+ yield(self) if block_given?
135
+
136
+ rows_affected
123
137
  end
124
138
  end
125
139
  end
@@ -3,40 +3,36 @@ module ActiveRecord::Turntable
3
3
  module QueryCache
4
4
  def self.prepended(klass)
5
5
  class << klass
6
- if Util.ar_version_equals_or_later?("5.0.1")
7
- prepend(ClassMethods::AR5_0_1)
8
- else
9
- prepend(ClassMethods::AR5_0)
10
- end
6
+ prepend ClassMethods.compatible_module
11
7
  end
12
8
  end
13
9
 
14
10
  module ClassMethods
15
- module AR5_0
11
+ extend Compatibility
12
+
13
+ module V5_1
16
14
  def run
17
15
  result = super
18
16
 
19
17
  pools = ActiveRecord::Base.turntable_connections.values
20
- pools.each do |k|
21
- k.connection.enable_query_cache!
18
+ pools.each do |pool|
19
+ pool.enable_query_cache!
22
20
  end
23
21
 
24
- result
22
+ [*result, pools]
25
23
  end
26
24
 
27
25
  def complete(state)
28
- enabled, _connection_id = state
29
- super
26
+ caching_pool, caching_was_enabled, turntable_pools = state
27
+ super([caching_pool, caching_was_enabled])
30
28
 
31
- klasses = ActiveRecord::Base.turntable_connections.values
32
- klasses.each do |k|
33
- k.connection.clear_query_cache
34
- k.connection.disable_query_cache! unless enabled
29
+ turntable_pools.each do |pool|
30
+ pool.disable_query_cache! unless caching_was_enabled
35
31
  end
36
32
  end
37
33
  end
38
34
 
39
- module AR5_0_1
35
+ module V5_0_1
40
36
  def run
41
37
  result = super
42
38
 
@@ -57,6 +53,30 @@ module ActiveRecord::Turntable
57
53
  end
58
54
  end
59
55
  end
56
+
57
+ module V5_0
58
+ def run
59
+ result = super
60
+
61
+ pools = ActiveRecord::Base.turntable_connections.values
62
+ pools.each do |k|
63
+ k.connection.enable_query_cache!
64
+ end
65
+
66
+ result
67
+ end
68
+
69
+ def complete(state)
70
+ enabled, _connection_id = state
71
+ super
72
+
73
+ klasses = ActiveRecord::Base.turntable_connections.values
74
+ klasses.each do |k|
75
+ k.connection.clear_query_cache
76
+ k.connection.disable_query_cache! unless enabled
77
+ end
78
+ end
79
+ end
60
80
  end
61
81
 
62
82
  def self.install_turntable_executor_hooks(executor = ActiveSupport::Executor)
@@ -20,11 +20,14 @@ module ActiveRecord::Turntable
20
20
 
21
21
  table_options = @connection.table_options(table)
22
22
  if table_options.present?
23
- options = respond_to?(:format_options) ? format_options(table_options) : table_options.inspect
24
- tbl.print ", options: #{options}"
23
+ if respond_to?(:format_options, true)
24
+ tbl.print ", #{format_options(table_options)}"
25
+ else
26
+ tbl.print ", options: #{table_options.inspect}"
27
+ end
25
28
  end
26
29
 
27
- if comment = @connection.table_comment(table).presence
30
+ if Util.ar_version_earlier_than?("5.0.1") && comment = @connection.table_comment(table).presence
28
31
  tbl.print ", comment: #{comment.inspect}"
29
32
  end
30
33
  tbl.puts
@@ -3,28 +3,25 @@ module ActiveRecord::Turntable
3
3
  module Transactions
4
4
  # @note Override to start transaction on current shard
5
5
  def with_transaction_returning_status
6
- if self.class.turntable_enabled?
7
- status = nil
8
- if self.new_record? && self.turntable_shard_key.to_s == self.class.primary_key &&
9
- self.id.nil? && self.class.connection.prefetch_primary_key?(self.class.table_name)
10
- self.id = self.class.connection.next_sequence_value(self.class.sequence_name)
11
- end
12
- self.class.connection.shards_transaction([self.turntable_shard]) do
13
- add_to_transaction
14
- begin
15
- status = yield
16
- rescue ActiveRecord::Rollback
17
- clear_transaction_record_state
18
- status = nil
19
- end
6
+ return super unless self.class.turntable_enabled?
20
7
 
21
- raise ActiveRecord::Rollback unless status
22
- end
23
- status
24
- else
25
- super
8
+ status = nil
9
+ if self.new_record? && self.turntable_shard_key.to_s == self.class.primary_key &&
10
+ self.id.nil? && self.class.connection.prefetch_primary_key?(self.class.table_name)
11
+ self.id = self.class.connection.next_sequence_value(self.class.sequence_name)
26
12
  end
13
+ self.class.connection.shards_transaction([self.turntable_shard]) do
14
+ add_to_transaction
15
+ begin
16
+ status = yield
17
+ rescue ActiveRecord::Rollback
18
+ clear_transaction_record_state
19
+ status = nil
20
+ end
27
21
 
22
+ raise ActiveRecord::Rollback unless status
23
+ end
24
+ status
28
25
  ensure
29
26
  if @transaction_state && @transaction_state.committed?
30
27
  clear_transaction_record_state
@@ -32,17 +29,15 @@ module ActiveRecord::Turntable
32
29
  end
33
30
 
34
31
  def add_to_transaction
35
- if self.class.turntable_enabled?
36
- if has_transactional_callbacks?
37
- self.turntable_shard.connection.add_transaction_record(self)
38
- else
39
- sync_with_transaction_state
40
- set_transaction_state(self.turntable_shard.connection.transaction_state)
41
- end
42
- remember_transaction_record_state
32
+ return super unless self.class.turntable_enabled?
33
+
34
+ if has_transactional_callbacks?
35
+ self.turntable_shard.connection.add_transaction_record(self)
43
36
  else
44
- super
37
+ sync_with_transaction_state
38
+ set_transaction_state(self.turntable_shard.connection.transaction_state)
45
39
  end
40
+ remember_transaction_record_state
46
41
  end
47
42
  end
48
43
  end
@@ -0,0 +1,44 @@
1
+ module ActiveRecord::Turntable
2
+ module Compatibility
3
+ def self.extended(base)
4
+ base.instance_variable_set(:@_compatible_versions, [])
5
+ end
6
+
7
+ def [](version = ActiveRecord.gem_version.release)
8
+ unless version.is_a?(Gem::Version)
9
+ version = Gem::Version.new(version)
10
+ end
11
+ find_compatible_module(version)
12
+ end
13
+ alias_method :compatible_module, :[]
14
+
15
+ def find_compatible_module(version)
16
+ module_version = find_compatible_version(version)
17
+ const_get("V#{module_version.to_s.tr(".", "_")}")
18
+ end
19
+
20
+ def find_compatible_version(version)
21
+ target_version = nil
22
+
23
+ compatible_versions.each do |compatible_version|
24
+ break if version < compatible_version
25
+ target_version = compatible_version
26
+ end
27
+
28
+ target_version
29
+ end
30
+
31
+ def compatible_versions
32
+ if @_compatible_versions.empty?
33
+ @_compatible_versions = constants.map do |const|
34
+ /^V(?<major>\d+)(_(?<minor>\d+)(_(?<teeny>\d))?)?/ =~ const
35
+ nil unless major
36
+ Gem::Version.new([major, minor, teeny].compact.join("."))
37
+ end
38
+ @_compatible_versions.compact!
39
+ @_compatible_versions.sort!
40
+ end
41
+ @_compatible_versions
42
+ end
43
+ end
44
+ end
@@ -9,11 +9,16 @@ module ActiveRecord::Turntable
9
9
  end
10
10
 
11
11
  def ar_version
12
- ActiveRecord.gem_version
12
+ ActiveRecord.gem_version.release
13
+ end
14
+
15
+ def ar51_or_later?
16
+ ar_version_equals_or_later?("5.1")
13
17
  end
14
18
 
15
19
  module_function :ar_version_equals_or_later?,
16
20
  :ar_version_earlier_than?,
17
- :ar_version
21
+ :ar_version,
22
+ :ar51_or_later?
18
23
  end
19
24
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Turntable
3
- VERSION = "3.0.1".freeze
3
+ VERSION = "3.1.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: 3.0.1
4
+ version: 3.1.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: 2017-06-13 00:00:00.000000000 Z
12
+ date: 2017-06-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -513,6 +513,8 @@ files:
513
513
  - gemfiles/rails5_0_1.gemfile
514
514
  - gemfiles/rails5_0_2.gemfile
515
515
  - gemfiles/rails5_0_3.gemfile
516
+ - gemfiles/rails5_1_0.gemfile
517
+ - gemfiles/rails5_1_1.gemfile
516
518
  - gemfiles/rails_edge.gemfile
517
519
  - lib/active_record/turntable.rb
518
520
  - lib/active_record/turntable/active_record_ext.rb
@@ -544,6 +546,7 @@ files:
544
546
  - lib/active_record/turntable/base.rb
545
547
  - lib/active_record/turntable/cluster.rb
546
548
  - lib/active_record/turntable/cluster_helper_methods.rb
549
+ - lib/active_record/turntable/compatibility.rb
547
550
  - lib/active_record/turntable/config.rb
548
551
  - lib/active_record/turntable/connection_proxy.rb
549
552
  - lib/active_record/turntable/connection_proxy/mixable.rb