activerecord-turntable 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. data/.document +5 -0
  2. data/.gitignore +25 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +25 -0
  5. data/Guardfile +9 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.rdoc +290 -0
  8. data/Rakefile +101 -0
  9. data/activerecord-turntable.gemspec +47 -0
  10. data/lib/active_record/turntable.rb +58 -0
  11. data/lib/active_record/turntable/active_record_ext.rb +26 -0
  12. data/lib/active_record/turntable/active_record_ext/.gitkeep +0 -0
  13. data/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +50 -0
  14. data/lib/active_record/turntable/active_record_ext/clever_load.rb +90 -0
  15. data/lib/active_record/turntable/active_record_ext/fixtures.rb +131 -0
  16. data/lib/active_record/turntable/active_record_ext/log_subscriber.rb +64 -0
  17. data/lib/active_record/turntable/active_record_ext/persistence.rb +95 -0
  18. data/lib/active_record/turntable/active_record_ext/schema_dumper.rb +107 -0
  19. data/lib/active_record/turntable/active_record_ext/sequencer.rb +28 -0
  20. data/lib/active_record/turntable/active_record_ext/transactions.rb +33 -0
  21. data/lib/active_record/turntable/algorithm.rb +7 -0
  22. data/lib/active_record/turntable/algorithm/.gitkeep +0 -0
  23. data/lib/active_record/turntable/algorithm/base.rb +11 -0
  24. data/lib/active_record/turntable/algorithm/range_algorithm.rb +37 -0
  25. data/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +41 -0
  26. data/lib/active_record/turntable/base.rb +130 -0
  27. data/lib/active_record/turntable/cluster.rb +70 -0
  28. data/lib/active_record/turntable/compatible.rb +19 -0
  29. data/lib/active_record/turntable/config.rb +24 -0
  30. data/lib/active_record/turntable/connection_proxy.rb +218 -0
  31. data/lib/active_record/turntable/connection_proxy/mixable.rb +39 -0
  32. data/lib/active_record/turntable/error.rb +8 -0
  33. data/lib/active_record/turntable/helpers.rb +5 -0
  34. data/lib/active_record/turntable/helpers/test_helper.rb +25 -0
  35. data/lib/active_record/turntable/master_shard.rb +28 -0
  36. data/lib/active_record/turntable/migration.rb +132 -0
  37. data/lib/active_record/turntable/mixer.rb +203 -0
  38. data/lib/active_record/turntable/mixer/fader.rb +34 -0
  39. data/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb +15 -0
  40. data/lib/active_record/turntable/mixer/fader/insert_shards_merge_result.rb +24 -0
  41. data/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb +22 -0
  42. data/lib/active_record/turntable/mixer/fader/specified_shard.rb +12 -0
  43. data/lib/active_record/turntable/mixer/fader/update_shards_merge_result.rb +17 -0
  44. data/lib/active_record/turntable/pool_proxy.rb +56 -0
  45. data/lib/active_record/turntable/rack.rb +5 -0
  46. data/lib/active_record/turntable/rack/connection_management.rb +18 -0
  47. data/lib/active_record/turntable/railtie.rb +14 -0
  48. data/lib/active_record/turntable/railties/databases.rake +205 -0
  49. data/lib/active_record/turntable/seq_shard.rb +14 -0
  50. data/lib/active_record/turntable/sequencer.rb +46 -0
  51. data/lib/active_record/turntable/sequencer/api.rb +36 -0
  52. data/lib/active_record/turntable/sequencer/mysql.rb +32 -0
  53. data/lib/active_record/turntable/shard.rb +48 -0
  54. data/lib/active_record/turntable/sql_tree_patch.rb +199 -0
  55. data/lib/active_record/turntable/version.rb +5 -0
  56. data/lib/activerecord-turntable.rb +2 -0
  57. data/lib/generators/active_record/turntable/install_generator.rb +14 -0
  58. data/lib/generators/templates/turntable.yml +40 -0
  59. data/sample_app/.gitignore +16 -0
  60. data/sample_app/Gemfile +41 -0
  61. data/sample_app/README.rdoc +261 -0
  62. data/sample_app/Rakefile +7 -0
  63. data/sample_app/app/assets/images/rails.png +0 -0
  64. data/sample_app/app/assets/javascripts/application.js +15 -0
  65. data/sample_app/app/assets/stylesheets/application.css +13 -0
  66. data/sample_app/app/controllers/application_controller.rb +3 -0
  67. data/sample_app/app/helpers/application_helper.rb +2 -0
  68. data/sample_app/app/mailers/.gitkeep +0 -0
  69. data/sample_app/app/models/.gitkeep +0 -0
  70. data/sample_app/app/models/user.rb +4 -0
  71. data/sample_app/app/views/layouts/application.html.erb +14 -0
  72. data/sample_app/config.ru +4 -0
  73. data/sample_app/config/application.rb +65 -0
  74. data/sample_app/config/boot.rb +6 -0
  75. data/sample_app/config/database.yml +70 -0
  76. data/sample_app/config/environment.rb +5 -0
  77. data/sample_app/config/environments/development.rb +37 -0
  78. data/sample_app/config/environments/production.rb +67 -0
  79. data/sample_app/config/environments/test.rb +37 -0
  80. data/sample_app/config/initializers/backtrace_silencers.rb +7 -0
  81. data/sample_app/config/initializers/inflections.rb +15 -0
  82. data/sample_app/config/initializers/mime_types.rb +5 -0
  83. data/sample_app/config/initializers/secret_token.rb +7 -0
  84. data/sample_app/config/initializers/session_store.rb +8 -0
  85. data/sample_app/config/initializers/wrap_parameters.rb +14 -0
  86. data/sample_app/config/locales/en.yml +5 -0
  87. data/sample_app/config/routes.rb +58 -0
  88. data/sample_app/config/turntable.yml +64 -0
  89. data/sample_app/db/migrate/20120316073058_create_users.rb +11 -0
  90. data/sample_app/db/seeds.rb +7 -0
  91. data/sample_app/lib/assets/.gitkeep +0 -0
  92. data/sample_app/lib/tasks/.gitkeep +0 -0
  93. data/sample_app/log/.gitkeep +0 -0
  94. data/sample_app/public/404.html +26 -0
  95. data/sample_app/public/422.html +26 -0
  96. data/sample_app/public/500.html +25 -0
  97. data/sample_app/public/favicon.ico +0 -0
  98. data/sample_app/public/index.html +241 -0
  99. data/sample_app/public/robots.txt +5 -0
  100. data/sample_app/script/rails +6 -0
  101. data/sample_app/vendor/assets/javascripts/.gitkeep +0 -0
  102. data/sample_app/vendor/assets/stylesheets/.gitkeep +0 -0
  103. data/sample_app/vendor/plugins/.gitkeep +0 -0
  104. data/script/performance/algorithm +32 -0
  105. data/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +81 -0
  106. data/spec/active_record/turntable/active_record_ext/persistence_spec.rb +151 -0
  107. data/spec/active_record/turntable/algorithm/range_algorithm_spec.rb +35 -0
  108. data/spec/active_record/turntable/algorithm_spec.rb +69 -0
  109. data/spec/active_record/turntable/base_spec.rb +13 -0
  110. data/spec/active_record/turntable/cluster_spec.rb +18 -0
  111. data/spec/active_record/turntable/config_spec.rb +17 -0
  112. data/spec/active_record/turntable/connection_proxy_spec.rb +186 -0
  113. data/spec/active_record/turntable/finder_spec.rb +27 -0
  114. data/spec/active_record/turntable/mixer/fader_spec.rb +4 -0
  115. data/spec/active_record/turntable/mixer_spec.rb +114 -0
  116. data/spec/active_record/turntable/shard_spec.rb +21 -0
  117. data/spec/active_record/turntable_spec.rb +30 -0
  118. data/spec/config/database.yml +45 -0
  119. data/spec/config/turntable.yml +17 -0
  120. data/spec/fabricators/.gitkeep +0 -0
  121. data/spec/fabricators/turntable_fabricator.rb +14 -0
  122. data/spec/migrations/.gitkeep +0 -0
  123. data/spec/migrations/001_create_users.rb +16 -0
  124. data/spec/migrations/002_create_user_statuses.rb +16 -0
  125. data/spec/migrations/003_create_cards.rb +14 -0
  126. data/spec/migrations/004_create_cards_users.rb +15 -0
  127. data/spec/spec_helper.rb +23 -0
  128. data/spec/test_models.rb +27 -0
  129. data/spec/turntable_helper.rb +29 -0
  130. metadata +367 -0
@@ -0,0 +1,47 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "active_record/turntable/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "activerecord-turntable"
6
+ s.version = ActiveRecord::Turntable::VERSION
7
+ s.authors = ["gussan"]
8
+ s.homepage = "https://github.com/drecom/activerecord-turntable"
9
+ s.summary = %q{ActiveRecord Sharding plugin}
10
+ s.description = %q{AcviveRecord Sharding plugin}
11
+
12
+ s.rubyforge_project = "activerecord-turntable"
13
+ s.extra_rdoc_files = [
14
+ "LICENSE.txt",
15
+ "README.rdoc"
16
+ ]
17
+
18
+ s.files = `git ls-files | grep -v "^spec"`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ s.licenses = ["MIT"]
23
+ s.rubygems_version = "1.8.16"
24
+
25
+ # runtime dependencies
26
+ s.add_runtime_dependency(%q<activerecord>, [">= 3.0.0"])
27
+ s.add_runtime_dependency(%q<activesupport>, [">=3.0.0"])
28
+ s.add_runtime_dependency(%q<sql_tree>, ["= 0.2.0"])
29
+ s.add_runtime_dependency(%q<bsearch>, ["~> 1.5"])
30
+ s.add_runtime_dependency(%q<httpclient>, [">= 0"])
31
+
32
+ # development dependencies
33
+ s.add_development_dependency(%q<rake>, ["~> 0.9.2"])
34
+ s.add_development_dependency(%q<rspec>, [">= 0"])
35
+ s.add_development_dependency(%q<rr>, [">= 0"])
36
+ s.add_development_dependency(%q<mysql2>, [">= 0"])
37
+ s.add_development_dependency(%q<fabrication>, [">= 0"])
38
+ s.add_development_dependency(%q<faker>, [">= 0"])
39
+ s.add_development_dependency(%q<activerecord-import>, [">= 0"])
40
+ s.add_development_dependency(%q<pry>, [">= 0"])
41
+ s.add_development_dependency(%q<guard-rspec>, [">= 0"])
42
+
43
+ if RUBY_PLATFORM =~ /darwin/
44
+ s.add_development_dependency(%q<growl>, [">= 0"])
45
+ end
46
+ end
47
+
@@ -0,0 +1,58 @@
1
+ #
2
+ #= ActiveRecord::Turntable
3
+ #
4
+ # ActiveRecord Sharding Plugin
5
+ #
6
+ require 'active_record/turntable/version'
7
+ require 'active_record'
8
+ require 'active_record/fixtures'
9
+ require 'active_support/concern'
10
+ require 'active_record/turntable/error'
11
+ require 'logger'
12
+ require 'singleton'
13
+
14
+ module ActiveRecord::Turntable
15
+ extend ActiveSupport::Concern
16
+
17
+ autoload :ActiveRecordExt, 'active_record/turntable/active_record_ext'
18
+ autoload :Algorithm, 'active_record/turntable/algorithm'
19
+ autoload :Base, 'active_record/turntable/base'
20
+ autoload :Cluster, 'active_record/turntable/cluster'
21
+ autoload :Config, 'active_record/turntable/config'
22
+ autoload :Compatible, "active_record/turntable/compatible"
23
+ autoload :ConnectionProxy, 'active_record/turntable/connection_proxy'
24
+ autoload :Helpers, 'active_record/turntable/helpers'
25
+ autoload :MasterShard, 'active_record/turntable/master_shard'
26
+ autoload :Migration, 'active_record/turntable/migration'
27
+ autoload :Mixer, 'active_record/turntable/mixer'
28
+ autoload :PoolProxy, 'active_record/turntable/pool_proxy'
29
+ autoload :Rack, 'active_record/turntable/rack'
30
+ autoload :SeqShard, 'active_record/turntable/seq_shard'
31
+ autoload :Sequencer, 'active_record/turntable/sequencer'
32
+ autoload :Shard, 'active_record/turntable/shard'
33
+
34
+ included do
35
+ include ActiveRecordExt
36
+ include Base
37
+ end
38
+
39
+ module ClassMethods
40
+ DEFAULT_PATH = File.dirname(File.dirname(__FILE__))
41
+
42
+ def turntable_config_file
43
+ @@turntable_config_file ||=
44
+ File.join(defined?(::Rails) ?
45
+ ::Rails.root.to_s : DEFAULT_PATH, 'config/turntable.yml')
46
+ end
47
+
48
+ def turntable_config_file=(filename)
49
+ @@turntable_config_file = filename
50
+ end
51
+
52
+ def turntable_config
53
+ ActiveRecord::Turntable::Config.instance
54
+ end
55
+ end
56
+
57
+ require "active_record/turntable/railtie" if defined?(Rails)
58
+ end
@@ -0,0 +1,26 @@
1
+ module ActiveRecord::Turntable
2
+ module ActiveRecordExt
3
+ extend ActiveSupport::Concern
4
+
5
+ autoload :AbstractAdapter, 'active_record/turntable/active_record_ext/abstract_adapter'
6
+ autoload :CleverLoad, 'active_record/turntable/active_record_ext/clever_load'
7
+ autoload :LogSubscriber, 'active_record/turntable/active_record_ext/log_subscriber'
8
+ autoload :Persistence, 'active_record/turntable/active_record_ext/persistence'
9
+ autoload :SchemaDumper, 'active_record/turntable/active_record_ext/schema_dumper'
10
+ autoload :Sequencer, 'active_record/turntable/active_record_ext/sequencer'
11
+ autoload :Transactions, 'active_record/turntable/active_record_ext/transactions'
12
+
13
+ included do
14
+ include Transactions
15
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, Sequencer)
16
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, AbstractAdapter)
17
+ ActiveRecord::LogSubscriber.send(:include, LogSubscriber)
18
+ ActiveRecord::Persistence.send(:include, Persistence)
19
+ ActiveRecord::Relation.send(:include, CleverLoad)
20
+ ActiveRecord::VERSION::STRING < '3.1' ?
21
+ ActiveRecord::Migration.extend(ActiveRecord::Turntable::Migration) :
22
+ ActiveRecord::Migration.send(:include, ActiveRecord::Turntable::Migration)
23
+ require 'active_record/turntable/active_record_ext/fixtures'
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,50 @@
1
+ module ActiveRecord::Turntable
2
+ module ActiveRecordExt
3
+ module AbstractAdapter
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ protected
8
+
9
+ if ActiveRecord::VERSION::STRING < '3.1'
10
+ def log(sql, name)
11
+ name ||= "SQL"
12
+ @instrumenter.instrument("sql.active_record",
13
+ :sql => sql, :name => name, :connection_id => object_id,
14
+ :turntable_shard_name => turntable_shard_name) do
15
+ yield
16
+ end
17
+ rescue Exception => e
18
+ message = "#{e.class.name}: #{e.message}: #{sql} : #{turntable_shard_name}"
19
+ @logger.debug message if @logger
20
+ raise translate_exception(e, message)
21
+ end
22
+ else
23
+ def log(sql, name = "SQL", binds = [])
24
+ @instrumenter.instrument(
25
+ "sql.active_record",
26
+ :sql => sql,
27
+ :name => name,
28
+ :connection_id => object_id,
29
+ :binds => binds,
30
+ :turntable_shard_name => turntable_shard_name) { yield }
31
+ rescue Exception => e
32
+ message = "#{e.class.name}: #{e.message}: #{sql} : #{turntable_shard_name}"
33
+ @logger.debug message if @logger
34
+ exception = translate_exception(e, message)
35
+ exception.set_backtrace e.backtrace
36
+ raise exception
37
+ end
38
+ end
39
+ end
40
+
41
+ def turntable_shard_name=(name)
42
+ @turntable_shard_name = name.to_s
43
+ end
44
+
45
+ def turntable_shard_name
46
+ @turntable_shard_name
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,90 @@
1
+ module ActiveRecord::Turntable::ActiveRecordExt
2
+ module CleverLoad
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ ActiveRecord::VERSION::STRING < '3.1' ?
7
+ include(AR30):
8
+ include(AR31)
9
+
10
+ class << ActiveRecord::Base
11
+ delegate :clever_load!, :to => :scoped
12
+ end
13
+ end
14
+
15
+ module AR30
16
+ def clever_load!(association_name)
17
+ # load records
18
+ records = self.to_a
19
+ klass = records.first.class
20
+ reflection = klass.reflections[association_name]
21
+
22
+ if reflection
23
+ foreign_class = reflection.klass
24
+ foreign_objects = case reflection.macro
25
+ when :has_one
26
+ foreign_class.where(reflection.primary_key_name => records.map(&reflection.association_primary_key.to_sym).uniq)
27
+ when :belongs_to
28
+ foreign_class.where(reflection.association_primary_key => records.map(&reflection.primary_key_name.to_sym).uniq)
29
+ else
30
+ []
31
+ end
32
+
33
+ self.each do |obj|
34
+ matched_object = case reflection.macro
35
+ when :has_one
36
+ foreign_objects.find {|fo|
37
+ obj.send(reflection.association_primary_key) == fo.send(reflection.primary_key_name)
38
+ }
39
+ when :belongs_to
40
+ foreign_objects.find {|fo|
41
+ obj.send(reflection.primary_key_name) == fo.send(reflection.association_primary_key)
42
+ }
43
+ end
44
+ association_proxy = obj.send("set_#{reflection.name}_target", matched_object)
45
+ # TODO: set reverse_instance
46
+ # association_proxy.send(:set_inverse_instance, matched_object, obj)
47
+ end
48
+ end
49
+ records
50
+ end
51
+ end
52
+
53
+ module AR31
54
+ def clever_load!(association_name)
55
+ # load records
56
+ records = self.to_a
57
+ klass = records.first.class
58
+ reflection = klass.reflections[association_name]
59
+
60
+ if reflection
61
+ foreign_class = reflection.klass
62
+ foreign_objects = case reflection.macro
63
+ when :has_one
64
+ foreign_class.where(reflection.foreign_key => records.map(&reflection.association_primary_key.to_sym).uniq)
65
+ when :belongs_to
66
+ foreign_class.where(reflection.association_primary_key => records.map(&reflection.foreign_key.to_sym).uniq)
67
+ else
68
+ []
69
+ end
70
+
71
+ self.each do |obj|
72
+ matched_object = case reflection.macro
73
+ when :has_one
74
+ foreign_objects.find {|fo|
75
+ obj.send(reflection.association_primary_key) == fo.send(reflection.foreign_key)
76
+ }
77
+ when :belongs_to
78
+ foreign_objects.find {|fo|
79
+ obj.send(reflection.foreign_key) == fo.send(reflection.association_primary_key)
80
+ }
81
+ end
82
+ obj.association(association_name).target = matched_object
83
+ obj.association(association_name).send(:set_inverse_instance, matched_object)
84
+ end
85
+ end
86
+ records
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,131 @@
1
+ #
2
+ # force TestFixtures to begin transaction with all shards.
3
+ #
4
+ require 'active_record/fixtures'
5
+ module ActiveRecord
6
+ class Fixtures
7
+ def self.create_fixtures(fixtures_directory, table_names, class_names = {})
8
+ table_names = [table_names].flatten.map { |n| n.to_s }
9
+ table_names.each { |n|
10
+ class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/')
11
+ }
12
+
13
+ # FIXME: Apparently JK uses this.
14
+ connection = block_given? ? yield : ActiveRecord::Base.connection
15
+
16
+ files_to_read = table_names.reject { |table_name|
17
+ fixture_is_cached?(connection, table_name)
18
+ }
19
+
20
+ unless files_to_read.empty?
21
+ connection.disable_referential_integrity do
22
+ fixtures_map = {}
23
+
24
+ fixture_files = files_to_read.map do |path|
25
+ table_name = path.tr '/', '_'
26
+
27
+ fixtures_map[path] = ActiveRecord::Fixtures.new(
28
+ connection,
29
+ table_name,
30
+ class_names[table_name.to_sym] || table_name.classify,
31
+ ::File.join(fixtures_directory, path))
32
+ end
33
+
34
+ all_loaded_fixtures.update(fixtures_map)
35
+
36
+ ActiveRecord::Turntable::Base.force_transaction_all_shards!(:requires_new => true) do
37
+ fixture_files.each do |ff|
38
+ conn = ff.model_class.respond_to?(:connection) ? ff.model_class.connection : connection
39
+ table_rows = ff.table_rows
40
+
41
+ table_rows.keys.each do |table|
42
+ conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
43
+ end
44
+
45
+ table_rows.each do |table_name,rows|
46
+ rows.each do |row|
47
+ conn.insert_fixture(row, table_name)
48
+ end
49
+ end
50
+ end
51
+
52
+ # Cap primary key sequences to max(pk).
53
+ if connection.respond_to?(:reset_pk_sequence!)
54
+ table_names.each do |table_name|
55
+ connection.reset_pk_sequence!(table_name.tr('/', '_'))
56
+ end
57
+ end
58
+ end
59
+
60
+ cache_fixtures(connection, fixtures_map)
61
+ end
62
+ end
63
+ cached_fixtures(connection, table_names)
64
+ end
65
+
66
+ end
67
+
68
+ module TestFixtures
69
+ def setup_fixtures
70
+ return unless !ActiveRecord::Base.configurations.blank?
71
+
72
+ if pre_loaded_fixtures && !use_transactional_fixtures
73
+ raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
74
+ end
75
+
76
+ @fixture_cache = {}
77
+ @fixture_connections = []
78
+ @@already_loaded_fixtures ||= {}
79
+
80
+ # Load fixtures once and begin transaction.
81
+ if run_in_transaction?
82
+ if @@already_loaded_fixtures[self.class]
83
+ @loaded_fixtures = @@already_loaded_fixtures[self.class]
84
+ else
85
+ @loaded_fixtures = load_fixtures
86
+ @@already_loaded_fixtures[self.class] = @loaded_fixtures
87
+ end
88
+ ActiveRecord::Base.force_connect_all_shards!
89
+ @fixture_connections = enlist_fixture_connections
90
+ @fixture_connections.each do |connection|
91
+ connection.increment_open_transactions
92
+ connection.transaction_joinable = false
93
+ connection.begin_db_transaction
94
+ end
95
+ # Load fixtures for every test.
96
+ else
97
+ ActiveRecord::Fixtures.reset_cache
98
+ @@already_loaded_fixtures[self.class] = nil
99
+ @loaded_fixtures = load_fixtures
100
+ end
101
+
102
+ # Instantiate fixtures for every test if requested.
103
+ instantiate_fixtures if use_instantiated_fixtures
104
+ end
105
+
106
+ def enlist_fixture_connections
107
+ ActiveRecord::Base.connection_handler.connection_pools.values.map(&:connection) +
108
+ ActiveRecord::Base.turntable_connections.values.map(&:connection)
109
+ end
110
+
111
+ def teardown_fixtures
112
+ return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
113
+
114
+ unless run_in_transaction?
115
+ ActiveRecord::Fixtures.reset_cache
116
+ end
117
+
118
+ # Rollback changes if a transaction is active.
119
+ if run_in_transaction?
120
+ @fixture_connections.each do |connection|
121
+ if connection.open_transactions != 0
122
+ connection.rollback_db_transaction
123
+ connection.decrement_open_transactions
124
+ end
125
+ end
126
+ @fixture_connections.clear
127
+ end
128
+ ActiveRecord::Base.clear_active_connections!
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,64 @@
1
+ module ActiveRecord::Turntable
2
+ module ActiveRecordExt
3
+ module LogSubscriber
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ if ActiveRecord::VERSION::STRING < '3.1'
8
+ def sql(event)
9
+ self.class.runtime += event.duration
10
+ return unless logger.debug?
11
+
12
+ name = '%s (%.1fms)' % [event.payload[:name], event.duration]
13
+ shard = '[Shard: %s]' % (event.payload[:turntable_shard_name] ? event.payload[:turntable_shard_name] : nil)
14
+ sql = event.payload[:sql].squeeze(' ')
15
+
16
+ if odd?
17
+ name = color(name, ActiveRecord::LogSubscriber::CYAN, true)
18
+ shard = color(shard, ActiveRecord::LogSubscriber::CYAN, true)
19
+ sql = color(sql, nil, true)
20
+ else
21
+ name = color(name, ActiveRecord::LogSubscriber::MAGENTA, true)
22
+ shard = color(shard, ActiveRecord::LogSubscriber::MAGENTA, true)
23
+ end
24
+
25
+ debug " #{name} #{shard} #{sql}"
26
+ end
27
+
28
+ else
29
+ def sql(event)
30
+ self.class.runtime += event.duration
31
+ return unless logger.debug?
32
+
33
+ payload = event.payload
34
+
35
+ return if 'SCHEMA' == payload[:name]
36
+
37
+ name = '%s (%.1fms)' % [payload[:name], event.duration]
38
+ shard = '[Shard: %s]' % (event.payload[:turntable_shard_name] ? event.payload[:turntable_shard_name] : nil)
39
+ sql = payload[:sql].squeeze(' ')
40
+ binds = nil
41
+
42
+ unless (payload[:binds] || []).empty?
43
+ binds = " " + payload[:binds].map { |col,v|
44
+ [col.name, v]
45
+ }.inspect
46
+ end
47
+
48
+ if odd?
49
+ name = color(name, ActiveRecord::LogSubscriber::CYAN, true)
50
+ shard = color(shard, ActiveRecord::LogSubscriber::CYAN, true)
51
+ sql = color(sql, nil, true)
52
+ else
53
+ name = color(name, ActiveRecord::LogSubscriber::MAGENTA, true)
54
+ shard = color(shard, ActiveRecord::LogSubscriber::MAGENTA, true)
55
+ end
56
+
57
+ debug " #{name} #{shard} #{sql}#{binds}"
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+