activerecord-turntable 3.0.1 → 3.1.0

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