activerecord 5.0.7.2 → 5.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (216) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +389 -2252
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +28 -28
  6. data/examples/simple.rb +3 -3
  7. data/lib/active_record.rb +20 -20
  8. data/lib/active_record/aggregations.rb +244 -244
  9. data/lib/active_record/association_relation.rb +5 -5
  10. data/lib/active_record/associations.rb +1579 -1569
  11. data/lib/active_record/associations/alias_tracker.rb +1 -1
  12. data/lib/active_record/associations/association.rb +23 -15
  13. data/lib/active_record/associations/association_scope.rb +83 -81
  14. data/lib/active_record/associations/belongs_to_association.rb +0 -1
  15. data/lib/active_record/associations/builder/belongs_to.rb +16 -14
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -2
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
  18. data/lib/active_record/associations/collection_association.rb +74 -241
  19. data/lib/active_record/associations/collection_proxy.rb +144 -70
  20. data/lib/active_record/associations/has_many_association.rb +15 -19
  21. data/lib/active_record/associations/has_many_through_association.rb +12 -5
  22. data/lib/active_record/associations/has_one_association.rb +22 -28
  23. data/lib/active_record/associations/has_one_through_association.rb +5 -1
  24. data/lib/active_record/associations/join_dependency.rb +117 -115
  25. data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
  26. data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
  27. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  28. data/lib/active_record/associations/preloader.rb +94 -94
  29. data/lib/active_record/associations/preloader/association.rb +87 -64
  30. data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
  31. data/lib/active_record/associations/preloader/collection_association.rb +6 -6
  32. data/lib/active_record/associations/preloader/has_many.rb +0 -2
  33. data/lib/active_record/associations/preloader/singular_association.rb +6 -8
  34. data/lib/active_record/associations/preloader/through_association.rb +34 -41
  35. data/lib/active_record/associations/singular_association.rb +8 -25
  36. data/lib/active_record/associations/through_association.rb +3 -6
  37. data/lib/active_record/attribute.rb +98 -71
  38. data/lib/active_record/attribute/user_provided_default.rb +4 -2
  39. data/lib/active_record/attribute_assignment.rb +61 -61
  40. data/lib/active_record/attribute_decorators.rb +35 -13
  41. data/lib/active_record/attribute_methods.rb +56 -65
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
  43. data/lib/active_record/attribute_methods/dirty.rb +216 -34
  44. data/lib/active_record/attribute_methods/primary_key.rb +78 -73
  45. data/lib/active_record/attribute_methods/read.rb +39 -35
  46. data/lib/active_record/attribute_methods/serialization.rb +7 -7
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
  48. data/lib/active_record/attribute_methods/write.rb +36 -30
  49. data/lib/active_record/attribute_mutation_tracker.rb +53 -10
  50. data/lib/active_record/attribute_set.rb +9 -6
  51. data/lib/active_record/attribute_set/builder.rb +41 -49
  52. data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
  53. data/lib/active_record/attributes.rb +21 -21
  54. data/lib/active_record/autosave_association.rb +13 -13
  55. data/lib/active_record/base.rb +24 -22
  56. data/lib/active_record/callbacks.rb +52 -14
  57. data/lib/active_record/coders/yaml_column.rb +9 -11
  58. data/lib/active_record/collection_cache_key.rb +6 -17
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
  62. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
  63. data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
  64. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
  65. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
  66. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
  67. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
  68. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
  71. data/lib/active_record/connection_adapters/column.rb +27 -5
  72. data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
  73. data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
  92. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
  93. data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
  94. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  95. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
  97. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
  98. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
  100. data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
  101. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
  103. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
  104. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
  105. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
  106. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
  107. data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
  108. data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
  109. data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
  110. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
  111. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
  112. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
  113. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
  114. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
  115. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
  116. data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
  117. data/lib/active_record/connection_handling.rb +14 -26
  118. data/lib/active_record/core.rb +110 -93
  119. data/lib/active_record/counter_cache.rb +62 -13
  120. data/lib/active_record/define_callbacks.rb +20 -0
  121. data/lib/active_record/dynamic_matchers.rb +80 -79
  122. data/lib/active_record/enum.rb +8 -6
  123. data/lib/active_record/errors.rb +58 -15
  124. data/lib/active_record/explain.rb +1 -2
  125. data/lib/active_record/explain_registry.rb +1 -1
  126. data/lib/active_record/explain_subscriber.rb +7 -4
  127. data/lib/active_record/fixture_set/file.rb +11 -8
  128. data/lib/active_record/fixtures.rb +66 -53
  129. data/lib/active_record/gem_version.rb +3 -3
  130. data/lib/active_record/inheritance.rb +93 -79
  131. data/lib/active_record/integration.rb +7 -7
  132. data/lib/active_record/internal_metadata.rb +3 -16
  133. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  134. data/lib/active_record/locking/optimistic.rb +64 -56
  135. data/lib/active_record/locking/pessimistic.rb +10 -1
  136. data/lib/active_record/log_subscriber.rb +29 -29
  137. data/lib/active_record/migration.rb +155 -172
  138. data/lib/active_record/migration/command_recorder.rb +94 -94
  139. data/lib/active_record/migration/compatibility.rb +76 -37
  140. data/lib/active_record/migration/join_table.rb +6 -6
  141. data/lib/active_record/model_schema.rb +85 -119
  142. data/lib/active_record/nested_attributes.rb +200 -199
  143. data/lib/active_record/null_relation.rb +10 -33
  144. data/lib/active_record/persistence.rb +45 -38
  145. data/lib/active_record/query_cache.rb +4 -8
  146. data/lib/active_record/querying.rb +2 -3
  147. data/lib/active_record/railtie.rb +16 -17
  148. data/lib/active_record/railties/controller_runtime.rb +6 -2
  149. data/lib/active_record/railties/databases.rake +125 -140
  150. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  151. data/lib/active_record/readonly_attributes.rb +2 -2
  152. data/lib/active_record/reflection.rb +79 -96
  153. data/lib/active_record/relation.rb +72 -115
  154. data/lib/active_record/relation/batches.rb +87 -58
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
  156. data/lib/active_record/relation/calculations.rb +154 -160
  157. data/lib/active_record/relation/delegation.rb +30 -29
  158. data/lib/active_record/relation/finder_methods.rb +195 -226
  159. data/lib/active_record/relation/merger.rb +58 -62
  160. data/lib/active_record/relation/predicate_builder.rb +92 -89
  161. data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
  162. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
  163. data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
  164. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
  165. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
  166. data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
  167. data/lib/active_record/relation/query_attribute.rb +1 -1
  168. data/lib/active_record/relation/query_methods.rb +247 -295
  169. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  170. data/lib/active_record/relation/spawn_methods.rb +4 -5
  171. data/lib/active_record/relation/where_clause.rb +79 -65
  172. data/lib/active_record/relation/where_clause_factory.rb +47 -8
  173. data/lib/active_record/result.rb +29 -31
  174. data/lib/active_record/runtime_registry.rb +3 -3
  175. data/lib/active_record/sanitization.rb +182 -197
  176. data/lib/active_record/schema.rb +3 -3
  177. data/lib/active_record/schema_dumper.rb +14 -37
  178. data/lib/active_record/schema_migration.rb +3 -3
  179. data/lib/active_record/scoping.rb +9 -10
  180. data/lib/active_record/scoping/default.rb +87 -91
  181. data/lib/active_record/scoping/named.rb +16 -28
  182. data/lib/active_record/secure_token.rb +2 -2
  183. data/lib/active_record/statement_cache.rb +13 -15
  184. data/lib/active_record/store.rb +31 -32
  185. data/lib/active_record/suppressor.rb +2 -1
  186. data/lib/active_record/table_metadata.rb +9 -5
  187. data/lib/active_record/tasks/database_tasks.rb +72 -65
  188. data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
  189. data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
  190. data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
  191. data/lib/active_record/timestamp.rb +39 -25
  192. data/lib/active_record/touch_later.rb +1 -2
  193. data/lib/active_record/transactions.rb +98 -110
  194. data/lib/active_record/type.rb +17 -13
  195. data/lib/active_record/type/adapter_specific_registry.rb +46 -42
  196. data/lib/active_record/type/decimal_without_scale.rb +9 -0
  197. data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
  198. data/lib/active_record/type/serialized.rb +8 -8
  199. data/lib/active_record/type/text.rb +9 -0
  200. data/lib/active_record/type/time.rb +0 -1
  201. data/lib/active_record/type/type_map.rb +11 -15
  202. data/lib/active_record/type/unsigned_integer.rb +15 -0
  203. data/lib/active_record/type_caster.rb +2 -2
  204. data/lib/active_record/type_caster/connection.rb +8 -6
  205. data/lib/active_record/type_caster/map.rb +3 -1
  206. data/lib/active_record/validations.rb +4 -4
  207. data/lib/active_record/validations/associated.rb +1 -1
  208. data/lib/active_record/validations/presence.rb +2 -2
  209. data/lib/active_record/validations/uniqueness.rb +8 -39
  210. data/lib/active_record/version.rb +1 -1
  211. data/lib/rails/generators/active_record.rb +4 -4
  212. data/lib/rails/generators/active_record/migration.rb +2 -2
  213. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
  214. data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
  215. metadata +22 -13
  216. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,5 +1,4 @@
1
- require 'active_support/lazy_load_hooks'
2
- require 'active_record/explain_registry'
1
+ require "active_record/explain_registry"
3
2
 
4
3
  module ActiveRecord
5
4
  module Explain
@@ -1,4 +1,4 @@
1
- require 'active_support/per_thread_registry'
1
+ require "active_support/per_thread_registry"
2
2
 
3
3
  module ActiveRecord
4
4
  # This is a thread locals registry for EXPLAIN. For example
@@ -1,5 +1,5 @@
1
- require 'active_support/notifications'
2
- require 'active_record/explain_registry'
1
+ require "active_support/notifications"
2
+ require "active_record/explain_registry"
3
3
 
4
4
  module ActiveRecord
5
5
  class ExplainSubscriber # :nodoc:
@@ -18,10 +18,13 @@ module ActiveRecord
18
18
  #
19
19
  # On the other hand, we want to monitor the performance of our real database
20
20
  # queries, not the performance of the access to the query cache.
21
- IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN CACHE)
21
+ IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN)
22
22
  EXPLAINED_SQLS = /\A\s*(with|select|update|delete|insert)\b/i
23
23
  def ignore_payload?(payload)
24
- payload[:exception] || IGNORED_PAYLOADS.include?(payload[:name]) || payload[:sql] !~ EXPLAINED_SQLS
24
+ payload[:exception] ||
25
+ payload[:cached] ||
26
+ IGNORED_PAYLOADS.include?(payload[:name]) ||
27
+ payload[:sql] !~ EXPLAINED_SQLS
25
28
  end
26
29
 
27
30
  ActiveSupport::Notifications.subscribe("sql.active_record", new)
@@ -1,5 +1,5 @@
1
- require 'erb'
2
- require 'yaml'
1
+ require "erb"
2
+ require "yaml"
3
3
 
4
4
  module ActiveRecord
5
5
  class FixtureSet
@@ -24,21 +24,21 @@ module ActiveRecord
24
24
  end
25
25
 
26
26
  def model_class
27
- config_row['model_class']
27
+ config_row["model_class"]
28
28
  end
29
29
 
30
30
  private
31
31
  def rows
32
- @rows ||= raw_rows.reject { |fixture_name, _| fixture_name == '_fixture' }
32
+ @rows ||= raw_rows.reject { |fixture_name, _| fixture_name == "_fixture" }
33
33
  end
34
34
 
35
35
  def config_row
36
36
  @config_row ||= begin
37
- row = raw_rows.find { |fixture_name, _| fixture_name == '_fixture' }
37
+ row = raw_rows.find { |fixture_name, _| fixture_name == "_fixture" }
38
38
  if row
39
39
  row.last
40
40
  else
41
- {'model_class': nil}
41
+ { 'model_class': nil }
42
42
  end
43
43
  end
44
44
  end
@@ -66,10 +66,13 @@ module ActiveRecord
66
66
  # Validate our unmarshalled data.
67
67
  def validate(data)
68
68
  unless Hash === data || YAML::Omap === data
69
- raise Fixture::FormatError, 'fixture is not a hash'
69
+ raise Fixture::FormatError, "fixture is not a hash: #{@file}"
70
70
  end
71
71
 
72
- raise Fixture::FormatError unless data.all? { |name, row| Hash === row }
72
+ invalid = data.reject { |_, row| Hash === row }
73
+ if invalid.any?
74
+ raise Fixture::FormatError, "fixture key is not a hash: #{@file}, keys: #{invalid.keys.inspect}"
75
+ end
73
76
  data
74
77
  end
75
78
  end
@@ -1,11 +1,11 @@
1
- require 'erb'
2
- require 'yaml'
3
- require 'zlib'
4
- require 'set'
5
- require 'active_support/dependencies'
6
- require 'active_support/core_ext/digest/uuid'
7
- require 'active_record/fixture_set/file'
8
- require 'active_record/errors'
1
+ require "erb"
2
+ require "yaml"
3
+ require "zlib"
4
+ require "set"
5
+ require "active_support/dependencies"
6
+ require "active_support/core_ext/digest/uuid"
7
+ require "active_record/fixture_set/file"
8
+ require "active_record/errors"
9
9
 
10
10
  module ActiveRecord
11
11
  class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
@@ -66,7 +66,7 @@ module ActiveRecord
66
66
  # By default, +test_helper.rb+ will load all of your fixtures into your test
67
67
  # database, so this test will succeed.
68
68
  #
69
- # The testing environment will automatically load the all fixtures into the database before each
69
+ # The testing environment will automatically load all the fixtures into the database before each
70
70
  # test. To ensure consistent data, the environment deletes the fixtures before running the load.
71
71
  #
72
72
  # In addition to being available in the database, the fixture's data may also be accessed by
@@ -88,7 +88,7 @@ module ActiveRecord
88
88
  # assert_equal "Ruby on Rails", @rubyonrails.name
89
89
  # end
90
90
  #
91
- # In order to use these methods to access fixtured data within your testcases, you must specify one of the
91
+ # In order to use these methods to access fixtured data within your test cases, you must specify one of the
92
92
  # following in your ActiveSupport::TestCase-derived class:
93
93
  #
94
94
  # - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
@@ -103,7 +103,7 @@ module ActiveRecord
103
103
  #
104
104
  # = Dynamic fixtures with ERB
105
105
  #
106
- # Some times you don't care about the content of the fixtures as much as you care about the volume.
106
+ # Sometimes you don't care about the content of the fixtures as much as you care about the volume.
107
107
  # In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
108
108
  # testing, like:
109
109
  #
@@ -415,9 +415,9 @@ module ActiveRecord
415
415
  # possibly in a folder with the same name.
416
416
  #++
417
417
 
418
- MAX_ID = 2 ** 30 - 1
418
+ MAX_ID = 2**30 - 1
419
419
 
420
- @@all_cached_fixtures = Hash.new { |h,k| h[k] = {} }
420
+ @@all_cached_fixtures = Hash.new { |h, k| h[k] = {} }
421
421
 
422
422
  def self.default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
423
423
  config.pluralize_table_names ?
@@ -426,9 +426,9 @@ module ActiveRecord
426
426
  end
427
427
 
428
428
  def self.default_fixture_table_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
429
- "#{ config.table_name_prefix }"\
430
- "#{ fixture_set_name.tr('/', '_') }"\
431
- "#{ config.table_name_suffix }".to_sym
429
+ "#{ config.table_name_prefix }"\
430
+ "#{ fixture_set_name.tr('/', '_') }"\
431
+ "#{ config.table_name_suffix }".to_sym
432
432
  end
433
433
 
434
434
  def self.reset_cache
@@ -494,18 +494,18 @@ module ActiveRecord
494
494
 
495
495
  private
496
496
 
497
- def insert_class(class_names, name, klass)
498
- # We only want to deal with AR objects.
499
- if klass && klass < ActiveRecord::Base
500
- class_names[name] = klass
501
- else
502
- class_names[name] = nil
497
+ def insert_class(class_names, name, klass)
498
+ # We only want to deal with AR objects.
499
+ if klass && klass < ActiveRecord::Base
500
+ class_names[name] = klass
501
+ else
502
+ class_names[name] = nil
503
+ end
503
504
  end
504
- end
505
505
 
506
- def default_fixture_model(fs_name, config)
507
- ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
508
- end
506
+ def default_fixture_model(fs_name, config)
507
+ ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
508
+ end
509
509
  end
510
510
 
511
511
  def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
@@ -597,18 +597,18 @@ module ActiveRecord
597
597
 
598
598
  @fixtures = read_fixture_files(path)
599
599
 
600
- @connection = connection
600
+ @connection = connection
601
601
 
602
- @table_name = ( model_class.respond_to?(:table_name) ?
602
+ @table_name = (model_class.respond_to?(:table_name) ?
603
603
  model_class.table_name :
604
- self.class.default_fixture_table_name(name, config) )
604
+ self.class.default_fixture_table_name(name, config))
605
605
  end
606
606
 
607
607
  def [](x)
608
608
  fixtures[x]
609
609
  end
610
610
 
611
- def []=(k,v)
611
+ def []=(k, v)
612
612
  fixtures[k] = v
613
613
  end
614
614
 
@@ -626,10 +626,10 @@ module ActiveRecord
626
626
  now = config.default_timezone == :utc ? Time.now.utc : Time.now
627
627
 
628
628
  # allow a standard key to be used for doing defaults in YAML
629
- fixtures.delete('DEFAULTS')
629
+ fixtures.delete("DEFAULTS")
630
630
 
631
631
  # track any join tables we need to insert later
632
- rows = Hash.new { |h,table| h[table] = [] }
632
+ rows = Hash.new { |h, table| h[table] = [] }
633
633
 
634
634
  rows[table_name] = fixtures.map do |label, fixture|
635
635
  row = fixture.to_hash
@@ -799,7 +799,6 @@ module ActiveRecord
799
799
  def yaml_file_path(path)
800
800
  "#{path}.yml"
801
801
  end
802
-
803
802
  end
804
803
 
805
804
  class Fixture #:nodoc:
@@ -859,33 +858,21 @@ module ActiveRecord
859
858
  end
860
859
 
861
860
  included do
862
- class_attribute :fixture_path, :instance_writer => false
861
+ class_attribute :fixture_path, instance_writer: false
863
862
  class_attribute :fixture_table_names
864
863
  class_attribute :fixture_class_names
865
864
  class_attribute :use_transactional_tests
866
- class_attribute :use_transactional_fixtures
867
865
  class_attribute :use_instantiated_fixtures # true, false, or :no_instances
868
866
  class_attribute :pre_loaded_fixtures
869
867
  class_attribute :config
870
868
 
871
- singleton_class.deprecate 'use_transactional_fixtures=' => 'use use_transactional_tests= instead'
872
-
873
869
  self.fixture_table_names = []
874
870
  self.use_instantiated_fixtures = false
875
871
  self.pre_loaded_fixtures = false
876
872
  self.config = ActiveRecord::Base
877
873
 
878
874
  self.fixture_class_names = {}
879
-
880
- silence_warnings do
881
- define_singleton_method :use_transactional_tests do
882
- if use_transactional_fixtures.nil?
883
- true
884
- else
885
- use_transactional_fixtures
886
- end
887
- end
888
- end
875
+ self.use_transactional_tests = true
889
876
  end
890
877
 
891
878
  module ClassMethods
@@ -898,12 +885,12 @@ module ActiveRecord
898
885
  #
899
886
  # The keys must be the fixture names, that coincide with the short paths to the fixture files.
900
887
  def set_fixture_class(class_names = {})
901
- self.fixture_class_names = self.fixture_class_names.merge(class_names.stringify_keys)
888
+ self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
902
889
  end
903
890
 
904
891
  def fixtures(*fixture_set_names)
905
892
  if fixture_set_names.first == :all
906
- fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
893
+ fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"].uniq
907
894
  fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
908
895
  else
909
896
  fixture_set_names = fixture_set_names.flatten.map(&:to_s)
@@ -918,7 +905,7 @@ module ActiveRecord
918
905
  methods = Module.new do
919
906
  fixture_set_names.each do |fs_name|
920
907
  fs_name = fs_name.to_s
921
- accessor_name = fs_name.tr('/', '_').to_sym
908
+ accessor_name = fs_name.tr("/", "_").to_sym
922
909
 
923
910
  define_method(accessor_name) do |*fixture_names|
924
911
  force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
@@ -962,12 +949,13 @@ module ActiveRecord
962
949
 
963
950
  def setup_fixtures(config = ActiveRecord::Base)
964
951
  if pre_loaded_fixtures && !use_transactional_tests
965
- raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_tests'
952
+ raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
966
953
  end
967
954
 
968
955
  @fixture_cache = {}
969
956
  @fixture_connections = []
970
957
  @@already_loaded_fixtures ||= {}
958
+ @connection_subscriber = nil
971
959
 
972
960
  # Load fixtures once and begin transaction.
973
961
  if run_in_transaction?
@@ -977,10 +965,33 @@ module ActiveRecord
977
965
  @loaded_fixtures = load_fixtures(config)
978
966
  @@already_loaded_fixtures[self.class] = @loaded_fixtures
979
967
  end
968
+
969
+ # Begin transactions for connections already established
980
970
  @fixture_connections = enlist_fixture_connections
981
971
  @fixture_connections.each do |connection|
982
972
  connection.begin_transaction joinable: false
973
+ connection.pool.lock_thread = true
983
974
  end
975
+
976
+ # When connections are established in the future, begin a transaction too
977
+ @connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
978
+ spec_name = payload[:spec_name] if payload.key?(:spec_name)
979
+
980
+ if spec_name
981
+ begin
982
+ connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name)
983
+ rescue ConnectionNotEstablished
984
+ connection = nil
985
+ end
986
+
987
+ if connection && !@fixture_connections.include?(connection)
988
+ connection.begin_transaction joinable: false
989
+ connection.pool.lock_thread = true
990
+ @fixture_connections << connection
991
+ end
992
+ end
993
+ end
994
+
984
995
  # Load fixtures for every test.
985
996
  else
986
997
  ActiveRecord::FixtureSet.reset_cache
@@ -995,8 +1006,10 @@ module ActiveRecord
995
1006
  def teardown_fixtures
996
1007
  # Rollback changes if a transaction is active.
997
1008
  if run_in_transaction?
1009
+ ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
998
1010
  @fixture_connections.each do |connection|
999
1011
  connection.rollback_transaction if connection.transaction_open?
1012
+ connection.pool.lock_thread = false
1000
1013
  end
1001
1014
  @fixture_connections.clear
1002
1015
  else
@@ -1018,10 +1031,10 @@ module ActiveRecord
1018
1031
 
1019
1032
  def instantiate_fixtures
1020
1033
  if pre_loaded_fixtures
1021
- raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
1034
+ raise RuntimeError, "Load fixtures before instantiating them." if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
1022
1035
  ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
1023
1036
  else
1024
- raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
1037
+ raise RuntimeError, "Load fixtures before instantiating them." if @loaded_fixtures.nil?
1025
1038
  @loaded_fixtures.each_value do |fixture_set|
1026
1039
  ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
1027
1040
  end
@@ -6,9 +6,9 @@ module ActiveRecord
6
6
 
7
7
  module VERSION
8
8
  MAJOR = 5
9
- MINOR = 0
10
- TINY = 7
11
- PRE = "2"
9
+ MINOR = 1
10
+ TINY = 0
11
+ PRE = "beta1"
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/hash/indifferent_access'
1
+ require "active_support/core_ext/hash/indifferent_access"
2
2
 
3
3
  module ActiveRecord
4
4
  # == Single table inheritance
@@ -19,7 +19,7 @@ module ActiveRecord
19
19
  # Be aware that because the type column is an attribute on the record every new
20
20
  # subclass will instantly be marked as dirty and the type column will be included
21
21
  # in the list of changed attributes on the record. This is different from non
22
- # STI classes:
22
+ # Single Table Inheritance(STI) classes:
23
23
  #
24
24
  # Company.new.changed? # => false
25
25
  # Firm.new.changed? # => true
@@ -37,6 +37,7 @@ module ActiveRecord
37
37
 
38
38
  included do
39
39
  # Determines whether to store the full constant name including namespace when using STI.
40
+ # This is true, by default.
40
41
  class_attribute :store_full_sti_class, instance_writer: false
41
42
  self.store_full_sti_class = true
42
43
  end
@@ -129,87 +130,100 @@ module ActiveRecord
129
130
  store_full_sti_class ? name : name.demodulize
130
131
  end
131
132
 
133
+ def inherited(subclass)
134
+ subclass.instance_variable_set(:@_type_candidates_cache, Concurrent::Map.new)
135
+ super
136
+ end
137
+
132
138
  protected
133
139
 
134
- # Returns the class type of the record using the current module as a prefix. So descendants of
135
- # MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.
136
- def compute_type(type_name)
137
- if type_name.match(/^::/)
138
- # If the type is prefixed with a scope operator then we assume that
139
- # the type_name is an absolute reference.
140
- ActiveSupport::Dependencies.constantize(type_name)
141
- else
142
- # Build a list of candidates to search for
143
- candidates = []
144
- name.scan(/::|$/) { candidates.unshift "#{$`}::#{type_name}" }
145
- candidates << type_name
146
-
147
- candidates.each do |candidate|
148
- constant = ActiveSupport::Dependencies.safe_constantize(candidate)
149
- return constant if candidate == constant.to_s
140
+ # Returns the class type of the record using the current module as a prefix. So descendants of
141
+ # MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.
142
+ def compute_type(type_name)
143
+ if type_name.start_with?("::".freeze)
144
+ # If the type is prefixed with a scope operator then we assume that
145
+ # the type_name is an absolute reference.
146
+ ActiveSupport::Dependencies.constantize(type_name)
147
+ else
148
+ type_candidate = @_type_candidates_cache[type_name]
149
+ if type_candidate && type_constant = ActiveSupport::Dependencies.safe_constantize(type_candidate)
150
+ return type_constant
151
+ end
152
+
153
+ # Build a list of candidates to search for
154
+ candidates = []
155
+ name.scan(/::|$/) { candidates.unshift "#{$`}::#{type_name}" }
156
+ candidates << type_name
157
+
158
+ candidates.each do |candidate|
159
+ constant = ActiveSupport::Dependencies.safe_constantize(candidate)
160
+ if candidate == constant.to_s
161
+ @_type_candidates_cache[type_name] = candidate
162
+ return constant
163
+ end
164
+ end
165
+
166
+ raise NameError.new("uninitialized constant #{candidates.first}", candidates.first)
150
167
  end
151
-
152
- raise NameError.new("uninitialized constant #{candidates.first}", candidates.first)
153
168
  end
154
- end
155
169
 
156
170
  private
157
171
 
158
- # Called by +instantiate+ to decide which class to use for a new
159
- # record instance. For single-table inheritance, we check the record
160
- # for a +type+ column and return the corresponding class.
161
- def discriminate_class_for_record(record)
162
- if using_single_table_inheritance?(record)
163
- find_sti_class(record[inheritance_column])
164
- else
165
- super
172
+ # Called by +instantiate+ to decide which class to use for a new
173
+ # record instance. For single-table inheritance, we check the record
174
+ # for a +type+ column and return the corresponding class.
175
+ def discriminate_class_for_record(record)
176
+ if using_single_table_inheritance?(record)
177
+ find_sti_class(record[inheritance_column])
178
+ else
179
+ super
180
+ end
166
181
  end
167
- end
168
182
 
169
- def using_single_table_inheritance?(record)
170
- record[inheritance_column].present? && has_attribute?(inheritance_column)
171
- end
183
+ def using_single_table_inheritance?(record)
184
+ record[inheritance_column].present? && has_attribute?(inheritance_column)
185
+ end
172
186
 
173
- def find_sti_class(type_name)
174
- type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
175
- subclass = begin
176
- if store_full_sti_class
177
- ActiveSupport::Dependencies.constantize(type_name)
178
- else
179
- compute_type(type_name)
187
+ def find_sti_class(type_name)
188
+ type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
189
+ subclass = begin
190
+ if store_full_sti_class
191
+ ActiveSupport::Dependencies.constantize(type_name)
192
+ else
193
+ compute_type(type_name)
194
+ end
195
+ rescue NameError
196
+ raise SubclassNotFound,
197
+ "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
198
+ "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
199
+ "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
200
+ "or overwrite #{name}.inheritance_column to use another column for that information."
180
201
  end
181
- rescue NameError
182
- raise SubclassNotFound,
183
- "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
184
- "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
185
- "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
186
- "or overwrite #{name}.inheritance_column to use another column for that information."
187
- end
188
- unless subclass == self || descendants.include?(subclass)
189
- raise SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}"
202
+ unless subclass == self || descendants.include?(subclass)
203
+ raise SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}"
204
+ end
205
+ subclass
190
206
  end
191
- subclass
192
- end
193
207
 
194
- def type_condition(table = arel_table)
195
- sti_column = arel_attribute(inheritance_column, table)
196
- sti_names = ([self] + descendants).map(&:sti_name)
208
+ def type_condition(table = arel_table)
209
+ sti_column = arel_attribute(inheritance_column, table)
210
+ sti_names = ([self] + descendants).map(&:sti_name)
197
211
 
198
- sti_column.in(sti_names)
199
- end
212
+ sti_column.in(sti_names)
213
+ end
200
214
 
201
- # Detect the subclass from the inheritance column of attrs. If the inheritance column value
202
- # is not self or a valid subclass, raises ActiveRecord::SubclassNotFound
203
- def subclass_from_attributes(attrs)
204
- attrs = attrs.to_h if attrs.respond_to?(:permitted?)
205
- if attrs.is_a?(Hash)
206
- subclass_name = attrs.with_indifferent_access[inheritance_column]
215
+ # Detect the subclass from the inheritance column of attrs. If the inheritance column value
216
+ # is not self or a valid subclass, raises ActiveRecord::SubclassNotFound
217
+ def subclass_from_attributes(attrs)
218
+ attrs = attrs.to_h if attrs.respond_to?(:permitted?)
219
+ if attrs.is_a?(Hash)
220
+ subclass_name = attrs.with_indifferent_access[inheritance_column]
207
221
 
208
- if subclass_name.present?
209
- find_sti_class(subclass_name)
222
+ if subclass_name.present?
223
+ find_sti_class(subclass_name)
224
+ end
210
225
  end
211
226
  end
212
- end
213
227
  end
214
228
 
215
229
  def initialize_dup(other)
@@ -219,21 +233,21 @@ module ActiveRecord
219
233
 
220
234
  private
221
235
 
222
- def initialize_internals_callback
223
- super
224
- ensure_proper_type
225
- end
236
+ def initialize_internals_callback
237
+ super
238
+ ensure_proper_type
239
+ end
226
240
 
227
- # Sets the attribute used for single table inheritance to this class name if this is not the
228
- # ActiveRecord::Base descendant.
229
- # Considering the hierarchy Reply < Message < ActiveRecord::Base, this makes it possible to
230
- # do Reply.new without having to set <tt>Reply[Reply.inheritance_column] = "Reply"</tt> yourself.
231
- # No such attribute would be set for objects of the Message class in that example.
232
- def ensure_proper_type
233
- klass = self.class
234
- if klass.finder_needs_type_condition?
235
- write_attribute(klass.inheritance_column, klass.sti_name)
241
+ # Sets the attribute used for single table inheritance to this class name if this is not the
242
+ # ActiveRecord::Base descendant.
243
+ # Considering the hierarchy Reply < Message < ActiveRecord::Base, this makes it possible to
244
+ # do Reply.new without having to set <tt>Reply[Reply.inheritance_column] = "Reply"</tt> yourself.
245
+ # No such attribute would be set for objects of the Message class in that example.
246
+ def ensure_proper_type
247
+ klass = self.class
248
+ if klass.finder_needs_type_condition?
249
+ write_attribute(klass.inheritance_column, klass.sti_name)
250
+ end
236
251
  end
237
- end
238
252
  end
239
253
  end