active_record_shards 2.6.6 → 2.6.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -40,15 +40,15 @@ ActiveRecord::Base.singleton_class.class_eval do
40
40
  alias_method_chain :establish_connection, :connection_pool_name
41
41
  end
42
42
 
43
- # backport improved connection fetching from rails 3.2
43
+ # old_code.sub('name', 'connection_pool_name')
44
44
  if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
45
45
  class ActiveRecord::Base
46
46
  def self.arel_engine
47
47
  @arel_engine ||= begin
48
48
  if self == ActiveRecord::Base
49
- ActiveRecord::Base
49
+ Arel::Table.engine
50
50
  else
51
- connection_handler.retrieve_connection_pool(self) ? self : superclass.arel_engine
51
+ connection_handler.connection_pools[connection_pool_name] ? self : superclass.arel_engine
52
52
  end
53
53
  end
54
54
  end
@@ -26,12 +26,12 @@ module ActiveRecordShards
26
26
  def on_all_shards(&block)
27
27
  old_options = current_shard_selection.options
28
28
  if supports_sharding?
29
- shard_names.each do |shard|
29
+ shard_names.map do |shard|
30
30
  switch_connection(:shard => shard)
31
31
  yield(shard)
32
32
  end
33
33
  else
34
- yield
34
+ [yield]
35
35
  end
36
36
  ensure
37
37
  switch_connection(old_options)
@@ -83,15 +83,16 @@ module ActiveRecordShards
83
83
  alias_method :with_slave_if, :on_slave_if
84
84
  alias_method :with_slave_unless, :on_slave_unless
85
85
 
86
- def on_cx_switch_block(which, &block)
86
+ def on_cx_switch_block(which, options = {}, &block)
87
87
  old_options = current_shard_selection.options
88
88
  switch_to_slave = (which == :slave && (@disallow_slave.nil? || @disallow_slave == 0))
89
89
  switch_connection(:slave => switch_to_slave)
90
90
 
91
91
  @disallow_slave = (@disallow_slave || 0) + 1 if which == :master
92
92
 
93
- # setting read-only scope on ActiveRecord::Base never made any sense, anyway
94
- if self == ActiveRecord::Base || !switch_to_slave
93
+ # we avoid_readonly_scope to prevent some stack overflow problems, like when
94
+ # .columns calls .with_scope which calls .columns and onward, endlessly.
95
+ if self == ActiveRecord::Base || !switch_to_slave || options[:construct_ro_scope] == false
95
96
  yield
96
97
  else
97
98
  with_scope({:find => {:readonly => true}}, &block)
@@ -1,12 +1,12 @@
1
1
  module ActiveRecordShards
2
2
  module DefaultSlavePatches
3
- CLASS_SLAVE_METHODS = [ :find_by_sql, :count_by_sql, :calculate, :find_one, :find_some, :find_every, :quote_value, :columns, :sanitize_sql_hash_for_conditions ]
3
+ CLASS_SLAVE_METHODS = [ :find_by_sql, :count_by_sql, :calculate, :find_one, :find_some, :find_every, :quote_value, :sanitize_sql_hash_for_conditions ]
4
4
 
5
5
  def self.extended(base)
6
6
  base_methods = (base.methods | base.private_methods).map(&:to_sym)
7
7
  (CLASS_SLAVE_METHODS & base_methods).each do |slave_method|
8
- base.class_eval <<-EOF, __FILE__, __LINE__ + 1
9
- class <<self
8
+ base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
9
+ class << self
10
10
  def #{slave_method}_with_default_slave(*args, &block)
11
11
  on_slave_unless_tx do
12
12
  #{slave_method}_without_default_slave(*args, &block)
@@ -15,7 +15,7 @@ module ActiveRecordShards
15
15
 
16
16
  alias_method_chain :#{slave_method}, :default_slave
17
17
  end
18
- EOF
18
+ RUBY
19
19
  end
20
20
 
21
21
  base.class_eval do
@@ -29,6 +29,19 @@ module ActiveRecordShards
29
29
  end
30
30
  alias_method_chain :reload, :slave_off
31
31
 
32
+ class << self
33
+ def columns_with_default_slave(*args, &block)
34
+ if on_slave_by_default? && !Thread.current[:_active_record_shards_slave_off]
35
+ read_columns_from = :slave
36
+ else
37
+ read_columns_form = :master
38
+ end
39
+
40
+ on_cx_switch_block(read_columns_from, :construct_ro_scope => false) { columns_without_default_slave(*args, &block) }
41
+ end
42
+ alias_method_chain :columns, :default_slave
43
+ end
44
+
32
45
  class << self
33
46
  def transaction_with_slave_off(*args, &block)
34
47
  if on_slave_by_default?
@@ -1,27 +1,20 @@
1
1
  require 'active_record_shards'
2
2
 
3
- Rake::TaskManager.class_eval do
4
- def remove_task(task_name)
5
- @tasks.delete(task_name.to_s)
6
- end
7
- end
8
-
9
- def remove_task(task_name)
10
- Rake.application.remove_task(task_name)
3
+ %w[db:drop db:create db:abort_if_pending_migrations db:reset].each do |name|
4
+ Rake.application.instance_variable_get(:@tasks).delete(name) || warn("could not delete #{name} task, potential load-order problem")
11
5
  end
12
6
 
13
- remove_task 'db:drop'
14
- remove_task 'db:create'
15
- remove_task 'db:abort_if_pending_migrations'
16
- remove_task 'db:reset'
17
-
18
7
  namespace :db do
19
8
  desc 'Drops the database for the current RAILS_ENV including shards and slaves'
20
9
  task :drop => :load_config do
21
10
  env_name = defined?(Rails.env) ? Rails.env : RAILS_ENV || 'development'
22
11
  ActiveRecord::Base.configurations.each do |key, conf|
23
12
  if key.starts_with?(env_name) && !key.ends_with?("_slave")
24
- drop_database(conf)
13
+ begin
14
+ drop_database(conf)
15
+ rescue Exception => e
16
+ puts "Couldn't drop #{conf['database']} : #{e.inspect}"
17
+ end
25
18
  end
26
19
  end
27
20
  end
@@ -46,22 +46,30 @@ class ConnectionSwitchingTest < ActiveSupport::TestCase
46
46
  @shard_0_master = ActiveRecord::Base.on_shard(0) {ActiveRecord::Base.connection}
47
47
  @shard_1_master = ActiveRecord::Base.on_shard(1) {ActiveRecord::Base.connection}
48
48
  assert_not_equal(@shard_0_master.select_value("SELECT DATABASE()"), @shard_1_master.select_value("SELECT DATABASE()"))
49
+ end
49
50
 
50
- @database_names = []
51
- @database_shards = []
52
- ActiveRecord::Base.on_all_shards do |shard|
53
- @database_names << ActiveRecord::Base.connection.select_value("SELECT DATABASE()")
54
- @database_shards << shard
51
+ should "execute the block on all shard masters" do
52
+ result = ActiveRecord::Base.on_all_shards do |shard|
53
+ [ActiveRecord::Base.connection.select_value("SELECT DATABASE()"), shard]
55
54
  end
55
+ database_names = result.map(&:first)
56
+ database_shards = result.map(&:last)
57
+
58
+ assert_equal(2, database_names.size)
59
+ assert_contains(database_names, @shard_0_master.select_value("SELECT DATABASE()"))
60
+ assert_contains(database_names, @shard_1_master.select_value("SELECT DATABASE()"))
61
+
62
+ assert_equal(2, database_shards.size)
63
+ assert_contains(database_shards, "0")
64
+ assert_contains(database_shards, "1")
56
65
  end
57
66
 
58
- should "execute the block on all shard masters" do
59
- assert_equal(2, @database_names.size)
60
- assert_contains(@database_names, @shard_0_master.select_value("SELECT DATABASE()"))
61
- assert_contains(@database_names, @shard_1_master.select_value("SELECT DATABASE()"))
62
- assert_equal(2, @database_shards.size)
63
- assert_contains(@database_shards, "0")
64
- assert_contains(@database_shards, "1")
67
+ should "execute the block unsharded" do
68
+ ActiveRecord::Base.expects(:supports_sharding?).returns false
69
+ result = ActiveRecord::Base.on_all_shards do |shard|
70
+ [ActiveRecord::Base.connection.select_value("SELECT DATABASE()"), shard]
71
+ end
72
+ assert_equal [["ars_test", nil]], result
65
73
  end
66
74
  end
67
75
  end
@@ -322,6 +330,18 @@ class ConnectionSwitchingTest < ActiveSupport::TestCase
322
330
  end
323
331
  end
324
332
 
333
+ context "a inherited model without cached columns hash" do
334
+ # before columns -> with_scope -> type-condition -> columns == loop
335
+ should "not loop when on slave by default" do
336
+ Person.on_slave_by_default = true
337
+ assert User.on_slave_by_default?
338
+ assert User.finder_needs_type_condition?
339
+
340
+ User.instance_variable_set(:@columns_hash, nil)
341
+ User.columns_hash
342
+ end
343
+ end
344
+
325
345
  context "a model loaded with the master" do
326
346
  setup do
327
347
  Account.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'master_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
data/test/models.rb CHANGED
@@ -17,3 +17,11 @@ class Ticket < ActiveRecord::Base
17
17
  # attributes: id, title, account_id, updated_at, created_at
18
18
  belongs_to :account
19
19
  end
20
+
21
+ class Person < ActiveRecord::Base
22
+ not_sharded
23
+ end
24
+
25
+ class User < Person
26
+ end
27
+
data/test/schema.rb CHANGED
@@ -21,4 +21,11 @@ ActiveRecord::Schema.define(:version => 1) do
21
21
  t.datetime "created_at"
22
22
  t.datetime "updated_at"
23
23
  end
24
+
25
+ create_table "people", :force => true do |t|
26
+ t.string "name"
27
+ t.string "type"
28
+ t.datetime "created_at"
29
+ t.datetime "updated_at"
30
+ end
24
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_shards
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.6
4
+ version: 2.6.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-01-15 00:00:00.000000000 Z
14
+ date: 2013-01-16 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activerecord
@@ -242,7 +242,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
242
242
  version: '0'
243
243
  segments:
244
244
  - 0
245
- hash: -1200466778001401541
245
+ hash: -349916606155063800
246
246
  required_rubygems_version: !ruby/object:Gem::Requirement
247
247
  none: false
248
248
  requirements:
@@ -251,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
251
251
  version: '0'
252
252
  segments:
253
253
  - 0
254
- hash: -1200466778001401541
254
+ hash: -349916606155063800
255
255
  requirements: []
256
256
  rubyforge_project:
257
257
  rubygems_version: 1.8.24