activerecord-turntable 2.0.6 → 2.1.0.beta1

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: d82829564262382156d47ab48a5331ee39507e2b
4
- data.tar.gz: 2046ebf2f59a336a20d91df727c98da717a1b4f5
3
+ metadata.gz: bd8da73b8e0ac2f22797a0eb070c3624038b2ea3
4
+ data.tar.gz: 57b762fbd0ef0d06c5f7562c4cf68d5cc3c8f8bb
5
5
  SHA512:
6
- metadata.gz: a29ef422e6cbe7494c67c9480e541469ebbfc2773f48a0ef606c130ca7b6c791a6a8502cb23ce46f8fb739899b4ea4c438a46d348e3ca4d4e42b6cd93e9117ce
7
- data.tar.gz: befc1adb93081acf2d9ba91c5cad860039b37530e484198334cec82935dc608719e8845dd83fe326d8da0c9add919222edfb5493033a2f8c69a256e712292a34
6
+ metadata.gz: 74cb71bdcd32cca8731ce965b5fd7d0e8b8dd9d7bde6484abb6aa83021d530c3a54ac22d33c73bc2bb8d7c491a0401562b827e78eef3e56eb3bb5e6a56121f8e
7
+ data.tar.gz: 8ffc60cb0b0dd8e4428f4b3d76690a6135eeb2c60bf5bb0a7ffb0c8655e0be7a835c72bfa8580841c46b0a44bb60d57f88b04d7a48ae7b54ea620cc44f5bc909
data/.travis.yml CHANGED
@@ -2,7 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.2
5
+ - 2.1
6
6
  - 2.2
7
7
  - ruby-head
8
8
  gemfile:
@@ -14,6 +14,4 @@ before_script:
14
14
  script: bundle exec rake spec
15
15
  matrix:
16
16
  allow_failures:
17
- - rvm: 2.2
18
17
  - rvm: ruby-head
19
- - gemfile: gemfiles/rails4_2.gemfile
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## activerecord-turntable 2.1.0 (unreleased) ##
2
+
3
+ Support activerecord 4.2.0
4
+
5
+ ### Bugfixes
6
+
7
+ * Fix cluster helper methods(i.e xxxx_cluster_transaction helper) on lazy load environments(development, test)
8
+
1
9
  ## activerecord-turntable 2.0.6 ##
2
10
 
3
11
  ### Bugfixes
data/Rakefile CHANGED
@@ -85,6 +85,7 @@ namespace :turntable do
85
85
  ActiveRecord::Base.connection.create_table :cards_users do |t|
86
86
  t.belongs_to :card, :null => false
87
87
  t.belongs_to :user, :null => false
88
+ t.integer :num, :default => 1, :null => false
88
89
  t.timestamps
89
90
  end
90
91
  ActiveRecord::Base.connection.create_sequence_for :cards_users
@@ -43,6 +43,9 @@ Gem::Specification.new do |spec|
43
43
  spec.add_development_dependency "faker"
44
44
  spec.add_development_dependency "webmock"
45
45
  spec.add_development_dependency "pry"
46
+ if RUBY_VERSION > "2.0"
47
+ spec.add_development_dependency "pry-byebug"
48
+ end
46
49
  spec.add_development_dependency "guard-rspec"
47
50
  spec.add_development_dependency "coveralls"
48
51
 
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'activerecord', "= 4.2.0.rc1"
4
- gem 'activesupport', "= 4.2.0.rc1"
3
+ gem 'activerecord', "~> 4.2.0"
4
+ gem 'activesupport', "~> 4.2.0"
5
5
 
6
6
  gemspec :path => '../'
@@ -11,33 +11,58 @@ module ActiveRecord::Turntable
11
11
  ActiveRecord::Associations::Builder::Association.valid_options += [:foreign_shard_key]
12
12
  end
13
13
 
14
+ private
15
+
16
+ def turntable_scope(scope, bind = nil)
17
+ if should_use_shard_key?
18
+ scope = scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key))
19
+ end
20
+ scope
21
+ end
22
+
14
23
  module SingularAssociationExt
15
24
  extend ActiveSupport::Concern
16
25
 
17
26
  included do
18
- alias_method_chain :find_target, :turntable
27
+ if ActiveRecord::Turntable.rails42_later?
28
+ alias_method_chain :get_records, :turntable
29
+ else
30
+ alias_method_chain :find_target, :turntable
31
+ end
19
32
  end
20
33
 
21
- private
22
-
23
34
  # @note Override to add sharding condition for singular association
24
- if ActiveRecord::Turntable.rails41_later?
25
- def find_target_with_turntable
26
- current_scope = scope
27
- if should_use_shard_key?
28
- current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key))
35
+ if ActiveRecord::Turntable.rails42_later?
36
+ def get_records_with_turntable
37
+ if reflection.scope_chain.any?(&:any?) ||
38
+ scope.eager_loading? ||
39
+ klass.current_scope ||
40
+ klass.default_scopes.any? ||
41
+ should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope
42
+
43
+ return turntable_scope(scope).limit(1).to_a
29
44
  end
30
- if record = current_scope.take
45
+
46
+ conn = klass.connection
47
+ sc = reflection.association_scope_cache(conn, owner) do
48
+ ActiveRecord::StatementCache.create(conn) { |params|
49
+ as = ActiveRecord::Associations::AssociationScope.create { params.bind }
50
+ target_scope.merge(as.scope(self, conn)).limit(1)
51
+ }
52
+ end
53
+
54
+ binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain)
55
+ sc.execute binds, klass, klass.connection
56
+ end
57
+ elsif ActiveRecord::Turntable.rails41_later?
58
+ def find_target_with_turntable
59
+ if record = turntable_scope(scope).take
31
60
  set_inverse_instance record
32
61
  end
33
62
  end
34
63
  else
35
64
  def find_target_with_turntable
36
- current_scope = scope
37
- if should_use_shard_key?
38
- current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key))
39
- end
40
- current_scope.take.tap { |record| set_inverse_instance(record) }
65
+ turntable_scope(scope).take.tap { |record| set_inverse_instance(record) }
41
66
  end
42
67
  end
43
68
  end
@@ -46,27 +71,54 @@ module ActiveRecord::Turntable
46
71
  extend ActiveSupport::Concern
47
72
 
48
73
  included do
49
- alias_method_chain :find_target, :turntable
74
+ if ActiveRecord::Turntable.rails42_later?
75
+ alias_method_chain :get_records, :turntable
76
+ else
77
+ alias_method_chain :find_target, :turntable
78
+ end
50
79
  end
51
80
 
52
81
  private
53
82
 
54
- # @note Override to add sharding condition for collection association
55
- def find_target_with_turntable
56
- records =
57
- if options[:finder_sql]
58
- reflection.klass.find_by_sql(custom_finder_sql)
59
- else
60
- current_scope = scope
61
- if should_use_shard_key?
62
- current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key))
63
- end
64
- current_scope.to_a
83
+ if ActiveRecord::Turntable.rails42_later?
84
+ def get_records_with_turntable
85
+ if reflection.scope_chain.any?(&:any?) ||
86
+ scope.eager_loading? ||
87
+ klass.current_scope ||
88
+ klass.default_scopes.any? ||
89
+ should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope
90
+
91
+ return turntable_scope(scope).to_a
92
+ end
93
+
94
+ conn = klass.connection
95
+ sc = reflection.association_scope_cache(conn, owner) do
96
+ ActiveRecord::StatementCache.create(conn) { |params|
97
+ as = ActiveRecord::Associations::AssociationScope.create { params.bind }
98
+ target_scope.merge as.scope(self, conn)
99
+ }
65
100
  end
66
- records.each { |record| set_inverse_instance(record) }
67
- records
68
- end
69
101
 
102
+ binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain)
103
+ sc.execute binds, klass, klass.connection
104
+ end
105
+ else
106
+ # @note Override to add sharding condition for collection association
107
+ def find_target_with_turntable
108
+ records =
109
+ if options[:finder_sql]
110
+ reflection.klass.find_by_sql(custom_finder_sql)
111
+ else
112
+ current_scope = scope
113
+ if should_use_shard_key?
114
+ current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key))
115
+ end
116
+ current_scope.to_a
117
+ end
118
+ records.each { |record| set_inverse_instance(record) }
119
+ records
120
+ end
121
+ end
70
122
  end
71
123
 
72
124
  private
@@ -12,7 +12,8 @@ module ActiveRecord::Turntable::ActiveRecordExt
12
12
  # load records
13
13
  records = self.to_a
14
14
  klass = records.first.class
15
- reflection = klass.reflections[association_name]
15
+ association_key = ActiveRecord::Turntable.rails42_later? ? association_name.to_s : association_name
16
+ reflection = klass.reflections[association_key]
16
17
 
17
18
  if reflection
18
19
  foreign_class = reflection.klass
@@ -29,7 +29,11 @@ module ActiveRecord::Turntable::ActiveRecordExt
29
29
  )
30
30
  )
31
31
  if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
32
- condition_scope = condition_scope.where(klass.turntable_shard_key => self.send(turntable_shard_key))
32
+ condition_scope = condition_scope.where(
33
+ relation.table[klass.turntable_shard_key].eq(
34
+ self.class.quote_value(self.send(turntable_shard_key), column_for_attribute(klass.turntable_shard_key))
35
+ )
36
+ )
33
37
  end
34
38
  stmt = condition_scope.arel.compile_update(arel_attributes_with_values_for_update(attribute_names))
35
39
 
@@ -48,7 +52,7 @@ module ActiveRecord::Turntable::ActiveRecordExt
48
52
  end
49
53
  end
50
54
  EOD
51
- else
55
+ elsif ar_version < "4.2"
52
56
  method_name = ar_version =~ /\A4\.1\.[01]\z/ ? "update_record" : "_update_record"
53
57
 
54
58
  class_eval <<-EOD
@@ -73,7 +77,11 @@ module ActiveRecord::Turntable::ActiveRecordExt
73
77
  )
74
78
  )
75
79
  if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
76
- condition_scope = condition_scope.where(klass.turntable_shard_key => self.send(turntable_shard_key))
80
+ condition_scope = condition_scope.where(
81
+ relation.table[klass.turntable_shard_key].eq(
82
+ self.class.quote_value(self.send(turntable_shard_key), column_for_attribute(klass.turntable_shard_key))
83
+ )
84
+ )
77
85
  end
78
86
  stmt = condition_scope.arel.compile_update(
79
87
  arel_attributes_with_values_for_update(attribute_names),
@@ -88,6 +96,56 @@ module ActiveRecord::Turntable::ActiveRecordExt
88
96
 
89
97
  affected_rows
90
98
 
99
+ # If something went wrong, revert the version.
100
+ rescue Exception
101
+ send(lock_col + '=', previous_lock_value)
102
+ raise
103
+ end
104
+ end
105
+ EOD
106
+ else
107
+ class_eval <<-EOD
108
+ def _update_record(attribute_names = self.attribute_names) #:nodoc:
109
+ return super unless locking_enabled?
110
+ return 0 if attribute_names.empty?
111
+
112
+ klass = self.class
113
+ lock_col = self.class.locking_column
114
+ previous_lock_value = send(lock_col).to_i
115
+ increment_lock
116
+
117
+ attribute_names += [lock_col]
118
+ attribute_names.uniq!
119
+
120
+ begin
121
+ relation = self.class.unscoped
122
+
123
+ condition_scope = relation.where(
124
+ relation.table[self.class.primary_key].eq(id).and(
125
+ relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col)))
126
+ )
127
+ )
128
+ if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
129
+ condition_scope = condition_scope.where(
130
+ relation.table[klass.turntable_shard_key].eq(
131
+ self.class.quote_value(self.send(turntable_shard_key), column_for_attribute(klass.turntable_shard_key))
132
+ )
133
+ )
134
+ end
135
+
136
+ stmt = condition_scope.arel.compile_update(
137
+ arel_attributes_with_values_for_update(attribute_names),
138
+ self.class.primary_key
139
+ )
140
+
141
+ affected_rows = self.class.connection.update stmt
142
+
143
+ unless affected_rows == 1
144
+ raise ActiveRecord::StaleObjectError.new(self, "update")
145
+ end
146
+
147
+ affected_rows
148
+
91
149
  # If something went wrong, revert the version.
92
150
  rescue Exception
93
151
  send(lock_col + '=', previous_lock_value)
@@ -21,11 +21,16 @@ module ActiveRecord::Turntable::ActiveRecordExt
21
21
  finder_scope.find(id)
22
22
  end
23
23
 
24
- @attributes.update(fresh_object.instance_variable_get('@attributes'))
25
-
26
- @column_types = self.class.column_types
27
- @column_types_override = fresh_object.instance_variable_get('@column_types_override')
28
- @attributes_cache = {}
24
+ if ActiveRecord::Turntable.rails42_later?
25
+ @attributes = fresh_object.instance_variable_get('@attributes')
26
+ else
27
+ @attributes.update(fresh_object.instance_variable_get('@attributes'))
28
+
29
+ @column_types = self.class.column_types
30
+ @column_types_override = fresh_object.instance_variable_get('@column_types_override')
31
+ @attributes_cache = {}
32
+ end
33
+ @new_record = false
29
34
  self
30
35
  end
31
36
 
@@ -57,6 +62,8 @@ module ActiveRecord::Turntable::ActiveRecordExt
57
62
  end
58
63
 
59
64
  finder_scope.where(primary_key => self[primary_key]).update_all(changes) == 1
65
+ else
66
+ true
60
67
  end
61
68
  end
62
69
 
@@ -85,26 +92,47 @@ module ActiveRecord::Turntable::ActiveRecordExt
85
92
 
86
93
  private
87
94
 
95
+ ar_version = ActiveRecord::VERSION::STRING
96
+
88
97
  # @note Override to add sharding scope on destroying
89
- def relation_for_destroy
90
- pk = self.class.primary_key
91
- column = self.class.columns_hash[pk]
92
- substitute = self.class.connection.substitute_at(column, 0)
93
- klass = self.class
94
-
95
- relation = self.class.unscoped.where(
96
- self.class.arel_table[pk].eq(substitute))
97
- if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
98
- relation = relation.where(klass.turntable_shard_key => self.send(turntable_shard_key))
98
+ if ActiveRecord::Turntable.rails42_later?
99
+ def relation_for_destroy
100
+ pk = self.class.primary_key
101
+ column = self.class.columns_hash[pk]
102
+ substitute = self.class.connection.substitute_at(column, 0)
103
+ klass = self.class
104
+
105
+ relation = self.class.unscoped.where(
106
+ self.class.arel_table[pk].eq(substitute))
107
+ relation.bind_values = [[column, id]]
108
+
109
+ if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
110
+ shard_key_column = klass.columns_hash[klass.turntable_shard_key]
111
+ shard_key_substitute = klass.connection.substitute_at(shard_key_column)
112
+
113
+ relation = relation.where(self.class.arel_table[klass.turntable_shard_key].eq(shard_key_substitute))
114
+ relation.bind_values << [shard_key_column, self[klass.turntable_shard_key]]
115
+ end
116
+ relation
117
+ end
118
+ else
119
+ def relation_for_destroy
120
+ pk = self.class.primary_key
121
+ column = self.class.columns_hash[pk]
122
+ substitute = self.class.connection.substitute_at(column, 0)
123
+ klass = self.class
124
+
125
+ relation = self.class.unscoped.where(
126
+ self.class.arel_table[pk].eq(substitute))
127
+ if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s
128
+ relation = relation.where(klass.turntable_shard_key => self.send(turntable_shard_key))
129
+ end
130
+ relation.bind_values = [[column, id]]
131
+ relation
99
132
  end
100
-
101
- relation.bind_values = [[column, id]]
102
- relation
103
133
  end
104
134
 
105
-
106
135
  # @note Override to add sharding scope on updating
107
- ar_version = ActiveRecord::VERSION::STRING
108
136
  if ar_version < "4.1"
109
137
  method_name = ar_version =~ /\A4\.0\.[0-5]\z/ ? "update_record" : "_update_record"
110
138
  class_eval <<-EOD
@@ -16,16 +16,42 @@ module ActiveRecord::Turntable
16
16
  end
17
17
 
18
18
  # @note Override to add sharding scope on updating
19
- def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # :nodoc:
20
- substitutes, binds = substitute_values values
21
- condition_scope = @klass.unscoped.where(@klass.arel_table[@klass.primary_key].eq(id_was || id))
22
- condition_scope = condition_scope.merge(turntable_scope) if turntable_scope
23
- um = condition_scope.arel.compile_update(substitutes, @klass.primary_key)
24
-
25
- @klass.connection.update(
26
- um,
27
- 'SQL',
28
- binds)
19
+ if ActiveRecord::Turntable.rails42_later?
20
+ def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # :nodoc:
21
+ substitutes, binds = substitute_values values
22
+
23
+ scope = @klass.unscoped
24
+
25
+ if @klass.finder_needs_type_condition?
26
+ scope.unscope!(where: @klass.inheritance_column)
27
+ end
28
+
29
+ relation = scope.where(@klass.primary_key => (id_was || id))
30
+ relation = relation.merge(turntable_scope) if turntable_scope
31
+
32
+ bvs = binds + relation.bind_values
33
+ um = relation
34
+ .arel
35
+ .compile_update(substitutes, @klass.primary_key)
36
+
37
+ @klass.connection.update(
38
+ um,
39
+ 'SQL',
40
+ bvs,
41
+ )
42
+ end
43
+ else
44
+ def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # :nodoc:
45
+ substitutes, binds = substitute_values values
46
+ condition_scope = @klass.unscoped.where(@klass.arel_table[@klass.primary_key].eq(id_was || id))
47
+ condition_scope = condition_scope.merge(turntable_scope) if turntable_scope
48
+ um = condition_scope.arel.compile_update(substitutes, @klass.primary_key)
49
+
50
+ @klass.connection.update(
51
+ um,
52
+ 'SQL',
53
+ binds)
54
+ end
29
55
  end
30
56
  end
31
57
  end
@@ -1,3 +1,5 @@
1
+ require 'active_support/lazy_load_hooks'
2
+
1
3
  module ActiveRecord::Turntable
2
4
  module Base
3
5
  extend ActiveSupport::Concern
@@ -7,12 +9,17 @@ module ActiveRecord::Turntable
7
9
  :turntable_enabled, :turntable_sequencer_enabled
8
10
 
9
11
  self.turntable_connections = {}
10
- self.turntable_clusters = Hash.new {|h,k| h[k]={}}
12
+ self.turntable_clusters = {}.with_indifferent_access
11
13
  self.turntable_enabled = false
12
14
  self.turntable_sequencer_enabled = false
13
15
  class << self
14
16
  delegate :shards_transaction, :with_all, :to => :connection
15
17
  end
18
+
19
+ ActiveSupport.on_load(:turntable_config_loaded) do
20
+ self.initialize_clusters!
21
+ end
22
+ include ClusterHelperMethods
16
23
  end
17
24
 
18
25
  module ClassMethods
@@ -26,55 +33,29 @@ module ActiveRecord::Turntable
26
33
  self.turntable_enabled = true
27
34
  self.turntable_cluster_name = cluster_name
28
35
  self.turntable_shard_key = shard_key_name
29
- self.turntable_cluster = Cluster.new(
30
- self,
31
- turntable_config[:clusters][cluster_name],
32
- options
33
- )
34
- self.turntable_clusters[cluster_name][self] = turntable_cluster
35
-
36
+ self.turntable_cluster =
37
+ self.turntable_clusters[cluster_name] ||= Cluster.new(
38
+ turntable_config[:clusters][cluster_name],
39
+ options
40
+ )
36
41
  turntable_replace_connection_pool
37
- turntable_define_cluster_methods(cluster_name)
38
- end
39
-
40
- #
41
- def force_transaction_all_shards!(options={}, &block)
42
- force_connect_all_shards!
43
- shards = turntable_connections.values
44
- shards += [ActiveRecord::Base.connection_pool]
45
- recursive_transaction(shards, options, &block)
46
42
  end
47
43
 
48
- def recursive_transaction(pools, options, &block)
49
- pool = pools.shift
50
- if pools.present?
51
- pool.connection.transaction(options) do
52
- recursive_transaction(pools, options, &block)
53
- end
54
- else
55
- pool.connection.transaction(options, &block)
56
- end
57
- end
58
-
59
- def force_connect_all_shards!
60
- conf = configurations[Rails.env]
61
- shards = {}
62
- shards = shards.merge(conf["shards"]) if conf["shards"]
63
- shards = shards.merge(conf["seq"]) if conf["seq"]
64
- shards.each do |name, config|
65
- turntable_connections[name] ||=
66
- ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec_for(config))
67
- end
68
- end
69
44
 
70
45
  def turntable_replace_connection_pool
71
46
  ch = connection_handler
72
- cp = turntable_cluster.connection_proxy
47
+ cp = ConnectionProxy.new(self, turntable_cluster)
73
48
  pp = PoolProxy.new(cp)
74
49
  ch.class_to_pool.clear if defined?(ch.class_to_pool)
75
50
  ch.send(:class_to_pool)[name] = ch.send(:owner_to_pool)[name] = pp
76
51
  end
77
52
 
53
+ def initialize_clusters!
54
+ turntable_config[:clusters].each do |name, spec|
55
+ self.turntable_clusters[name] ||= Cluster.new(spec, {})
56
+ end
57
+ end
58
+
78
59
  def spec_for(config)
79
60
  begin
80
61
  require "active_record/connection_adapters/#{config['adapter']}_adapter"
@@ -114,16 +95,6 @@ module ActiveRecord::Turntable
114
95
  turntable_cluster.select_shard(current_sequence) if sequencer_enabled?
115
96
  end
116
97
 
117
- def weighted_random_shard_with(*klasses, &block)
118
- shards_weight = self.turntable_cluster.weighted_shards
119
- sum = shards_weight.values.inject(&:+)
120
- idx = rand(sum)
121
- shard, weight = shards_weight.find {|k,v|
122
- (idx -= v) < 0
123
- }
124
- self.connection.with_recursive_shards(shard.name, *klasses, &block)
125
- end
126
-
127
98
  def with_shard(any_shard)
128
99
  shard = case any_shard
129
100
  when Numeric
@@ -135,41 +106,6 @@ module ActiveRecord::Turntable
135
106
  end
136
107
  connection.with_shard(shard) { yield }
137
108
  end
138
-
139
- private
140
-
141
- def turntable_define_cluster_methods(cluster_name)
142
- turntable_define_cluster_class_methods(cluster_name)
143
- end
144
-
145
- def turntable_define_cluster_class_methods(cluster_name)
146
- (class << ActiveRecord::Base; self; end).class_eval <<-EOD
147
- unless respond_to?(:#{cluster_name}_transaction)
148
- def #{cluster_name}_transaction(shards = [], options = {})
149
- cluster = turntable_clusters[#{cluster_name.inspect}].values.first
150
- cluster.shards_transaction(shards, options) { yield }
151
- end
152
- end
153
-
154
- unless respond_to?(:all_cluster_transaction)
155
- def all_cluster_transaction(options = {})
156
- clusters = turntable_clusters.values.map { |v| v.values.first }
157
- recursive_cluster_transaction(clusters) { yield }
158
- end
159
-
160
- def recursive_cluster_transaction(clusters, options = {}, &block)
161
- current_cluster = clusters.shift
162
- current_cluster.shards_transaction do
163
- if clusters.present?
164
- recursive_cluster_transaction(clusters, options, &block)
165
- else
166
- yield
167
- end
168
- end
169
- end
170
- end
171
- EOD
172
- end
173
109
  end
174
110
 
175
111
  def shards_transaction(options = {}, &block)
@@ -8,15 +8,11 @@ module ActiveRecord::Turntable
8
8
  "algorithm" => "range",
9
9
  }.with_indifferent_access
10
10
 
11
- def initialize(klass, cluster_spec, options = {})
12
- @klass = klass
11
+ def initialize(cluster_spec, options = {})
13
12
  @config = DEFAULT_CONFIG.merge(cluster_spec)
14
13
  @options = options.with_indifferent_access
15
14
  @shards = {}.with_indifferent_access
16
15
 
17
- # setup master shard
18
- @master_shard = MasterShard.new(klass)
19
-
20
16
  # setup sequencer
21
17
  if (seq = (@options[:seq] || @config[:seq])) && seq[:type] == :mysql
22
18
  @seq_shard = SeqShard.new(seq)
@@ -30,36 +26,21 @@ module ActiveRecord::Turntable
30
26
  # setup algorithm
31
27
  alg_name = "ActiveRecord::Turntable::Algorithm::#{@config["algorithm"].camelize}Algorithm"
32
28
  @algorithm = alg_name.constantize.new(@config)
33
-
34
- # setup proxy
35
- @connection_proxy = ConnectionProxy.new(self, cluster_spec)
36
- end
37
-
38
- def klass
39
- @klass
40
- end
41
-
42
- def master
43
- @master_shard
44
29
  end
45
30
 
46
31
  def seq
47
- @seq_shard || @master_shard
32
+ @seq_shard
48
33
  end
49
34
 
50
35
  def shards
51
36
  @shards
52
37
  end
53
38
 
54
- def connection_proxy
55
- @connection_proxy
56
- end
57
-
58
39
  def shard_for(key)
59
40
  @shards[@algorithm.calculate(key)]
60
41
  rescue
61
42
  raise ActiveRecord::Turntable::CannotSpecifyShardError,
62
- "[#{klass}] cannot select_shard for key:#{key}"
43
+ "cannot select_shard for key:#{key}"
63
44
  end
64
45
 
65
46
  def select_shard(key)
@@ -74,8 +55,7 @@ module ActiveRecord::Turntable
74
55
  shards = @shards.values.dup
75
56
  end
76
57
  end
77
- shard_or_object = shards.shift
78
- shard = to_shard(shard_or_object)
58
+ shard = to_shard(shards.shift)
79
59
  if shards.present?
80
60
  shard.connection.transaction(options) do
81
61
  shards_transaction(shards, options, true, &block)
@@ -98,14 +78,12 @@ module ActiveRecord::Turntable
98
78
  when Symbol
99
79
  shards[shard_or_object]
100
80
  else
101
- binding.pry
102
81
  raise ActiveRecord::Turntable::TurntableError,
103
82
  "transaction cannot call to object: #{shard_or_object}"
104
83
  end
105
84
  end
106
85
 
107
86
  def weighted_shards(key = nil)
108
- key ||= @klass.current_sequence
109
87
  Hash[@algorithm.calculate_used_shards_with_weight(key).map do |k,v|
110
88
  [@shards[k], v]
111
89
  end]
@@ -0,0 +1,85 @@
1
+ module ActiveRecord::Turntable
2
+ module ClusterHelperMethods
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ ActiveSupport.on_load(:turntable_config_loaded) do
7
+ turntable_clusters.each do |name, cluster|
8
+ turntable_define_cluster_methods(name)
9
+ end
10
+ end
11
+ end
12
+
13
+ module ClassMethods
14
+ def force_transaction_all_shards!(options={}, &block)
15
+ force_connect_all_shards!
16
+ shards = turntable_connections.values
17
+ shards += [ActiveRecord::Base.connection_pool]
18
+ recursive_transaction(shards, options, &block)
19
+ end
20
+
21
+ def recursive_transaction(pools, options, &block)
22
+ pool = pools.shift
23
+ if pools.present?
24
+ pool.connection.transaction(options) do
25
+ recursive_transaction(pools, options, &block)
26
+ end
27
+ else
28
+ pool.connection.transaction(options, &block)
29
+ end
30
+ end
31
+
32
+ def force_connect_all_shards!
33
+ conf = configurations[Rails.env]
34
+ shards = {}
35
+ shards = shards.merge(conf["shards"]) if conf["shards"]
36
+ shards = shards.merge(conf["seq"]) if conf["seq"]
37
+ shards.each do |name, config|
38
+ turntable_connections[name] ||=
39
+ ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec_for(config))
40
+ end
41
+ end
42
+
43
+ def weighted_random_shard_with(*klasses, &block)
44
+ shards_weight = self.turntable_cluster.weighted_shards(self.current_sequence)
45
+ sum = shards_weight.values.inject(&:+)
46
+ idx = rand(sum)
47
+ shard, weight = shards_weight.find {|k,v|
48
+ (idx -= v) < 0
49
+ }
50
+ self.connection.with_recursive_shards(shard.name, *klasses, &block)
51
+ end
52
+
53
+ def all_cluster_transaction(options = {})
54
+ clusters = turntable_clusters.values
55
+ recursive_cluster_transaction(clusters) { yield }
56
+ end
57
+
58
+ def recursive_cluster_transaction(clusters, options = {}, &block)
59
+ current_cluster = clusters.shift
60
+ current_cluster.shards_transaction do
61
+ if clusters.present?
62
+ recursive_cluster_transaction(clusters, options, &block)
63
+ else
64
+ yield
65
+ end
66
+ end
67
+ end
68
+
69
+ def turntable_define_cluster_methods(cluster_name)
70
+ turntable_define_cluster_class_methods(cluster_name)
71
+ end
72
+
73
+ def turntable_define_cluster_class_methods(cluster_name)
74
+ (class << ActiveRecord::Base; self; end).class_eval <<-EOD
75
+ unless respond_to?(:#{cluster_name}_transaction)
76
+ def #{cluster_name}_transaction(shards = [], options = {})
77
+ cluster = turntable_clusters[#{cluster_name.inspect}]
78
+ cluster.shards_transaction(shards, options) { yield }
79
+ end
80
+ end
81
+ EOD
82
+ end
83
+ end
84
+ end
85
+ end
@@ -1,3 +1,4 @@
1
+ require 'active_support/lazy_load_hooks'
1
2
  require 'active_support/core_ext/hash/indifferent_access'
2
3
 
3
4
  module ActiveRecord::Turntable
@@ -13,12 +14,13 @@ module ActiveRecord::Turntable
13
14
  @config[key]
14
15
  end
15
16
 
16
- def self.load!(config_file, env = (defined?(Rails) ? Rails.env : 'development'))
17
+ def self.load!(config_file = ActiveRecord::Base.turntable_config_file, env = (defined?(Rails) ? Rails.env : 'development'))
17
18
  instance.load!(config_file, env)
18
19
  end
19
20
 
20
21
  def load!(config_file, env)
21
22
  @config = YAML.load(ERB.new(IO.read(config_file)).result).with_indifferent_access[env]
23
+ ActiveSupport.run_load_hooks(:turntable_config_loaded, ActiveRecord::Base)
22
24
  end
23
25
  end
24
26
  end
@@ -6,12 +6,14 @@ module ActiveRecord::Turntable
6
6
  # for expiring query cache
7
7
  CLEAR_CACHE_METHODS = [:update, :insert, :delete, :exec_insert, :exec_update, :exec_delete, :insert_many]
8
8
 
9
+ attr_reader :klass
9
10
  attr_writer :spec
10
11
 
11
- def initialize(cluster, options = {})
12
- @cluster = cluster
13
- @model_class = cluster.klass
14
- @default_current_shard = (cluster.master || cluster.shards.first[1])
12
+ def initialize(klass, cluster, options = {})
13
+ @klass = klass
14
+ @cluster = cluster
15
+ @master_shard = MasterShard.new(klass)
16
+ @default_current_shard = @master_shard
15
17
  @mixer = ActiveRecord::Turntable::Mixer.new(self)
16
18
  end
17
19
 
@@ -36,7 +38,7 @@ module ActiveRecord::Turntable
36
38
  end
37
39
 
38
40
  def enable_query_cache!
39
- @model_class.turntable_connections.each do |k,v|
41
+ klass.turntable_connections.each do |k,v|
40
42
  v.connection.enable_query_cache!
41
43
  end
42
44
  end
@@ -46,7 +48,7 @@ module ActiveRecord::Turntable
46
48
  end
47
49
 
48
50
  def clear_query_cache
49
- @model_class.turntable_connections.each do |k,v|
51
+ klass.turntable_connections.each do |k,v|
50
52
  v.connection.clear_query_cache
51
53
  end
52
54
  end
@@ -91,7 +93,7 @@ module ActiveRecord::Turntable
91
93
  end
92
94
 
93
95
  def master
94
- @cluster.master
96
+ @master_shard
95
97
  end
96
98
 
97
99
  def master_connection
@@ -99,7 +101,7 @@ module ActiveRecord::Turntable
99
101
  end
100
102
 
101
103
  def seq
102
- @cluster.seq
104
+ @cluster.seq || master
103
105
  end
104
106
 
105
107
  def current_shard
@@ -107,7 +109,7 @@ module ActiveRecord::Turntable
107
109
  end
108
110
 
109
111
  def current_shard=(shard)
110
- logger.debug { "Changing #{@model_class}'s shard to #{shard.name}"}
112
+ logger.debug { "Changing #{klass}'s shard to #{shard.name}"}
111
113
  current_shard_entry[object_id] = shard
112
114
  end
113
115
 
@@ -170,7 +172,7 @@ module ActiveRecord::Turntable
170
172
  # Send queries to master connection and all shards in this cluster
171
173
  # @param [Boolean] continue_on_error when a shard raises error, ignore exception and continue
172
174
  def with_master_and_all(continue_on_error = false)
173
- ([@cluster.master] + @cluster.shards.values).map do |shard|
175
+ ([master] + @cluster.shards.values).map do |shard|
174
176
  begin
175
177
  with_shard(shard) {
176
178
  yield
@@ -185,7 +187,7 @@ module ActiveRecord::Turntable
185
187
  end
186
188
 
187
189
  def with_master(&block)
188
- with_shard(@cluster.master) do
190
+ with_shard(master) do
189
191
  yield
190
192
  end
191
193
  end
@@ -126,12 +126,12 @@ module ActiveRecord::Turntable
126
126
  def build_select_fader(tree, method, query, *args, &block)
127
127
  shard_keys = if !tree.where and tree.from.size == 1 and SQLTree::Node::SubQuery === tree.from.first.table_reference.table
128
128
  find_shard_keys(tree.from.first.table_reference.table.where,
129
- @proxy.cluster.klass.table_name,
130
- @proxy.cluster.klass.turntable_shard_key.to_s)
129
+ @proxy.klass.table_name,
130
+ @proxy.klass.turntable_shard_key.to_s)
131
131
  else
132
132
  find_shard_keys(tree.where,
133
- @proxy.cluster.klass.table_name,
134
- @proxy.cluster.klass.turntable_shard_key.to_s)
133
+ @proxy.klass.table_name,
134
+ @proxy.klass.turntable_shard_key.to_s)
135
135
  end
136
136
 
137
137
  if shard_keys.size == 1 # shard
@@ -186,7 +186,7 @@ module ActiveRecord::Turntable
186
186
  end
187
187
 
188
188
  def build_update_fader(tree, method, query, *args, &block)
189
- shard_keys = find_shard_keys(tree.where, @proxy.cluster.klass.table_name, @proxy.cluster.klass.turntable_shard_key.to_s)
189
+ shard_keys = find_shard_keys(tree.where, @proxy.klass.table_name, @proxy.klass.turntable_shard_key.to_s)
190
190
  shards_with_query = if shard_keys.present?
191
191
  build_shards_with_same_query(shard_keys.map {|k| @proxy.cluster.shard_for(k) }, query)
192
192
  else
@@ -208,7 +208,7 @@ module ActiveRecord::Turntable
208
208
  end
209
209
 
210
210
  def build_insert_fader(tree, method, query, *args, &block)
211
- values_hash = divide_insert_values(tree, @proxy.cluster.klass.turntable_shard_key)
211
+ values_hash = divide_insert_values(tree, @proxy.klass.turntable_shard_key)
212
212
  shards_with_query = {}
213
213
  values_hash.each do |k,vs|
214
214
  tree.values = [[SQLTree::Node::Expression::Variable.new("\\0")]]
@@ -12,6 +12,13 @@ module ActiveRecord::Turntable
12
12
  end
13
13
  end
14
14
 
15
+ # initialize
16
+ initializer "turntable.initialize_clusters" do
17
+ ActiveSupport.on_load(:active_record) do
18
+ ActiveRecord::Turntable::Config.load!
19
+ end
20
+ end
21
+
15
22
  # QueryCache Middleware for turntable shards
16
23
  initializer "turntable.insert_query_cache_middleware" do |app|
17
24
  app.middleware.insert_after ActiveRecord::QueryCache, ActiveRecord::Turntable::Rack::QueryCache
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Turntable
3
- VERSION = "2.0.6"
3
+ VERSION = "2.1.0.beta1"
4
4
  end
5
5
  end
@@ -20,6 +20,7 @@ module ActiveRecord::Turntable
20
20
  autoload :Algorithm
21
21
  autoload :Base
22
22
  autoload :Cluster
23
+ autoload :ClusterHelperMethods
23
24
  autoload :Config
24
25
  autoload :ConnectionProxy
25
26
  autoload :MasterShard
@@ -64,5 +65,9 @@ module ActiveRecord::Turntable
64
65
  rails4? && ActiveRecord::VERSION::MINOR >= 1
65
66
  end
66
67
 
68
+ def self.rails42_later?
69
+ rails4? && ActiveRecord::VERSION::MINOR >= 2
70
+ end
71
+
67
72
  require "active_record/turntable/railtie" if defined?(Rails)
68
73
  end
@@ -49,14 +49,14 @@ describe ActiveRecord::Turntable::ActiveRecordExt::Association do
49
49
  let(:cards_user) { CardsUser.where(user: user).first }
50
50
 
51
51
  context "associated objects has same turntable_key" do
52
- subject { cards_user.cards_users_histories }
52
+ subject { cards_user.cards_users_histories.to_a }
53
53
  it { expect { subject }.to_not raise_error }
54
54
  it { is_expected.to include(*cards_users_histories.select { |history| history.cards_user_id == cards_user.id }) }
55
55
  end
56
56
 
57
57
  context "associated objects has different turntable_key" do
58
58
  context "when foreign_shard_key option passed" do
59
- subject { cards_user.events_users_histories_with_foreign_shard_key }
59
+ subject { cards_user.events_users_histories_with_foreign_shard_key.to_a }
60
60
 
61
61
  it { expect { subject }.to_not raise_error }
62
62
  it { is_expected.to include(*events_users_histories.select { |history| history.cards_user_id == cards_user.id }) }
@@ -34,7 +34,9 @@ describe ActiveRecord::Turntable::ActiveRecordExt::Persistence do
34
34
  let(:card){
35
35
  Card.create!(:name => 'foobar')
36
36
  }
37
-
37
+ let(:cards_user){
38
+ user.cards_users.create(card: card)
39
+ }
38
40
  context "When creating record" do
39
41
  context "with blob column" do
40
42
  let(:blob_value) { "\123\123\123" }
@@ -108,31 +110,31 @@ describe ActiveRecord::Turntable::ActiveRecordExt::Persistence do
108
110
 
109
111
  context "When the model is sharded by other key" do
110
112
  it "should send shard_key condition when updating" do
111
- user_status.hp = 20
113
+ cards_user.num = 10
112
114
 
113
115
  strio = StringIO.new
114
116
  ActiveRecord::Base.logger = Logger.new(strio)
115
117
  expect {
116
- user_status.save!
118
+ cards_user.save!
117
119
  }.to_not raise_error
118
- expect(strio.string).to match(/`user_statuses`\.`user_id` = #{user_status.user_id}[^\s]*($|\s)/)
120
+ expect(strio.string).to match(/`cards_users`\.`user_id` = #{cards_user.user_id}[^\s]*($|\s)/)
119
121
  end
120
122
 
121
123
  it "should change updated_at when updating" do
122
- user_status.hp = 20
124
+ cards_user.num = 2
123
125
 
124
126
  expect {
125
- user_status.save!
126
- }.to change(user_status, :updated_at)
127
+ cards_user.save!
128
+ }.to change(cards_user, :updated_at)
127
129
  end
128
130
 
129
131
  it "should send shard_key condition when destroying" do
130
132
  strio = StringIO.new
131
133
  ActiveRecord::Base.logger = Logger.new(strio)
132
134
  expect {
133
- user_status.destroy
135
+ cards_user.destroy
134
136
  }.to_not raise_error
135
- expect(strio.string).to match(/`user_statuses`\.`user_id` = #{user_status.user_id}[^\s]*($|\s)/)
137
+ expect(strio.string).to match(/`cards_users`\.`user_id` = #{cards_user.user_id}[^\s]*($|\s)/)
136
138
  end
137
139
 
138
140
  it "should warn when creating without shard_key" do
@@ -140,39 +142,39 @@ describe ActiveRecord::Turntable::ActiveRecordExt::Persistence do
140
142
  end
141
143
 
142
144
  it "should execute one query when reloading" do
143
- user; user_status
145
+ user; cards_user
144
146
  strio = StringIO.new
145
147
  ActiveRecord::Base.logger = Logger.new(strio)
146
148
 
147
- expect { user_status.reload }.to_not raise_error
149
+ expect { cards_user.reload }.to_not raise_error
148
150
 
149
151
  expect(strio.string.split("\n").select {|stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items
150
152
  end
151
153
 
152
154
  it "should execute one query when touching" do
153
- user; user_status
155
+ user; cards_user
154
156
  strio = StringIO.new
155
157
  ActiveRecord::Base.logger = Logger.new(strio)
156
158
 
157
- expect { user_status.touch }.to_not raise_error
159
+ expect { cards_user.touch }.to_not raise_error
158
160
  expect(strio.string.split("\n").select {|stmt| stmt =~ /UPDATE/ and stmt !~ /Turntable/ }).to have(1).items
159
161
  end
160
162
 
161
163
  it "should execute one query when locking" do
162
- user; user_status
164
+ user; cards_user
163
165
  strio = StringIO.new
164
166
  ActiveRecord::Base.logger = Logger.new(strio)
165
167
 
166
- expect { user_status.lock! }.to_not raise_error
168
+ expect { cards_user.lock! }.to_not raise_error
167
169
  expect(strio.string.split("\n").select {|stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items
168
170
  end
169
171
 
170
172
  it "should execute one query when update_columns" do
171
- user; user_status
173
+ user; cards_user
172
174
  strio = StringIO.new
173
175
  ActiveRecord::Base.logger = Logger.new(strio)
174
176
 
175
- expect { user_status.update_columns(hp: 10) }.to_not raise_error
177
+ expect { cards_user.update_columns(num: 10) }.to_not raise_error
176
178
  expect(strio.string.split("\n").select {|stmt| stmt =~ /UPDATE/ and stmt !~ /Turntable/ }).to have(1).items
177
179
  end
178
180
  end
@@ -199,9 +201,9 @@ describe ActiveRecord::Turntable::ActiveRecordExt::Persistence do
199
201
  end
200
202
 
201
203
  context "When call reload" do
202
- subject { user_status.reload }
203
- it { is_expected.to be_instance_of(UserStatus)}
204
- it { is_expected.to eq(user_status) }
204
+ subject { cards_user.reload }
205
+ it { is_expected.to be_instance_of(CardsUser) }
206
+ it { is_expected.to eq(cards_user) }
205
207
  end
206
208
 
207
209
  end
@@ -10,14 +10,13 @@ describe ActiveRecord::Turntable::Cluster do
10
10
  truncate_shard
11
11
  end
12
12
  let(:cluster_config) { ActiveRecord::Base.turntable_config[:clusters][:user_cluster] }
13
- let(:cluster) { ActiveRecord::Turntable::Cluster.new(User, cluster_config) }
13
+ let(:cluster) { ActiveRecord::Turntable::Cluster.new(cluster_config) }
14
14
  let(:in_range_shard_key_value) { cluster_config[:shards].last[:less_than] - 1 }
15
15
  let(:out_of_range_shard_key_value) { cluster_config[:shards].last[:less_than] }
16
16
 
17
17
  context "When initialized" do
18
18
  subject { cluster }
19
19
 
20
- its(:klass) { should == User }
21
20
  its(:shards) { should have(3).items }
22
21
  end
23
22
 
@@ -11,8 +11,8 @@ describe ActiveRecord::Turntable::ConnectionProxy do
11
11
  truncate_shard
12
12
  end
13
13
 
14
- let(:cluster) { ActiveRecord::Turntable::Cluster.new(User, ActiveRecord::Base.turntable_config[:clusters][:user_cluster]) }
15
- subject { ActiveRecord::Turntable::ConnectionProxy.new(cluster) }
14
+ let(:cluster) { ActiveRecord::Turntable::Cluster.new(ActiveRecord::Base.turntable_config[:clusters][:user_cluster]) }
15
+ subject { ActiveRecord::Turntable::ConnectionProxy.new(User, cluster) }
16
16
 
17
17
  its(:master_connection) { is_expected.to eql(ActiveRecord::Base.connection) }
18
18
  end
@@ -8,8 +8,8 @@ describe ActiveRecord::Turntable::Mixer do
8
8
  before do
9
9
  establish_connection_to(:test)
10
10
  truncate_shard
11
- @cluster = ActiveRecord::Turntable::Cluster.new(User, ActiveRecord::Base.turntable_config[:clusters][:user_cluster])
12
- @connection_proxy = ActiveRecord::Turntable::ConnectionProxy.new(@cluster)
11
+ @cluster = ActiveRecord::Turntable::Cluster.new(ActiveRecord::Base.turntable_config[:clusters][:user_cluster])
12
+ @connection_proxy = ActiveRecord::Turntable::ConnectionProxy.new(User, @cluster)
13
13
  end
14
14
 
15
15
  context "When initialized" do
@@ -12,7 +12,7 @@ describe "transaction" do
12
12
  let(:clusters) { ActiveRecord::Base.turntable_clusters }
13
13
 
14
14
  describe "all_cluster_transaction" do
15
- let(:all_clusters) { clusters.values.map { |v| v.values.first } }
15
+ let(:all_clusters) { clusters.values }
16
16
  let(:shards) { all_clusters.map { |c| c.shards.values }.flatten(1) }
17
17
 
18
18
  it "all shards should begin transaction" do
@@ -23,7 +23,7 @@ describe "transaction" do
23
23
  end
24
24
 
25
25
  describe "cluster_transaction" do
26
- let(:cluster) { clusters[:user_cluster].values.first }
26
+ let(:cluster) { clusters[:user_cluster] }
27
27
  let(:shards) { cluster.shards.values }
28
28
 
29
29
  it "all shards in the cluster should begin transaction" do
data/spec/spec_helper.rb CHANGED
@@ -5,6 +5,11 @@ require 'bundler/setup'
5
5
  require 'rspec/its'
6
6
  require 'rspec/collection_matchers'
7
7
  require 'webmock/rspec'
8
+ require 'pry'
9
+ begin
10
+ require 'pry-byebug'
11
+ rescue LoadError
12
+ end
8
13
 
9
14
  require 'activerecord-turntable'
10
15
 
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: 2.0.6
4
+ version: 2.1.0.beta1
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: 2014-12-08 00:00:00.000000000 Z
12
+ date: 2015-01-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -261,6 +261,20 @@ dependencies:
261
261
  - - ">="
262
262
  - !ruby/object:Gem::Version
263
263
  version: '0'
264
+ - !ruby/object:Gem::Dependency
265
+ name: pry-byebug
266
+ requirement: !ruby/object:Gem::Requirement
267
+ requirements:
268
+ - - ">="
269
+ - !ruby/object:Gem::Version
270
+ version: '0'
271
+ type: :development
272
+ prerelease: false
273
+ version_requirements: !ruby/object:Gem::Requirement
274
+ requirements:
275
+ - - ">="
276
+ - !ruby/object:Gem::Version
277
+ version: '0'
264
278
  - !ruby/object:Gem::Dependency
265
279
  name: guard-rspec
266
280
  requirement: !ruby/object:Gem::Requirement
@@ -354,6 +368,7 @@ files:
354
368
  - lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb
355
369
  - lib/active_record/turntable/base.rb
356
370
  - lib/active_record/turntable/cluster.rb
371
+ - lib/active_record/turntable/cluster_helper_methods.rb
357
372
  - lib/active_record/turntable/config.rb
358
373
  - lib/active_record/turntable/connection_proxy.rb
359
374
  - lib/active_record/turntable/connection_proxy/mixable.rb
@@ -445,9 +460,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
445
460
  version: 1.9.3
446
461
  required_rubygems_version: !ruby/object:Gem::Requirement
447
462
  requirements:
448
- - - ">="
463
+ - - ">"
449
464
  - !ruby/object:Gem::Version
450
- version: '0'
465
+ version: 1.3.1
451
466
  requirements: []
452
467
  rubyforge_project: activerecord-turntable
453
468
  rubygems_version: 2.4.4