active_record_shards 2.6.6 → 2.6.7

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.
@@ -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