activerecord 4.2.0 → 5.2.8.1

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 (274) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +640 -928
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -11
  5. data/examples/performance.rb +32 -31
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +264 -247
  8. data/lib/active_record/association_relation.rb +24 -6
  9. data/lib/active_record/associations/alias_tracker.rb +29 -35
  10. data/lib/active_record/associations/association.rb +87 -41
  11. data/lib/active_record/associations/association_scope.rb +106 -132
  12. data/lib/active_record/associations/belongs_to_association.rb +55 -36
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +29 -38
  15. data/lib/active_record/associations/builder/belongs_to.rb +77 -30
  16. data/lib/active_record/associations/builder/collection_association.rb +14 -23
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +50 -39
  18. data/lib/active_record/associations/builder/has_many.rb +6 -4
  19. data/lib/active_record/associations/builder/has_one.rb +13 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +15 -11
  21. data/lib/active_record/associations/collection_association.rb +145 -266
  22. data/lib/active_record/associations/collection_proxy.rb +242 -138
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +35 -75
  25. data/lib/active_record/associations/has_many_through_association.rb +51 -69
  26. data/lib/active_record/associations/has_one_association.rb +39 -24
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +40 -81
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +134 -154
  32. data/lib/active_record/associations/preloader/association.rb +85 -116
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -74
  34. data/lib/active_record/associations/preloader.rb +83 -93
  35. data/lib/active_record/associations/singular_association.rb +27 -40
  36. data/lib/active_record/associations/through_association.rb +48 -23
  37. data/lib/active_record/associations.rb +1732 -1596
  38. data/lib/active_record/attribute_assignment.rb +58 -182
  39. data/lib/active_record/attribute_decorators.rb +39 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -5
  41. data/lib/active_record/attribute_methods/dirty.rb +94 -125
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -71
  43. data/lib/active_record/attribute_methods/query.rb +4 -2
  44. data/lib/active_record/attribute_methods/read.rb +45 -63
  45. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +62 -36
  47. data/lib/active_record/attribute_methods/write.rb +31 -46
  48. data/lib/active_record/attribute_methods.rb +170 -117
  49. data/lib/active_record/attributes.rb +201 -74
  50. data/lib/active_record/autosave_association.rb +118 -45
  51. data/lib/active_record/base.rb +60 -48
  52. data/lib/active_record/callbacks.rb +97 -57
  53. data/lib/active_record/coders/json.rb +3 -1
  54. data/lib/active_record/coders/yaml_column.rb +37 -13
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -284
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +254 -87
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +72 -22
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -52
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -217
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +617 -212
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +139 -75
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +332 -191
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +567 -563
  69. data/lib/active_record/connection_adapters/column.rb +50 -41
  70. data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +42 -195
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -115
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +7 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  99. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +65 -51
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +466 -280
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +439 -330
  117. data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -324
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +40 -27
  128. data/lib/active_record/core.rb +205 -202
  129. data/lib/active_record/counter_cache.rb +80 -37
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +87 -105
  132. data/lib/active_record/enum.rb +136 -90
  133. data/lib/active_record/errors.rb +180 -52
  134. data/lib/active_record/explain.rb +23 -11
  135. data/lib/active_record/explain_registry.rb +4 -2
  136. data/lib/active_record/explain_subscriber.rb +11 -6
  137. data/lib/active_record/fixture_set/file.rb +35 -9
  138. data/lib/active_record/fixtures.rb +193 -135
  139. data/lib/active_record/gem_version.rb +5 -3
  140. data/lib/active_record/inheritance.rb +148 -112
  141. data/lib/active_record/integration.rb +70 -28
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  144. data/lib/active_record/locale/en.yml +3 -2
  145. data/lib/active_record/locking/optimistic.rb +92 -98
  146. data/lib/active_record/locking/pessimistic.rb +15 -3
  147. data/lib/active_record/log_subscriber.rb +95 -33
  148. data/lib/active_record/migration/command_recorder.rb +133 -90
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +8 -6
  151. data/lib/active_record/migration.rb +594 -267
  152. data/lib/active_record/model_schema.rb +292 -111
  153. data/lib/active_record/nested_attributes.rb +266 -214
  154. data/lib/active_record/no_touching.rb +8 -2
  155. data/lib/active_record/null_relation.rb +24 -37
  156. data/lib/active_record/persistence.rb +350 -119
  157. data/lib/active_record/query_cache.rb +13 -24
  158. data/lib/active_record/querying.rb +19 -17
  159. data/lib/active_record/railtie.rb +117 -35
  160. data/lib/active_record/railties/console_sandbox.rb +2 -0
  161. data/lib/active_record/railties/controller_runtime.rb +9 -3
  162. data/lib/active_record/railties/databases.rake +160 -174
  163. data/lib/active_record/readonly_attributes.rb +5 -4
  164. data/lib/active_record/reflection.rb +447 -288
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +204 -55
  167. data/lib/active_record/relation/calculations.rb +259 -244
  168. data/lib/active_record/relation/delegation.rb +67 -60
  169. data/lib/active_record/relation/finder_methods.rb +290 -253
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +91 -68
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -23
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  179. data/lib/active_record/relation/predicate_builder.rb +118 -92
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +446 -389
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +18 -16
  184. data/lib/active_record/relation/where_clause.rb +186 -0
  185. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  186. data/lib/active_record/relation.rb +287 -339
  187. data/lib/active_record/result.rb +54 -36
  188. data/lib/active_record/runtime_registry.rb +6 -4
  189. data/lib/active_record/sanitization.rb +155 -124
  190. data/lib/active_record/schema.rb +30 -24
  191. data/lib/active_record/schema_dumper.rb +91 -87
  192. data/lib/active_record/schema_migration.rb +19 -19
  193. data/lib/active_record/scoping/default.rb +102 -84
  194. data/lib/active_record/scoping/named.rb +81 -32
  195. data/lib/active_record/scoping.rb +45 -26
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +5 -5
  198. data/lib/active_record/statement_cache.rb +45 -35
  199. data/lib/active_record/store.rb +42 -36
  200. data/lib/active_record/suppressor.rb +61 -0
  201. data/lib/active_record/table_metadata.rb +82 -0
  202. data/lib/active_record/tasks/database_tasks.rb +136 -95
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +59 -89
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -31
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
  206. data/lib/active_record/timestamp.rb +70 -38
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +208 -123
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  211. data/lib/active_record/type/date.rb +4 -41
  212. data/lib/active_record/type/date_time.rb +4 -38
  213. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  214. data/lib/active_record/type/hash_lookup_type_map.rb +13 -5
  215. data/lib/active_record/type/internal/timezone.rb +17 -0
  216. data/lib/active_record/type/json.rb +30 -0
  217. data/lib/active_record/type/serialized.rb +30 -15
  218. data/lib/active_record/type/text.rb +2 -2
  219. data/lib/active_record/type/time.rb +11 -16
  220. data/lib/active_record/type/type_map.rb +15 -17
  221. data/lib/active_record/type/unsigned_integer.rb +9 -7
  222. data/lib/active_record/type.rb +79 -23
  223. data/lib/active_record/type_caster/connection.rb +33 -0
  224. data/lib/active_record/type_caster/map.rb +23 -0
  225. data/lib/active_record/type_caster.rb +9 -0
  226. data/lib/active_record/validations/absence.rb +25 -0
  227. data/lib/active_record/validations/associated.rb +13 -4
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +14 -13
  230. data/lib/active_record/validations/uniqueness.rb +41 -32
  231. data/lib/active_record/validations.rb +38 -35
  232. data/lib/active_record/version.rb +3 -1
  233. data/lib/active_record.rb +36 -21
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  236. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
  237. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -6
  238. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -7
  239. data/lib/rails/generators/active_record/migration.rb +18 -1
  240. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  241. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
  242. data/lib/rails/generators/active_record.rb +7 -5
  243. metadata +77 -53
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  251. data/lib/active_record/attribute.rb +0 -149
  252. data/lib/active_record/attribute_set/builder.rb +0 -86
  253. data/lib/active_record/attribute_set.rb +0 -77
  254. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  255. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  256. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  257. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  258. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  259. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  260. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  261. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  262. data/lib/active_record/type/big_integer.rb +0 -13
  263. data/lib/active_record/type/binary.rb +0 -50
  264. data/lib/active_record/type/boolean.rb +0 -30
  265. data/lib/active_record/type/decimal.rb +0 -40
  266. data/lib/active_record/type/decorator.rb +0 -14
  267. data/lib/active_record/type/float.rb +0 -19
  268. data/lib/active_record/type/integer.rb +0 -55
  269. data/lib/active_record/type/mutable.rb +0 -16
  270. data/lib/active_record/type/numeric.rb +0 -36
  271. data/lib/active_record/type/string.rb +0 -36
  272. data/lib/active_record/type/time_value.rb +0 -38
  273. data/lib/active_record/type/value.rb +0 -101
  274. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,10 +1,13 @@
1
- require 'erb'
2
- require 'yaml'
3
- require 'zlib'
4
- require 'active_support/dependencies'
5
- require 'active_support/core_ext/digest/uuid'
6
- require 'active_record/fixture_set/file'
7
- require 'active_record/errors'
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+ require "yaml"
5
+ require "zlib"
6
+ require "set"
7
+ require "active_support/dependencies"
8
+ require "active_support/core_ext/digest/uuid"
9
+ require "active_record/fixture_set/file"
10
+ require "active_record/errors"
8
11
 
9
12
  module ActiveRecord
10
13
  class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
@@ -65,17 +68,36 @@ module ActiveRecord
65
68
  # By default, +test_helper.rb+ will load all of your fixtures into your test
66
69
  # database, so this test will succeed.
67
70
  #
68
- # The testing environment will automatically load the all fixtures into the database before each
71
+ # The testing environment will automatically load all the fixtures into the database before each
69
72
  # test. To ensure consistent data, the environment deletes the fixtures before running the load.
70
73
  #
71
74
  # In addition to being available in the database, the fixture's data may also be accessed by
72
- # using a special dynamic method, which has the same name as the model, and accepts the
73
- # name of the fixture to instantiate:
75
+ # using a special dynamic method, which has the same name as the model.
76
+ #
77
+ # Passing in a fixture name to this dynamic method returns the fixture matching this name:
74
78
  #
75
- # test "find" do
79
+ # test "find one" do
76
80
  # assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
77
81
  # end
78
82
  #
83
+ # Passing in multiple fixture names returns all fixtures matching these names:
84
+ #
85
+ # test "find all by name" do
86
+ # assert_equal 2, web_sites(:rubyonrails, :google).length
87
+ # end
88
+ #
89
+ # Passing in no arguments returns all fixtures:
90
+ #
91
+ # test "find all" do
92
+ # assert_equal 2, web_sites.length
93
+ # end
94
+ #
95
+ # Passing in any fixture name that does not exist will raise <tt>StandardError</tt>:
96
+ #
97
+ # test "find by name that does not exist" do
98
+ # assert_raise(StandardError) { web_sites(:reddit) }
99
+ # end
100
+ #
79
101
  # Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the
80
102
  # following tests:
81
103
  #
@@ -87,8 +109,8 @@ module ActiveRecord
87
109
  # assert_equal "Ruby on Rails", @rubyonrails.name
88
110
  # end
89
111
  #
90
- # In order to use these methods to access fixtured data within your testcases, you must specify one of the
91
- # following in your <tt>ActiveSupport::TestCase</tt>-derived class:
112
+ # In order to use these methods to access fixtured data within your test cases, you must specify one of the
113
+ # following in your ActiveSupport::TestCase-derived class:
92
114
  #
93
115
  # - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
94
116
  # self.use_instantiated_fixtures = true
@@ -102,14 +124,14 @@ module ActiveRecord
102
124
  #
103
125
  # = Dynamic fixtures with ERB
104
126
  #
105
- # Some times you don't care about the content of the fixtures as much as you care about the volume.
127
+ # Sometimes you don't care about the content of the fixtures as much as you care about the volume.
106
128
  # In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
107
129
  # testing, like:
108
130
  #
109
131
  # <% 1.upto(1000) do |i| %>
110
132
  # fix_<%= i %>:
111
133
  # id: <%= i %>
112
- # name: guy_<%= 1 %>
134
+ # name: guy_<%= i %>
113
135
  # <% end %>
114
136
  #
115
137
  # This will create 1000 very simple fixtures.
@@ -123,49 +145,49 @@ module ActiveRecord
123
145
  #
124
146
  # Helper methods defined in a fixture will not be available in other fixtures, to prevent against
125
147
  # unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module
126
- # that is included in <tt>ActiveRecord::FixtureSet.context_class</tt>.
148
+ # that is included in ActiveRecord::FixtureSet.context_class.
127
149
  #
128
- # - define a helper method in `test_helper.rb`
150
+ # - define a helper method in <tt>test_helper.rb</tt>
129
151
  # module FixtureFileHelpers
130
152
  # def file_sha(path)
131
153
  # Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
132
154
  # end
133
155
  # end
134
- # ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers
156
+ # ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
135
157
  #
136
158
  # - use the helper method in a fixture
137
159
  # photo:
138
160
  # name: kitten.png
139
161
  # sha: <%= file_sha 'files/kitten.png' %>
140
162
  #
141
- # = Transactional Fixtures
163
+ # = Transactional Tests
142
164
  #
143
165
  # Test cases can use begin+rollback to isolate their changes to the database instead of having to
144
166
  # delete+insert for every test case.
145
167
  #
146
168
  # class FooTest < ActiveSupport::TestCase
147
- # self.use_transactional_fixtures = true
169
+ # self.use_transactional_tests = true
148
170
  #
149
171
  # test "godzilla" do
150
- # assert !Foo.all.empty?
172
+ # assert_not_empty Foo.all
151
173
  # Foo.destroy_all
152
- # assert Foo.all.empty?
174
+ # assert_empty Foo.all
153
175
  # end
154
176
  #
155
177
  # test "godzilla aftermath" do
156
- # assert !Foo.all.empty?
178
+ # assert_not_empty Foo.all
157
179
  # end
158
180
  # end
159
181
  #
160
182
  # If you preload your test database with all fixture data (probably in the rake task) and use
161
- # transactional fixtures, then you may omit all fixtures declarations in your test cases since
183
+ # transactional tests, then you may omit all fixtures declarations in your test cases since
162
184
  # all the data's already there and every case rolls back its changes.
163
185
  #
164
186
  # In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to
165
187
  # true. This will provide access to fixture data for every table that has been loaded through
166
188
  # fixtures (depending on the value of +use_instantiated_fixtures+).
167
189
  #
168
- # When *not* to use transactional fixtures:
190
+ # When *not* to use transactional tests:
169
191
  #
170
192
  # 1. You're testing whether a transaction works correctly. Nested transactions don't commit until
171
193
  # all parent transactions commit, particularly, the fixtures transaction which is begun in setup
@@ -394,15 +416,29 @@ module ActiveRecord
394
416
  # <<: *DEFAULTS
395
417
  #
396
418
  # Any fixture labeled "DEFAULTS" is safely ignored.
419
+ #
420
+ # == Configure the fixture model class
421
+ #
422
+ # It's possible to set the fixture's model class directly in the YAML file.
423
+ # This is helpful when fixtures are loaded outside tests and
424
+ # +set_fixture_class+ is not available (e.g.
425
+ # when running <tt>rails db:fixtures:load</tt>).
426
+ #
427
+ # _fixture:
428
+ # model_class: User
429
+ # david:
430
+ # name: David
431
+ #
432
+ # Any fixtures labeled "_fixture" are safely ignored.
397
433
  class FixtureSet
398
434
  #--
399
435
  # An instance of FixtureSet is normally stored in a single YAML file and
400
436
  # possibly in a folder with the same name.
401
437
  #++
402
438
 
403
- MAX_ID = 2 ** 30 - 1
439
+ MAX_ID = 2**30 - 1
404
440
 
405
- @@all_cached_fixtures = Hash.new { |h,k| h[k] = {} }
441
+ @@all_cached_fixtures = Hash.new { |h, k| h[k] = {} }
406
442
 
407
443
  def self.default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
408
444
  config.pluralize_table_names ?
@@ -411,9 +447,9 @@ module ActiveRecord
411
447
  end
412
448
 
413
449
  def self.default_fixture_table_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
414
- "#{ config.table_name_prefix }"\
415
- "#{ fixture_set_name.tr('/', '_') }"\
416
- "#{ config.table_name_suffix }".to_sym
450
+ "#{ config.table_name_prefix }"\
451
+ "#{ fixture_set_name.tr('/', '_') }"\
452
+ "#{ config.table_name_suffix }".to_sym
417
453
  end
418
454
 
419
455
  def self.reset_cache
@@ -458,8 +494,7 @@ module ActiveRecord
458
494
  end
459
495
  end
460
496
 
461
- cattr_accessor :all_loaded_fixtures
462
- self.all_loaded_fixtures = {}
497
+ cattr_accessor :all_loaded_fixtures, default: {}
463
498
 
464
499
  class ClassCache
465
500
  def initialize(class_names, config)
@@ -479,18 +514,18 @@ module ActiveRecord
479
514
 
480
515
  private
481
516
 
482
- def insert_class(class_names, name, klass)
483
- # We only want to deal with AR objects.
484
- if klass && klass < ActiveRecord::Base
485
- class_names[name] = klass
486
- else
487
- class_names[name] = nil
517
+ def insert_class(class_names, name, klass)
518
+ # We only want to deal with AR objects.
519
+ if klass && klass < ActiveRecord::Base
520
+ class_names[name] = klass
521
+ else
522
+ class_names[name] = nil
523
+ end
488
524
  end
489
- end
490
525
 
491
- def default_fixture_model(fs_name, config)
492
- ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
493
- end
526
+ def default_fixture_model(fs_name, config)
527
+ ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
528
+ end
494
529
  end
495
530
 
496
531
  def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
@@ -505,47 +540,38 @@ module ActiveRecord
505
540
  }
506
541
 
507
542
  unless files_to_read.empty?
508
- connection.disable_referential_integrity do
509
- fixtures_map = {}
510
-
511
- fixture_sets = files_to_read.map do |fs_name|
512
- klass = class_names[fs_name]
513
- conn = klass ? klass.connection : connection
514
- fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
515
- conn,
516
- fs_name,
517
- klass,
518
- ::File.join(fixtures_directory, fs_name))
519
- end
520
-
521
- update_all_loaded_fixtures fixtures_map
543
+ fixtures_map = {}
544
+
545
+ fixture_sets = files_to_read.map do |fs_name|
546
+ klass = class_names[fs_name]
547
+ conn = klass ? klass.connection : connection
548
+ fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
549
+ conn,
550
+ fs_name,
551
+ klass,
552
+ ::File.join(fixtures_directory, fs_name))
553
+ end
522
554
 
523
- connection.transaction(:requires_new => true) do
524
- fixture_sets.each do |fs|
525
- conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
526
- table_rows = fs.table_rows
555
+ update_all_loaded_fixtures fixtures_map
556
+ fixture_sets_by_connection = fixture_sets.group_by { |fs| fs.model_class ? fs.model_class.connection : connection }
527
557
 
528
- table_rows.each_key do |table|
529
- conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
530
- end
558
+ fixture_sets_by_connection.each do |conn, set|
559
+ table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
531
560
 
532
- table_rows.each do |fixture_set_name, rows|
533
- rows.each do |row|
534
- conn.insert_fixture(row, fixture_set_name)
535
- end
536
- end
537
- end
538
-
539
- # Cap primary key sequences to max(pk).
540
- if connection.respond_to?(:reset_pk_sequence!)
541
- fixture_sets.each do |fs|
542
- connection.reset_pk_sequence!(fs.table_name)
543
- end
561
+ set.each do |fs|
562
+ fs.table_rows.each do |table, rows|
563
+ table_rows_for_connection[table].unshift(*rows)
544
564
  end
545
565
  end
566
+ conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
546
567
 
547
- cache_fixtures(connection, fixtures_map)
568
+ # Cap primary key sequences to max(pk).
569
+ if conn.respond_to?(:reset_pk_sequence!)
570
+ set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
571
+ end
548
572
  end
573
+
574
+ cache_fixtures(connection, fixtures_map)
549
575
  end
550
576
  cached_fixtures(connection, fixture_set_names)
551
577
  end
@@ -575,28 +601,23 @@ module ActiveRecord
575
601
  @name = name
576
602
  @path = path
577
603
  @config = config
578
- @model_class = nil
579
604
 
580
- if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
581
- @model_class = class_name
582
- else
583
- @model_class = class_name.safe_constantize if class_name
584
- end
605
+ self.model_class = class_name
585
606
 
586
- @connection = connection
607
+ @fixtures = read_fixture_files(path)
587
608
 
588
- @table_name = ( model_class.respond_to?(:table_name) ?
589
- model_class.table_name :
590
- self.class.default_fixture_table_name(name, config) )
609
+ @connection = connection
591
610
 
592
- @fixtures = read_fixture_files path, @model_class
611
+ @table_name = (model_class.respond_to?(:table_name) ?
612
+ model_class.table_name :
613
+ self.class.default_fixture_table_name(name, config))
593
614
  end
594
615
 
595
616
  def [](x)
596
617
  fixtures[x]
597
618
  end
598
619
 
599
- def []=(k,v)
620
+ def []=(k, v)
600
621
  fixtures[k] = v
601
622
  end
602
623
 
@@ -612,13 +633,12 @@ module ActiveRecord
612
633
  # a list of rows to insert to that table.
613
634
  def table_rows
614
635
  now = config.default_timezone == :utc ? Time.now.utc : Time.now
615
- now = now.to_s(:db)
616
636
 
617
637
  # allow a standard key to be used for doing defaults in YAML
618
- fixtures.delete('DEFAULTS')
638
+ fixtures.delete("DEFAULTS")
619
639
 
620
640
  # track any join tables we need to insert later
621
- rows = Hash.new { |h,table| h[table] = [] }
641
+ rows = Hash.new { |h, table| h[table] = [] }
622
642
 
623
643
  rows[table_name] = fixtures.map do |label, fixture|
624
644
  row = fixture.to_hash
@@ -633,7 +653,7 @@ module ActiveRecord
633
653
 
634
654
  # interpolate the fixture label
635
655
  row.each do |key, value|
636
- row[key] = value.gsub("$LABEL", label) if value.is_a?(String)
656
+ row[key] = value.gsub("$LABEL", label.to_s) if value.is_a?(String)
637
657
  end
638
658
 
639
659
  # generate a primary key if necessary
@@ -641,6 +661,13 @@ module ActiveRecord
641
661
  row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
642
662
  end
643
663
 
664
+ # Resolve enums
665
+ model_class.defined_enums.each do |name, values|
666
+ if row.include?(name)
667
+ row[name] = values.fetch(row[name], row[name])
668
+ end
669
+ end
670
+
644
671
  # If STI is used, find the correct subclass for association reflection
645
672
  reflection_class =
646
673
  if row.include?(inheritance_column_name)
@@ -661,7 +688,7 @@ module ActiveRecord
661
688
  row[association.foreign_type] = $1
662
689
  end
663
690
 
664
- fk_type = association.active_record.columns_hash[fk_name].type
691
+ fk_type = reflection_class.type_for_attribute(fk_name).type
665
692
  row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
666
693
  end
667
694
  when :has_many
@@ -691,7 +718,7 @@ module ActiveRecord
691
718
  end
692
719
 
693
720
  def primary_key_type
694
- @association.klass.column_types[@association.klass.primary_key].type
721
+ @association.klass.type_for_attribute(@association.klass.primary_key).type
695
722
  end
696
723
  end
697
724
 
@@ -703,6 +730,10 @@ module ActiveRecord
703
730
  def lhs_key
704
731
  @association.through_reflection.foreign_key
705
732
  end
733
+
734
+ def join_table
735
+ @association.through_reflection.table_name
736
+ end
706
737
  end
707
738
 
708
739
  private
@@ -711,7 +742,7 @@ module ActiveRecord
711
742
  end
712
743
 
713
744
  def primary_key_type
714
- @primary_key_type ||= model_class && model_class.column_types[model_class.primary_key].type
745
+ @primary_key_type ||= model_class && model_class.type_for_attribute(model_class.primary_key).type
715
746
  end
716
747
 
717
748
  def add_join_records(rows, row, association)
@@ -745,16 +776,28 @@ module ActiveRecord
745
776
  end
746
777
 
747
778
  def column_names
748
- @column_names ||= @connection.columns(@table_name).collect { |c| c.name }
779
+ @column_names ||= @connection.columns(@table_name).collect(&:name)
749
780
  end
750
781
 
751
- def read_fixture_files(path, model_class)
782
+ def model_class=(class_name)
783
+ if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
784
+ @model_class = class_name
785
+ else
786
+ @model_class = class_name.safe_constantize if class_name
787
+ end
788
+ end
789
+
790
+ # Loads the fixtures from the YAML file at +path+.
791
+ # If the file sets the +model_class+ and current instance value is not set,
792
+ # it uses the file value.
793
+ def read_fixture_files(path)
752
794
  yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
753
795
  ::File.file?(f)
754
796
  } + [yaml_file_path(path)]
755
797
 
756
798
  yaml_files.each_with_object({}) do |file, fixtures|
757
799
  FixtureSet::File.open(file) do |fh|
800
+ self.model_class ||= fh.model_class if fh.model_class
758
801
  fh.each do |fixture_name, row|
759
802
  fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
760
803
  end
@@ -765,15 +808,8 @@ module ActiveRecord
765
808
  def yaml_file_path(path)
766
809
  "#{path}.yml"
767
810
  end
768
-
769
811
  end
770
812
 
771
- #--
772
- # Deprecate 'Fixtures' in favor of 'FixtureSet'.
773
- #++
774
- # :nodoc:
775
- Fixtures = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveRecord::Fixtures', 'ActiveRecord::FixtureSet')
776
-
777
813
  class Fixture #:nodoc:
778
814
  include Enumerable
779
815
 
@@ -820,34 +856,24 @@ module ActiveRecord
820
856
  module TestFixtures
821
857
  extend ActiveSupport::Concern
822
858
 
823
- def before_setup
859
+ def before_setup # :nodoc:
824
860
  setup_fixtures
825
861
  super
826
862
  end
827
863
 
828
- def after_teardown
864
+ def after_teardown # :nodoc:
829
865
  super
830
866
  teardown_fixtures
831
867
  end
832
868
 
833
869
  included do
834
- class_attribute :fixture_path, :instance_writer => false
835
- class_attribute :fixture_table_names
836
- class_attribute :fixture_class_names
837
- class_attribute :use_transactional_fixtures
838
- class_attribute :use_instantiated_fixtures # true, false, or :no_instances
839
- class_attribute :pre_loaded_fixtures
840
- class_attribute :config
841
-
842
- self.fixture_table_names = []
843
- self.use_transactional_fixtures = true
844
- self.use_instantiated_fixtures = false
845
- self.pre_loaded_fixtures = false
846
- self.config = ActiveRecord::Base
847
-
848
- self.fixture_class_names = Hash.new do |h, fixture_set_name|
849
- h[fixture_set_name] = ActiveRecord::FixtureSet.default_fixture_model_name(fixture_set_name, self.config)
850
- end
870
+ class_attribute :fixture_path, instance_writer: false
871
+ class_attribute :fixture_table_names, default: []
872
+ class_attribute :fixture_class_names, default: {}
873
+ class_attribute :use_transactional_tests, default: true
874
+ class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
875
+ class_attribute :pre_loaded_fixtures, default: false
876
+ class_attribute :config, default: ActiveRecord::Base
851
877
  end
852
878
 
853
879
  module ClassMethods
@@ -860,15 +886,15 @@ module ActiveRecord
860
886
  #
861
887
  # The keys must be the fixture names, that coincide with the short paths to the fixture files.
862
888
  def set_fixture_class(class_names = {})
863
- self.fixture_class_names = self.fixture_class_names.merge(class_names.stringify_keys)
889
+ self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
864
890
  end
865
891
 
866
892
  def fixtures(*fixture_set_names)
867
893
  if fixture_set_names.first == :all
868
- fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
894
+ fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"].uniq
869
895
  fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
870
896
  else
871
- fixture_set_names = fixture_set_names.flatten.map { |n| n.to_s }
897
+ fixture_set_names = fixture_set_names.flatten.map(&:to_s)
872
898
  end
873
899
 
874
900
  self.fixture_table_names |= fixture_set_names
@@ -880,15 +906,17 @@ module ActiveRecord
880
906
  methods = Module.new do
881
907
  fixture_set_names.each do |fs_name|
882
908
  fs_name = fs_name.to_s
883
- accessor_name = fs_name.tr('/', '_').to_sym
909
+ accessor_name = fs_name.tr("/", "_").to_sym
884
910
 
885
911
  define_method(accessor_name) do |*fixture_names|
886
912
  force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
913
+ return_single_record = fixture_names.size == 1
914
+ fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
887
915
 
888
916
  @fixture_cache[fs_name] ||= {}
889
917
 
890
918
  instances = fixture_names.map do |f_name|
891
- f_name = f_name.to_s
919
+ f_name = f_name.to_s if f_name.is_a?(Symbol)
892
920
  @fixture_cache[fs_name].delete(f_name) if force_reload
893
921
 
894
922
  if @loaded_fixtures[fs_name][f_name]
@@ -898,7 +926,7 @@ module ActiveRecord
898
926
  end
899
927
  end
900
928
 
901
- instances.size == 1 ? instances.first : instances
929
+ return_single_record ? instances.first : instances
902
930
  end
903
931
  private accessor_name
904
932
  end
@@ -908,7 +936,7 @@ module ActiveRecord
908
936
 
909
937
  def uses_transaction(*methods)
910
938
  @uses_transaction = [] unless defined?(@uses_transaction)
911
- @uses_transaction.concat methods.map { |m| m.to_s }
939
+ @uses_transaction.concat methods.map(&:to_s)
912
940
  end
913
941
 
914
942
  def uses_transaction?(method)
@@ -918,18 +946,19 @@ module ActiveRecord
918
946
  end
919
947
 
920
948
  def run_in_transaction?
921
- use_transactional_fixtures &&
949
+ use_transactional_tests &&
922
950
  !self.class.uses_transaction?(method_name)
923
951
  end
924
952
 
925
953
  def setup_fixtures(config = ActiveRecord::Base)
926
- if pre_loaded_fixtures && !use_transactional_fixtures
927
- raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
954
+ if pre_loaded_fixtures && !use_transactional_tests
955
+ raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
928
956
  end
929
957
 
930
958
  @fixture_cache = {}
931
959
  @fixture_connections = []
932
960
  @@already_loaded_fixtures ||= {}
961
+ @connection_subscriber = nil
933
962
 
934
963
  # Load fixtures once and begin transaction.
935
964
  if run_in_transaction?
@@ -939,10 +968,33 @@ module ActiveRecord
939
968
  @loaded_fixtures = load_fixtures(config)
940
969
  @@already_loaded_fixtures[self.class] = @loaded_fixtures
941
970
  end
971
+
972
+ # Begin transactions for connections already established
942
973
  @fixture_connections = enlist_fixture_connections
943
974
  @fixture_connections.each do |connection|
944
975
  connection.begin_transaction joinable: false
976
+ connection.pool.lock_thread = true
945
977
  end
978
+
979
+ # When connections are established in the future, begin a transaction too
980
+ @connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
981
+ spec_name = payload[:spec_name] if payload.key?(:spec_name)
982
+
983
+ if spec_name
984
+ begin
985
+ connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name)
986
+ rescue ConnectionNotEstablished
987
+ connection = nil
988
+ end
989
+
990
+ if connection && !@fixture_connections.include?(connection)
991
+ connection.begin_transaction joinable: false
992
+ connection.pool.lock_thread = true
993
+ @fixture_connections << connection
994
+ end
995
+ end
996
+ end
997
+
946
998
  # Load fixtures for every test.
947
999
  else
948
1000
  ActiveRecord::FixtureSet.reset_cache
@@ -957,8 +1009,10 @@ module ActiveRecord
957
1009
  def teardown_fixtures
958
1010
  # Rollback changes if a transaction is active.
959
1011
  if run_in_transaction?
1012
+ ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
960
1013
  @fixture_connections.each do |connection|
961
1014
  connection.rollback_transaction if connection.transaction_open?
1015
+ connection.pool.lock_thread = false
962
1016
  end
963
1017
  @fixture_connections.clear
964
1018
  else
@@ -980,10 +1034,10 @@ module ActiveRecord
980
1034
 
981
1035
  def instantiate_fixtures
982
1036
  if pre_loaded_fixtures
983
- raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
1037
+ raise RuntimeError, "Load fixtures before instantiating them." if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
984
1038
  ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
985
1039
  else
986
- raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
1040
+ raise RuntimeError, "Load fixtures before instantiating them." if @loaded_fixtures.nil?
987
1041
  @loaded_fixtures.each_value do |fixture_set|
988
1042
  ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
989
1043
  end
@@ -1002,6 +1056,10 @@ class ActiveRecord::FixtureSet::RenderContext # :nodoc:
1002
1056
  def get_binding
1003
1057
  binding()
1004
1058
  end
1059
+
1060
+ def binary(path)
1061
+ %(!!binary "#{Base64.strict_encode64(File.read(path))}")
1062
+ end
1005
1063
  end
1006
1064
  end
1007
1065
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # Returns the version of the currently loaded Active Record as a <tt>Gem::Version</tt>
3
5
  def self.gem_version
@@ -5,10 +7,10 @@ module ActiveRecord
5
7
  end
6
8
 
7
9
  module VERSION
8
- MAJOR = 4
10
+ MAJOR = 5
9
11
  MINOR = 2
10
- TINY = 0
11
- PRE = nil
12
+ TINY = 8
13
+ PRE = "1"
12
14
 
13
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
16
  end