activerecord 4.2.11.1 → 5.2.4.5

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 +4 -4
  2. data/CHANGELOG.md +594 -1620
  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 +263 -249
  8. data/lib/active_record/association_relation.rb +11 -6
  9. data/lib/active_record/associations/alias_tracker.rb +29 -35
  10. data/lib/active_record/associations/association.rb +77 -43
  11. data/lib/active_record/associations/association_scope.rb +106 -133
  12. data/lib/active_record/associations/belongs_to_association.rb +52 -41
  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 +9 -22
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -35
  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 +139 -280
  22. data/lib/active_record/associations/collection_proxy.rb +231 -133
  23. data/lib/active_record/associations/foreign_association.rb +3 -1
  24. data/lib/active_record/associations/has_many_association.rb +34 -89
  25. data/lib/active_record/associations/has_many_through_association.rb +49 -76
  26. data/lib/active_record/associations/has_one_association.rb +38 -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 -87
  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 +133 -159
  32. data/lib/active_record/associations/preloader/association.rb +85 -120
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -74
  34. data/lib/active_record/associations/preloader.rb +81 -91
  35. data/lib/active_record/associations/singular_association.rb +27 -34
  36. data/lib/active_record/associations/through_association.rb +38 -18
  37. data/lib/active_record/associations.rb +1732 -1597
  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 +10 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +94 -135
  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 +58 -36
  47. data/lib/active_record/attribute_methods/write.rb +30 -45
  48. data/lib/active_record/attribute_methods.rb +166 -109
  49. data/lib/active_record/attributes.rb +201 -82
  50. data/lib/active_record/autosave_association.rb +94 -36
  51. data/lib/active_record/base.rb +57 -44
  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 +24 -12
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -290
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +237 -90
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +71 -21
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +118 -52
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +318 -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 +570 -228
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +138 -70
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +325 -202
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +542 -601
  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 +41 -180
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +45 -114
  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 -58
  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 +4 -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 -22
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -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 -5
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +55 -53
  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 +462 -284
  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 +432 -323
  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 -308
  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 +178 -198
  129. data/lib/active_record/counter_cache.rb +79 -36
  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 +135 -88
  133. data/lib/active_record/errors.rb +179 -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 +10 -5
  137. data/lib/active_record/fixture_set/file.rb +35 -9
  138. data/lib/active_record/fixtures.rb +188 -132
  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 +21 -3
  144. data/lib/active_record/locale/en.yml +3 -2
  145. data/lib/active_record/locking/optimistic.rb +88 -96
  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 +581 -282
  152. data/lib/active_record/model_schema.rb +290 -111
  153. data/lib/active_record/nested_attributes.rb +264 -222
  154. data/lib/active_record/no_touching.rb +7 -1
  155. data/lib/active_record/null_relation.rb +24 -37
  156. data/lib/active_record/persistence.rb +347 -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 +94 -32
  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 +149 -156
  163. data/lib/active_record/readonly_attributes.rb +5 -4
  164. data/lib/active_record/reflection.rb +414 -267
  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 +256 -248
  168. data/lib/active_record/relation/delegation.rb +67 -60
  169. data/lib/active_record/relation/finder_methods.rb +288 -239
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +86 -86
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -24
  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 +116 -119
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +448 -393
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +11 -13
  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 -340
  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 -16
  193. data/lib/active_record/scoping/default.rb +102 -85
  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 +134 -96
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +56 -100
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +83 -41
  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 +199 -124
  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 -45
  212. data/lib/active_record/type/date_time.rb +4 -49
  213. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  214. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  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 +24 -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 +40 -41
  231. data/lib/active_record/validations.rb +38 -35
  232. data/lib/active_record/version.rb +3 -1
  233. data/lib/active_record.rb +34 -22
  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 -3
  238. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -1
  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/model/templates/{module.rb → module.rb.tt} +0 -0
  243. data/lib/rails/generators/active_record.rb +7 -5
  244. metadata +72 -49
  245. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  246. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  247. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  248. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  249. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  250. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  251. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  252. data/lib/active_record/attribute.rb +0 -163
  253. data/lib/active_record/attribute_set/builder.rb +0 -106
  254. data/lib/active_record/attribute_set.rb +0 -81
  255. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  256. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  257. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  258. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  259. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  260. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  261. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  262. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  263. data/lib/active_record/type/big_integer.rb +0 -13
  264. data/lib/active_record/type/binary.rb +0 -50
  265. data/lib/active_record/type/boolean.rb +0 -31
  266. data/lib/active_record/type/decimal.rb +0 -64
  267. data/lib/active_record/type/decorator.rb +0 -14
  268. data/lib/active_record/type/float.rb +0 -19
  269. data/lib/active_record/type/integer.rb +0 -59
  270. data/lib/active_record/type/mutable.rb +0 -16
  271. data/lib/active_record/type/numeric.rb +0 -36
  272. data/lib/active_record/type/string.rb +0 -40
  273. data/lib/active_record/type/time_value.rb +0 -38
  274. data/lib/active_record/type/value.rb +0 -110
@@ -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,45 +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
-
538
- # Cap primary key sequences to max(pk).
539
- if conn.respond_to?(:reset_pk_sequence!)
540
- conn.reset_pk_sequence!(fs.table_name)
541
- end
561
+ set.each do |fs|
562
+ fs.table_rows.each do |table, rows|
563
+ table_rows_for_connection[table].unshift(*rows)
542
564
  end
543
565
  end
566
+ conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
544
567
 
545
- 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
546
572
  end
573
+
574
+ cache_fixtures(connection, fixtures_map)
547
575
  end
548
576
  cached_fixtures(connection, fixture_set_names)
549
577
  end
@@ -573,28 +601,23 @@ module ActiveRecord
573
601
  @name = name
574
602
  @path = path
575
603
  @config = config
576
- @model_class = nil
577
604
 
578
- if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
579
- @model_class = class_name
580
- else
581
- @model_class = class_name.safe_constantize if class_name
582
- end
605
+ self.model_class = class_name
583
606
 
584
- @connection = connection
607
+ @fixtures = read_fixture_files(path)
585
608
 
586
- @table_name = ( model_class.respond_to?(:table_name) ?
587
- model_class.table_name :
588
- self.class.default_fixture_table_name(name, config) )
609
+ @connection = connection
589
610
 
590
- @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))
591
614
  end
592
615
 
593
616
  def [](x)
594
617
  fixtures[x]
595
618
  end
596
619
 
597
- def []=(k,v)
620
+ def []=(k, v)
598
621
  fixtures[k] = v
599
622
  end
600
623
 
@@ -610,13 +633,12 @@ module ActiveRecord
610
633
  # a list of rows to insert to that table.
611
634
  def table_rows
612
635
  now = config.default_timezone == :utc ? Time.now.utc : Time.now
613
- now = now.to_s(:db)
614
636
 
615
637
  # allow a standard key to be used for doing defaults in YAML
616
- fixtures.delete('DEFAULTS')
638
+ fixtures.delete("DEFAULTS")
617
639
 
618
640
  # track any join tables we need to insert later
619
- rows = Hash.new { |h,table| h[table] = [] }
641
+ rows = Hash.new { |h, table| h[table] = [] }
620
642
 
621
643
  rows[table_name] = fixtures.map do |label, fixture|
622
644
  row = fixture.to_hash
@@ -639,6 +661,13 @@ module ActiveRecord
639
661
  row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
640
662
  end
641
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
+
642
671
  # If STI is used, find the correct subclass for association reflection
643
672
  reflection_class =
644
673
  if row.include?(inheritance_column_name)
@@ -659,7 +688,7 @@ module ActiveRecord
659
688
  row[association.foreign_type] = $1
660
689
  end
661
690
 
662
- fk_type = reflection_class.columns_hash[fk_name].type
691
+ fk_type = reflection_class.type_for_attribute(fk_name).type
663
692
  row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
664
693
  end
665
694
  when :has_many
@@ -689,7 +718,7 @@ module ActiveRecord
689
718
  end
690
719
 
691
720
  def primary_key_type
692
- @association.klass.column_types[@association.klass.primary_key].type
721
+ @association.klass.type_for_attribute(@association.klass.primary_key).type
693
722
  end
694
723
  end
695
724
 
@@ -713,7 +742,7 @@ module ActiveRecord
713
742
  end
714
743
 
715
744
  def primary_key_type
716
- @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
717
746
  end
718
747
 
719
748
  def add_join_records(rows, row, association)
@@ -747,16 +776,28 @@ module ActiveRecord
747
776
  end
748
777
 
749
778
  def column_names
750
- @column_names ||= @connection.columns(@table_name).collect { |c| c.name }
779
+ @column_names ||= @connection.columns(@table_name).collect(&:name)
751
780
  end
752
781
 
753
- 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)
754
794
  yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
755
795
  ::File.file?(f)
756
796
  } + [yaml_file_path(path)]
757
797
 
758
798
  yaml_files.each_with_object({}) do |file, fixtures|
759
799
  FixtureSet::File.open(file) do |fh|
800
+ self.model_class ||= fh.model_class if fh.model_class
760
801
  fh.each do |fixture_name, row|
761
802
  fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
762
803
  end
@@ -767,15 +808,8 @@ module ActiveRecord
767
808
  def yaml_file_path(path)
768
809
  "#{path}.yml"
769
810
  end
770
-
771
811
  end
772
812
 
773
- #--
774
- # Deprecate 'Fixtures' in favor of 'FixtureSet'.
775
- #++
776
- # :nodoc:
777
- Fixtures = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveRecord::Fixtures', 'ActiveRecord::FixtureSet')
778
-
779
813
  class Fixture #:nodoc:
780
814
  include Enumerable
781
815
 
@@ -822,34 +856,24 @@ module ActiveRecord
822
856
  module TestFixtures
823
857
  extend ActiveSupport::Concern
824
858
 
825
- def before_setup
859
+ def before_setup # :nodoc:
826
860
  setup_fixtures
827
861
  super
828
862
  end
829
863
 
830
- def after_teardown
864
+ def after_teardown # :nodoc:
831
865
  super
832
866
  teardown_fixtures
833
867
  end
834
868
 
835
869
  included do
836
- class_attribute :fixture_path, :instance_writer => false
837
- class_attribute :fixture_table_names
838
- class_attribute :fixture_class_names
839
- class_attribute :use_transactional_fixtures
840
- class_attribute :use_instantiated_fixtures # true, false, or :no_instances
841
- class_attribute :pre_loaded_fixtures
842
- class_attribute :config
843
-
844
- self.fixture_table_names = []
845
- self.use_transactional_fixtures = true
846
- self.use_instantiated_fixtures = false
847
- self.pre_loaded_fixtures = false
848
- self.config = ActiveRecord::Base
849
-
850
- self.fixture_class_names = Hash.new do |h, fixture_set_name|
851
- h[fixture_set_name] = ActiveRecord::FixtureSet.default_fixture_model_name(fixture_set_name, self.config)
852
- 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
853
877
  end
854
878
 
855
879
  module ClassMethods
@@ -862,15 +886,15 @@ module ActiveRecord
862
886
  #
863
887
  # The keys must be the fixture names, that coincide with the short paths to the fixture files.
864
888
  def set_fixture_class(class_names = {})
865
- 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)
866
890
  end
867
891
 
868
892
  def fixtures(*fixture_set_names)
869
893
  if fixture_set_names.first == :all
870
- fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
894
+ fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"].uniq
871
895
  fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
872
896
  else
873
- fixture_set_names = fixture_set_names.flatten.map { |n| n.to_s }
897
+ fixture_set_names = fixture_set_names.flatten.map(&:to_s)
874
898
  end
875
899
 
876
900
  self.fixture_table_names |= fixture_set_names
@@ -882,15 +906,17 @@ module ActiveRecord
882
906
  methods = Module.new do
883
907
  fixture_set_names.each do |fs_name|
884
908
  fs_name = fs_name.to_s
885
- accessor_name = fs_name.tr('/', '_').to_sym
909
+ accessor_name = fs_name.tr("/", "_").to_sym
886
910
 
887
911
  define_method(accessor_name) do |*fixture_names|
888
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?
889
915
 
890
916
  @fixture_cache[fs_name] ||= {}
891
917
 
892
918
  instances = fixture_names.map do |f_name|
893
- f_name = f_name.to_s
919
+ f_name = f_name.to_s if f_name.is_a?(Symbol)
894
920
  @fixture_cache[fs_name].delete(f_name) if force_reload
895
921
 
896
922
  if @loaded_fixtures[fs_name][f_name]
@@ -900,7 +926,7 @@ module ActiveRecord
900
926
  end
901
927
  end
902
928
 
903
- instances.size == 1 ? instances.first : instances
929
+ return_single_record ? instances.first : instances
904
930
  end
905
931
  private accessor_name
906
932
  end
@@ -910,7 +936,7 @@ module ActiveRecord
910
936
 
911
937
  def uses_transaction(*methods)
912
938
  @uses_transaction = [] unless defined?(@uses_transaction)
913
- @uses_transaction.concat methods.map { |m| m.to_s }
939
+ @uses_transaction.concat methods.map(&:to_s)
914
940
  end
915
941
 
916
942
  def uses_transaction?(method)
@@ -920,18 +946,19 @@ module ActiveRecord
920
946
  end
921
947
 
922
948
  def run_in_transaction?
923
- use_transactional_fixtures &&
949
+ use_transactional_tests &&
924
950
  !self.class.uses_transaction?(method_name)
925
951
  end
926
952
 
927
953
  def setup_fixtures(config = ActiveRecord::Base)
928
- if pre_loaded_fixtures && !use_transactional_fixtures
929
- 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"
930
956
  end
931
957
 
932
958
  @fixture_cache = {}
933
959
  @fixture_connections = []
934
960
  @@already_loaded_fixtures ||= {}
961
+ @connection_subscriber = nil
935
962
 
936
963
  # Load fixtures once and begin transaction.
937
964
  if run_in_transaction?
@@ -941,10 +968,33 @@ module ActiveRecord
941
968
  @loaded_fixtures = load_fixtures(config)
942
969
  @@already_loaded_fixtures[self.class] = @loaded_fixtures
943
970
  end
971
+
972
+ # Begin transactions for connections already established
944
973
  @fixture_connections = enlist_fixture_connections
945
974
  @fixture_connections.each do |connection|
946
975
  connection.begin_transaction joinable: false
976
+ connection.pool.lock_thread = true
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
947
996
  end
997
+
948
998
  # Load fixtures for every test.
949
999
  else
950
1000
  ActiveRecord::FixtureSet.reset_cache
@@ -959,8 +1009,10 @@ module ActiveRecord
959
1009
  def teardown_fixtures
960
1010
  # Rollback changes if a transaction is active.
961
1011
  if run_in_transaction?
1012
+ ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
962
1013
  @fixture_connections.each do |connection|
963
1014
  connection.rollback_transaction if connection.transaction_open?
1015
+ connection.pool.lock_thread = false
964
1016
  end
965
1017
  @fixture_connections.clear
966
1018
  else
@@ -982,10 +1034,10 @@ module ActiveRecord
982
1034
 
983
1035
  def instantiate_fixtures
984
1036
  if pre_loaded_fixtures
985
- 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?
986
1038
  ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
987
1039
  else
988
- raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
1040
+ raise RuntimeError, "Load fixtures before instantiating them." if @loaded_fixtures.nil?
989
1041
  @loaded_fixtures.each_value do |fixture_set|
990
1042
  ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
991
1043
  end
@@ -1004,6 +1056,10 @@ class ActiveRecord::FixtureSet::RenderContext # :nodoc:
1004
1056
  def get_binding
1005
1057
  binding()
1006
1058
  end
1059
+
1060
+ def binary(path)
1061
+ %(!!binary "#{Base64.strict_encode64(File.read(path))}")
1062
+ end
1007
1063
  end
1008
1064
  end
1009
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 = 11
11
- PRE = "1"
12
+ TINY = 4
13
+ PRE = "5"
12
14
 
13
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
16
  end