activerecord 4.2.9 → 6.1.4.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 (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +964 -1382
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +266 -251
  8. data/lib/active_record/association_relation.rb +40 -15
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +162 -69
  11. data/lib/active_record/associations/association_scope.rb +105 -130
  12. data/lib/active_record/associations/belongs_to_association.rb +83 -65
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -37
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +148 -287
  22. data/lib/active_record/associations/collection_proxy.rb +252 -150
  23. data/lib/active_record/associations/foreign_association.rb +23 -1
  24. data/lib/active_record/associations/has_many_association.rb +56 -98
  25. data/lib/active_record/associations/has_many_through_association.rb +68 -89
  26. data/lib/active_record/associations/has_one_association.rb +73 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -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 +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +174 -169
  32. data/lib/active_record/associations/preloader/association.rb +108 -115
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +97 -94
  35. data/lib/active_record/associations/singular_association.rb +18 -39
  36. data/lib/active_record/associations/through_association.rb +39 -19
  37. data/lib/active_record/associations.rb +1845 -1598
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -148
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +55 -36
  46. data/lib/active_record/attribute_methods/write.rb +24 -55
  47. data/lib/active_record/attribute_methods.rb +149 -154
  48. data/lib/active_record/attributes.rb +234 -78
  49. data/lib/active_record/autosave_association.rb +133 -60
  50. data/lib/active_record/base.rb +46 -46
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +34 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +194 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -160
  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 +49 -58
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  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 +8 -6
  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 +14 -19
  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 -4
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +145 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +496 -298
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +588 -375
  119. data/lib/active_record/connection_adapters/schema_cache.rb +167 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -373
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +458 -241
  133. data/lib/active_record/counter_cache.rb +70 -49
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +272 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +211 -92
  143. data/lib/active_record/errors.rb +224 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +10 -5
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +275 -500
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +62 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +27 -5
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +98 -92
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +295 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +673 -325
  170. data/lib/active_record/model_schema.rb +418 -113
  171. data/lib/active_record/nested_attributes.rb +263 -224
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +572 -136
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +170 -51
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +523 -199
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +454 -291
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +324 -249
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +316 -242
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +95 -103
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +136 -122
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -413
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +18 -20
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -343
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -23
  209. data/lib/active_record/scoping/default.rb +96 -83
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +128 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +364 -130
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +287 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +182 -163
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -45
  231. data/lib/active_record/type/date_time.rb +4 -49
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +27 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +63 -56
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +42 -29
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -4
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  339. data/lib/rails/generators/active_record.rb +7 -5
  340. metadata +172 -65
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  348. data/lib/active_record/attribute.rb +0 -163
  349. data/lib/active_record/attribute_decorators.rb +0 -66
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/attribute_set.rb +0 -81
  352. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  353. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  354. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  355. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  356. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  357. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  358. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  359. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  360. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  361. data/lib/active_record/type/big_integer.rb +0 -13
  362. data/lib/active_record/type/binary.rb +0 -50
  363. data/lib/active_record/type/boolean.rb +0 -31
  364. data/lib/active_record/type/decimal.rb +0 -64
  365. data/lib/active_record/type/decorator.rb +0 -14
  366. data/lib/active_record/type/float.rb +0 -19
  367. data/lib/active_record/type/integer.rb +0 -59
  368. data/lib/active_record/type/mutable.rb +0 -16
  369. data/lib/active_record/type/numeric.rb +0 -36
  370. data/lib/active_record/type/string.rb +0 -40
  371. data/lib/active_record/type/time_value.rb +0 -38
  372. data/lib/active_record/type/value.rb +0 -110
  373. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  374. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,10 +1,15 @@
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/fixture_set/render_context"
11
+ require "active_record/fixture_set/table_rows"
12
+ require "active_record/test_fixtures"
8
13
 
9
14
  module ActiveRecord
10
15
  class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
@@ -35,7 +40,7 @@ module ActiveRecord
35
40
  # separated by a blank line for your viewing pleasure.
36
41
  #
37
42
  # Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
38
- # See http://yaml.org/type/omap.html
43
+ # See https://yaml.org/type/omap.html
39
44
  # for the specification. You will need ordered fixtures when you have foreign key constraints
40
45
  # on keys in the same table. This is commonly needed for tree structures. Example:
41
46
  #
@@ -54,7 +59,7 @@ module ActiveRecord
54
59
  # Since fixtures are a testing construct, we use them in our unit and functional tests. There
55
60
  # are two ways to use the fixtures, but first let's take a look at a sample unit test:
56
61
  #
57
- # require 'test_helper'
62
+ # require "test_helper"
58
63
  #
59
64
  # class WebSiteTest < ActiveSupport::TestCase
60
65
  # test "web_site_count" do
@@ -65,17 +70,36 @@ module ActiveRecord
65
70
  # By default, +test_helper.rb+ will load all of your fixtures into your test
66
71
  # database, so this test will succeed.
67
72
  #
68
- # The testing environment will automatically load the all fixtures into the database before each
73
+ # The testing environment will automatically load all the fixtures into the database before each
69
74
  # test. To ensure consistent data, the environment deletes the fixtures before running the load.
70
75
  #
71
76
  # 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:
77
+ # using a special dynamic method, which has the same name as the model.
74
78
  #
75
- # test "find" do
79
+ # Passing in a fixture name to this dynamic method returns the fixture matching this name:
80
+ #
81
+ # test "find one" do
76
82
  # assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
77
83
  # end
78
84
  #
85
+ # Passing in multiple fixture names returns all fixtures matching these names:
86
+ #
87
+ # test "find all by name" do
88
+ # assert_equal 2, web_sites(:rubyonrails, :google).length
89
+ # end
90
+ #
91
+ # Passing in no arguments returns all fixtures:
92
+ #
93
+ # test "find all" do
94
+ # assert_equal 2, web_sites.length
95
+ # end
96
+ #
97
+ # Passing in any fixture name that does not exist will raise <tt>StandardError</tt>:
98
+ #
99
+ # test "find by name that does not exist" do
100
+ # assert_raise(StandardError) { web_sites(:reddit) }
101
+ # end
102
+ #
79
103
  # Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the
80
104
  # following tests:
81
105
  #
@@ -87,8 +111,8 @@ module ActiveRecord
87
111
  # assert_equal "Ruby on Rails", @rubyonrails.name
88
112
  # end
89
113
  #
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:
114
+ # In order to use these methods to access fixtured data within your test cases, you must specify one of the
115
+ # following in your ActiveSupport::TestCase-derived class:
92
116
  #
93
117
  # - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
94
118
  # self.use_instantiated_fixtures = true
@@ -102,14 +126,14 @@ module ActiveRecord
102
126
  #
103
127
  # = Dynamic fixtures with ERB
104
128
  #
105
- # Some times you don't care about the content of the fixtures as much as you care about the volume.
129
+ # Sometimes you don't care about the content of the fixtures as much as you care about the volume.
106
130
  # In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
107
131
  # testing, like:
108
132
  #
109
133
  # <% 1.upto(1000) do |i| %>
110
134
  # fix_<%= i %>:
111
135
  # id: <%= i %>
112
- # name: guy_<%= 1 %>
136
+ # name: guy_<%= i %>
113
137
  # <% end %>
114
138
  #
115
139
  # This will create 1000 very simple fixtures.
@@ -123,49 +147,49 @@ module ActiveRecord
123
147
  #
124
148
  # Helper methods defined in a fixture will not be available in other fixtures, to prevent against
125
149
  # 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>.
150
+ # that is included in ActiveRecord::FixtureSet.context_class.
127
151
  #
128
- # - define a helper method in `test_helper.rb`
152
+ # - define a helper method in <tt>test_helper.rb</tt>
129
153
  # module FixtureFileHelpers
130
154
  # def file_sha(path)
131
155
  # Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
132
156
  # end
133
157
  # end
134
- # ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers
158
+ # ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
135
159
  #
136
160
  # - use the helper method in a fixture
137
161
  # photo:
138
162
  # name: kitten.png
139
163
  # sha: <%= file_sha 'files/kitten.png' %>
140
164
  #
141
- # = Transactional Fixtures
165
+ # = Transactional Tests
142
166
  #
143
167
  # Test cases can use begin+rollback to isolate their changes to the database instead of having to
144
168
  # delete+insert for every test case.
145
169
  #
146
170
  # class FooTest < ActiveSupport::TestCase
147
- # self.use_transactional_fixtures = true
171
+ # self.use_transactional_tests = true
148
172
  #
149
173
  # test "godzilla" do
150
- # assert !Foo.all.empty?
174
+ # assert_not_empty Foo.all
151
175
  # Foo.destroy_all
152
- # assert Foo.all.empty?
176
+ # assert_empty Foo.all
153
177
  # end
154
178
  #
155
179
  # test "godzilla aftermath" do
156
- # assert !Foo.all.empty?
180
+ # assert_not_empty Foo.all
157
181
  # end
158
182
  # end
159
183
  #
160
- # 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
184
+ # If you preload your test database with all fixture data (probably by running <tt>bin/rails db:fixtures:load</tt>)
185
+ # and use transactional tests, then you may omit all fixtures declarations in your test cases since
162
186
  # all the data's already there and every case rolls back its changes.
163
187
  #
164
188
  # In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to
165
189
  # true. This will provide access to fixture data for every table that has been loaded through
166
190
  # fixtures (depending on the value of +use_instantiated_fixtures+).
167
191
  #
168
- # When *not* to use transactional fixtures:
192
+ # When *not* to use transactional tests:
169
193
  #
170
194
  # 1. You're testing whether a transaction works correctly. Nested transactions don't commit until
171
195
  # all parent transactions commit, particularly, the fixtures transaction which is begun in setup
@@ -394,207 +418,256 @@ module ActiveRecord
394
418
  # <<: *DEFAULTS
395
419
  #
396
420
  # Any fixture labeled "DEFAULTS" is safely ignored.
421
+ #
422
+ # Besides using "DEFAULTS", you can also specify what fixtures will
423
+ # be ignored by setting "ignore" in "_fixture" section.
424
+ #
425
+ # # users.yml
426
+ # _fixture:
427
+ # ignore:
428
+ # - base
429
+ # # or use "ignore: base" when there is only one fixture needs to be ignored.
430
+ #
431
+ # base: &base
432
+ # admin: false
433
+ # introduction: "This is a default description"
434
+ #
435
+ # admin:
436
+ # <<: *base
437
+ # admin: true
438
+ #
439
+ # visitor:
440
+ # <<: *base
441
+ #
442
+ # In the above example, 'base' will be ignored when creating fixtures.
443
+ # This can be used for common attributes inheriting.
444
+ #
445
+ # == Configure the fixture model class
446
+ #
447
+ # It's possible to set the fixture's model class directly in the YAML file.
448
+ # This is helpful when fixtures are loaded outside tests and
449
+ # +set_fixture_class+ is not available (e.g.
450
+ # when running <tt>bin/rails db:fixtures:load</tt>).
451
+ #
452
+ # _fixture:
453
+ # model_class: User
454
+ # david:
455
+ # name: David
456
+ #
457
+ # Any fixtures labeled "_fixture" are safely ignored.
397
458
  class FixtureSet
398
459
  #--
399
460
  # An instance of FixtureSet is normally stored in a single YAML file and
400
461
  # possibly in a folder with the same name.
401
462
  #++
402
463
 
403
- MAX_ID = 2 ** 30 - 1
464
+ MAX_ID = 2**30 - 1
404
465
 
405
- @@all_cached_fixtures = Hash.new { |h,k| h[k] = {} }
466
+ @@all_cached_fixtures = Hash.new { |h, k| h[k] = {} }
406
467
 
407
- def self.default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
408
- config.pluralize_table_names ?
409
- fixture_set_name.singularize.camelize :
410
- fixture_set_name.camelize
411
- end
468
+ cattr_accessor :all_loaded_fixtures, default: {}
412
469
 
413
- 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
417
- end
470
+ class ClassCache
471
+ def initialize(class_names, config)
472
+ @class_names = class_names.stringify_keys
473
+ @config = config
418
474
 
419
- def self.reset_cache
420
- @@all_cached_fixtures.clear
421
- end
475
+ # Remove string values that aren't constants or subclasses of AR
476
+ @class_names.delete_if do |klass_name, klass|
477
+ !insert_class(@class_names, klass_name, klass)
478
+ end
479
+ end
422
480
 
423
- def self.cache_for_connection(connection)
424
- @@all_cached_fixtures[connection]
425
- end
481
+ def [](fs_name)
482
+ @class_names.fetch(fs_name) do
483
+ klass = default_fixture_model(fs_name, @config).safe_constantize
484
+ insert_class(@class_names, fs_name, klass)
485
+ end
486
+ end
426
487
 
427
- def self.fixture_is_cached?(connection, table_name)
428
- cache_for_connection(connection)[table_name]
488
+ private
489
+ def insert_class(class_names, name, klass)
490
+ # We only want to deal with AR objects.
491
+ if klass && klass < ActiveRecord::Base
492
+ class_names[name] = klass
493
+ else
494
+ class_names[name] = nil
495
+ end
496
+ end
497
+
498
+ def default_fixture_model(fs_name, config)
499
+ ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
500
+ end
429
501
  end
430
502
 
431
- def self.cached_fixtures(connection, keys_to_fetch = nil)
432
- if keys_to_fetch
433
- cache_for_connection(connection).values_at(*keys_to_fetch)
434
- else
435
- cache_for_connection(connection).values
503
+ class << self
504
+ def default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
505
+ config.pluralize_table_names ?
506
+ fixture_set_name.singularize.camelize :
507
+ fixture_set_name.camelize
436
508
  end
437
- end
438
509
 
439
- def self.cache_fixtures(connection, fixtures_map)
440
- cache_for_connection(connection).update(fixtures_map)
441
- end
510
+ def default_fixture_table_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
511
+ "#{ config.table_name_prefix }"\
512
+ "#{ fixture_set_name.tr('/', '_') }"\
513
+ "#{ config.table_name_suffix }".to_sym
514
+ end
442
515
 
443
- def self.instantiate_fixtures(object, fixture_set, load_instances = true)
444
- if load_instances
445
- fixture_set.each do |fixture_name, fixture|
446
- begin
447
- object.instance_variable_set "@#{fixture_name}", fixture.find
448
- rescue FixtureClassNotFound
449
- nil
450
- end
451
- end
516
+ def reset_cache
517
+ @@all_cached_fixtures.clear
452
518
  end
453
- end
454
519
 
455
- def self.instantiate_all_loaded_fixtures(object, load_instances = true)
456
- all_loaded_fixtures.each_value do |fixture_set|
457
- instantiate_fixtures(object, fixture_set, load_instances)
520
+ def cache_for_connection(connection)
521
+ @@all_cached_fixtures[connection]
458
522
  end
459
- end
460
523
 
461
- cattr_accessor :all_loaded_fixtures
462
- self.all_loaded_fixtures = {}
524
+ def fixture_is_cached?(connection, table_name)
525
+ cache_for_connection(connection)[table_name]
526
+ end
463
527
 
464
- class ClassCache
465
- def initialize(class_names, config)
466
- @class_names = class_names.stringify_keys
467
- @config = config
528
+ def cached_fixtures(connection, keys_to_fetch = nil)
529
+ if keys_to_fetch
530
+ cache_for_connection(connection).values_at(*keys_to_fetch)
531
+ else
532
+ cache_for_connection(connection).values
533
+ end
534
+ end
468
535
 
469
- # Remove string values that aren't constants or subclasses of AR
470
- @class_names.delete_if { |klass_name, klass| !insert_class(@class_names, klass_name, klass) }
536
+ def cache_fixtures(connection, fixtures_map)
537
+ cache_for_connection(connection).update(fixtures_map)
471
538
  end
472
539
 
473
- def [](fs_name)
474
- @class_names.fetch(fs_name) {
475
- klass = default_fixture_model(fs_name, @config).safe_constantize
476
- insert_class(@class_names, fs_name, klass)
477
- }
540
+ def instantiate_fixtures(object, fixture_set, load_instances = true)
541
+ return unless load_instances
542
+ fixture_set.each do |fixture_name, fixture|
543
+ object.instance_variable_set "@#{fixture_name}", fixture.find
544
+ rescue FixtureClassNotFound
545
+ nil
546
+ end
478
547
  end
479
548
 
480
- private
549
+ def instantiate_all_loaded_fixtures(object, load_instances = true)
550
+ all_loaded_fixtures.each_value do |fixture_set|
551
+ instantiate_fixtures(object, fixture_set, load_instances)
552
+ end
553
+ end
481
554
 
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
555
+ def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
556
+ fixture_set_names = Array(fixture_set_names).map(&:to_s)
557
+ class_names = ClassCache.new class_names, config
558
+
559
+ # FIXME: Apparently JK uses this.
560
+ connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
561
+
562
+ fixture_files_to_read = fixture_set_names.reject do |fs_name|
563
+ fixture_is_cached?(connection.call, fs_name)
488
564
  end
565
+
566
+ if fixture_files_to_read.any?
567
+ fixtures_map = read_and_insert(
568
+ fixtures_directory,
569
+ fixture_files_to_read,
570
+ class_names,
571
+ connection,
572
+ )
573
+ cache_fixtures(connection.call, fixtures_map)
574
+ end
575
+ cached_fixtures(connection.call, fixture_set_names)
489
576
  end
490
577
 
491
- def default_fixture_model(fs_name, config)
492
- ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
578
+ # Returns a consistent, platform-independent identifier for +label+.
579
+ # Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
580
+ def identify(label, column_type = :integer)
581
+ if column_type == :uuid
582
+ Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
583
+ else
584
+ Zlib.crc32(label.to_s) % MAX_ID
585
+ end
493
586
  end
494
- end
495
587
 
496
- def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
497
- fixture_set_names = Array(fixture_set_names).map(&:to_s)
498
- class_names = ClassCache.new class_names, config
588
+ def signed_global_id(fixture_set_name, label, column_type: :integer, **options)
589
+ identifier = identify(label, column_type)
590
+ model_name = default_fixture_model_name(fixture_set_name)
591
+ uri = URI::GID.build([GlobalID.app, model_name, identifier, {}])
499
592
 
500
- # FIXME: Apparently JK uses this.
501
- connection = block_given? ? yield : ActiveRecord::Base.connection
593
+ SignedGlobalID.new(uri, **options)
594
+ end
502
595
 
503
- files_to_read = fixture_set_names.reject { |fs_name|
504
- fixture_is_cached?(connection, fs_name)
505
- }
596
+ # Superclass for the evaluation contexts used by ERB fixtures.
597
+ def context_class
598
+ @context_class ||= Class.new
599
+ end
506
600
 
507
- unless files_to_read.empty?
508
- connection.disable_referential_integrity do
601
+ private
602
+ def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc:
509
603
  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,
604
+ fixture_sets = fixture_files.map do |fixture_set_name|
605
+ klass = class_names[fixture_set_name]
606
+ fixtures_map[fixture_set_name] = new( # ActiveRecord::FixtureSet.new
607
+ nil,
608
+ fixture_set_name,
517
609
  klass,
518
- ::File.join(fixtures_directory, fs_name))
610
+ ::File.join(fixtures_directory, fixture_set_name)
611
+ )
519
612
  end
613
+ update_all_loaded_fixtures(fixtures_map)
520
614
 
521
- update_all_loaded_fixtures fixtures_map
615
+ insert(fixture_sets, connection)
522
616
 
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
617
+ fixtures_map
618
+ end
527
619
 
528
- table_rows.each_key do |table|
529
- conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
530
- end
620
+ def insert(fixture_sets, connection) # :nodoc:
621
+ fixture_sets_by_connection = fixture_sets.group_by do |fixture_set|
622
+ if fixture_set.model_class
623
+ fixture_set.model_class.connection
624
+ else
625
+ connection.call
626
+ end
627
+ end
531
628
 
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
629
+ fixture_sets_by_connection.each do |conn, set|
630
+ table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
537
631
 
538
- # Cap primary key sequences to max(pk).
539
- if conn.respond_to?(:reset_pk_sequence!)
540
- conn.reset_pk_sequence!(fs.table_name)
632
+ set.each do |fixture_set|
633
+ fixture_set.table_rows.each do |table, rows|
634
+ table_rows_for_connection[table].unshift(*rows)
541
635
  end
542
636
  end
543
- end
544
637
 
545
- cache_fixtures(connection, fixtures_map)
546
- end
547
- end
548
- cached_fixtures(connection, fixture_set_names)
549
- end
550
-
551
- # Returns a consistent, platform-independent identifier for +label+.
552
- # Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
553
- def self.identify(label, column_type = :integer)
554
- if column_type == :uuid
555
- Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
556
- else
557
- Zlib.crc32(label.to_s) % MAX_ID
558
- end
559
- end
638
+ conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
560
639
 
561
- # Superclass for the evaluation contexts used by ERB fixtures.
562
- def self.context_class
563
- @context_class ||= Class.new
564
- end
640
+ # Cap primary key sequences to max(pk).
641
+ if conn.respond_to?(:reset_pk_sequence!)
642
+ set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
643
+ end
644
+ end
645
+ end
565
646
 
566
- def self.update_all_loaded_fixtures(fixtures_map) # :nodoc:
567
- all_loaded_fixtures.update(fixtures_map)
647
+ def update_all_loaded_fixtures(fixtures_map) # :nodoc:
648
+ all_loaded_fixtures.update(fixtures_map)
649
+ end
568
650
  end
569
651
 
570
- attr_reader :table_name, :name, :fixtures, :model_class, :config
652
+ attr_reader :table_name, :name, :fixtures, :model_class, :ignored_fixtures, :config
571
653
 
572
- def initialize(connection, name, class_name, path, config = ActiveRecord::Base)
654
+ def initialize(_, name, class_name, path, config = ActiveRecord::Base)
573
655
  @name = name
574
656
  @path = path
575
657
  @config = config
576
- @model_class = nil
577
658
 
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
659
+ self.model_class = class_name
583
660
 
584
- @connection = connection
661
+ @fixtures = read_fixture_files(path)
585
662
 
586
- @table_name = ( model_class.respond_to?(:table_name) ?
587
- model_class.table_name :
588
- self.class.default_fixture_table_name(name, config) )
589
-
590
- @fixtures = read_fixture_files path, @model_class
663
+ @table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
591
664
  end
592
665
 
593
666
  def [](x)
594
667
  fixtures[x]
595
668
  end
596
669
 
597
- def []=(k,v)
670
+ def []=(k, v)
598
671
  fixtures[k] = v
599
672
  end
600
673
 
@@ -609,154 +682,53 @@ module ActiveRecord
609
682
  # Returns a hash of rows to be inserted. The key is the table, the value is
610
683
  # a list of rows to insert to that table.
611
684
  def table_rows
612
- now = config.default_timezone == :utc ? Time.now.utc : Time.now
613
- now = now.to_s(:db)
614
-
615
- # allow a standard key to be used for doing defaults in YAML
616
- fixtures.delete('DEFAULTS')
617
-
618
- # track any join tables we need to insert later
619
- rows = Hash.new { |h,table| h[table] = [] }
620
-
621
- rows[table_name] = fixtures.map do |label, fixture|
622
- row = fixture.to_hash
623
-
624
- if model_class
625
- # fill in timestamp columns if they aren't specified and the model is set to record_timestamps
626
- if model_class.record_timestamps
627
- timestamp_column_names.each do |c_name|
628
- row[c_name] = now unless row.key?(c_name)
629
- end
630
- end
685
+ # allow specifying fixtures to be ignored by setting `ignore` in `_fixture` section
686
+ fixtures.except!(*ignored_fixtures)
631
687
 
632
- # interpolate the fixture label
633
- row.each do |key, value|
634
- row[key] = value.gsub("$LABEL", label.to_s) if value.is_a?(String)
635
- end
636
-
637
- # generate a primary key if necessary
638
- if has_primary_key_column? && !row.include?(primary_key_name)
639
- row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
640
- end
641
-
642
- # If STI is used, find the correct subclass for association reflection
643
- reflection_class =
644
- if row.include?(inheritance_column_name)
645
- row[inheritance_column_name].constantize rescue model_class
646
- else
647
- model_class
648
- end
649
-
650
- reflection_class._reflections.each_value do |association|
651
- case association.macro
652
- when :belongs_to
653
- # Do not replace association name with association foreign key if they are named the same
654
- fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
655
-
656
- if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
657
- if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
658
- # support polymorphic belongs_to as "label (Type)"
659
- row[association.foreign_type] = $1
660
- end
661
-
662
- fk_type = reflection_class.columns_hash[fk_name].type
663
- row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
664
- end
665
- when :has_many
666
- if association.options[:through]
667
- add_join_records(rows, row, HasManyThroughProxy.new(association))
668
- end
669
- end
670
- end
671
- end
672
-
673
- row
674
- end
675
- rows
676
- end
677
-
678
- class ReflectionProxy # :nodoc:
679
- def initialize(association)
680
- @association = association
681
- end
682
-
683
- def join_table
684
- @association.join_table
685
- end
686
-
687
- def name
688
- @association.name
689
- end
690
-
691
- def primary_key_type
692
- @association.klass.column_types[@association.klass.primary_key].type
693
- end
694
- end
695
-
696
- class HasManyThroughProxy < ReflectionProxy # :nodoc:
697
- def rhs_key
698
- @association.foreign_key
699
- end
700
-
701
- def lhs_key
702
- @association.through_reflection.foreign_key
703
- end
704
-
705
- def join_table
706
- @association.through_reflection.table_name
707
- end
688
+ TableRows.new(
689
+ table_name,
690
+ model_class: model_class,
691
+ fixtures: fixtures,
692
+ config: config,
693
+ ).to_hash
708
694
  end
709
695
 
710
696
  private
711
- def primary_key_name
712
- @primary_key_name ||= model_class && model_class.primary_key
713
- end
714
-
715
- def primary_key_type
716
- @primary_key_type ||= model_class && model_class.column_types[model_class.primary_key].type
717
- end
718
-
719
- def add_join_records(rows, row, association)
720
- # This is the case when the join table has no fixtures file
721
- if (targets = row.delete(association.name.to_s))
722
- table_name = association.join_table
723
- column_type = association.primary_key_type
724
- lhs_key = association.lhs_key
725
- rhs_key = association.rhs_key
726
-
727
- targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
728
- rows[table_name].concat targets.map { |target|
729
- { lhs_key => row[primary_key_name],
730
- rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
731
- }
697
+ def model_class=(class_name)
698
+ if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
699
+ @model_class = class_name
700
+ else
701
+ @model_class = class_name.safe_constantize if class_name
732
702
  end
733
703
  end
734
704
 
735
- def has_primary_key_column?
736
- @has_primary_key_column ||= primary_key_name &&
737
- model_class.columns.any? { |c| c.name == primary_key_name }
738
- end
739
-
740
- def timestamp_column_names
741
- @timestamp_column_names ||=
742
- %w(created_at created_on updated_at updated_on) & column_names
743
- end
744
-
745
- def inheritance_column_name
746
- @inheritance_column_name ||= model_class && model_class.inheritance_column
747
- end
705
+ def ignored_fixtures=(base)
706
+ @ignored_fixtures =
707
+ case base
708
+ when Array
709
+ base
710
+ when String
711
+ [base]
712
+ else
713
+ []
714
+ end
748
715
 
749
- def column_names
750
- @column_names ||= @connection.columns(@table_name).collect { |c| c.name }
716
+ @ignored_fixtures << "DEFAULTS" unless @ignored_fixtures.include?("DEFAULTS")
717
+ @ignored_fixtures.compact
751
718
  end
752
719
 
753
- def read_fixture_files(path, model_class)
720
+ # Loads the fixtures from the YAML file at +path+.
721
+ # If the file sets the +model_class+ and current instance value is not set,
722
+ # it uses the file value.
723
+ def read_fixture_files(path)
754
724
  yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
755
725
  ::File.file?(f)
756
726
  } + [yaml_file_path(path)]
757
727
 
758
728
  yaml_files.each_with_object({}) do |file, fixtures|
759
729
  FixtureSet::File.open(file) do |fh|
730
+ self.model_class ||= fh.model_class if fh.model_class
731
+ self.ignored_fixtures ||= fh.ignored_fixtures
760
732
  fh.each do |fixture_name, row|
761
733
  fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
762
734
  end
@@ -767,15 +739,8 @@ module ActiveRecord
767
739
  def yaml_file_path(path)
768
740
  "#{path}.yml"
769
741
  end
770
-
771
742
  end
772
743
 
773
- #--
774
- # Deprecate 'Fixtures' in favor of 'FixtureSet'.
775
- #++
776
- # :nodoc:
777
- Fixtures = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveRecord::Fixtures', 'ActiveRecord::FixtureSet')
778
-
779
744
  class Fixture #:nodoc:
780
745
  include Enumerable
781
746
 
@@ -807,203 +772,13 @@ module ActiveRecord
807
772
  alias :to_hash :fixture
808
773
 
809
774
  def find
810
- if model_class
811
- model_class.unscoped do
812
- model_class.find(fixture[model_class.primary_key])
813
- end
814
- else
815
- raise FixtureClassNotFound, "No class attached to find."
816
- end
817
- end
818
- end
819
- end
820
-
821
- module ActiveRecord
822
- module TestFixtures
823
- extend ActiveSupport::Concern
824
-
825
- def before_setup
826
- setup_fixtures
827
- super
828
- end
829
-
830
- def after_teardown
831
- super
832
- teardown_fixtures
833
- end
834
-
835
- 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
853
- end
854
-
855
- module ClassMethods
856
- # Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
857
- #
858
- # Examples:
859
- #
860
- # set_fixture_class some_fixture: SomeModel,
861
- # 'namespaced/fixture' => Another::Model
862
- #
863
- # The keys must be the fixture names, that coincide with the short paths to the fixture files.
864
- def set_fixture_class(class_names = {})
865
- self.fixture_class_names = self.fixture_class_names.merge(class_names.stringify_keys)
866
- end
867
-
868
- def fixtures(*fixture_set_names)
869
- if fixture_set_names.first == :all
870
- fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
871
- fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
872
- else
873
- fixture_set_names = fixture_set_names.flatten.map { |n| n.to_s }
874
- end
875
-
876
- self.fixture_table_names |= fixture_set_names
877
- setup_fixture_accessors(fixture_set_names)
878
- end
879
-
880
- def setup_fixture_accessors(fixture_set_names = nil)
881
- fixture_set_names = Array(fixture_set_names || fixture_table_names)
882
- methods = Module.new do
883
- fixture_set_names.each do |fs_name|
884
- fs_name = fs_name.to_s
885
- accessor_name = fs_name.tr('/', '_').to_sym
886
-
887
- define_method(accessor_name) do |*fixture_names|
888
- force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
889
-
890
- @fixture_cache[fs_name] ||= {}
891
-
892
- instances = fixture_names.map do |f_name|
893
- f_name = f_name.to_s
894
- @fixture_cache[fs_name].delete(f_name) if force_reload
895
-
896
- if @loaded_fixtures[fs_name][f_name]
897
- @fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
898
- else
899
- raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
900
- end
901
- end
902
-
903
- instances.size == 1 ? instances.first : instances
904
- end
905
- private accessor_name
906
- end
907
- end
908
- include methods
909
- end
910
-
911
- def uses_transaction(*methods)
912
- @uses_transaction = [] unless defined?(@uses_transaction)
913
- @uses_transaction.concat methods.map { |m| m.to_s }
914
- end
915
-
916
- def uses_transaction?(method)
917
- @uses_transaction = [] unless defined?(@uses_transaction)
918
- @uses_transaction.include?(method.to_s)
919
- end
920
- end
921
-
922
- def run_in_transaction?
923
- use_transactional_fixtures &&
924
- !self.class.uses_transaction?(method_name)
925
- end
926
-
927
- def setup_fixtures(config = ActiveRecord::Base)
928
- if pre_loaded_fixtures && !use_transactional_fixtures
929
- raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
930
- end
931
-
932
- @fixture_cache = {}
933
- @fixture_connections = []
934
- @@already_loaded_fixtures ||= {}
935
-
936
- # Load fixtures once and begin transaction.
937
- if run_in_transaction?
938
- if @@already_loaded_fixtures[self.class]
939
- @loaded_fixtures = @@already_loaded_fixtures[self.class]
940
- else
941
- @loaded_fixtures = load_fixtures(config)
942
- @@already_loaded_fixtures[self.class] = @loaded_fixtures
943
- end
944
- @fixture_connections = enlist_fixture_connections
945
- @fixture_connections.each do |connection|
946
- connection.begin_transaction joinable: false
947
- end
948
- # Load fixtures for every test.
949
- else
950
- ActiveRecord::FixtureSet.reset_cache
951
- @@already_loaded_fixtures[self.class] = nil
952
- @loaded_fixtures = load_fixtures(config)
953
- end
954
-
955
- # Instantiate fixtures for every test if requested.
956
- instantiate_fixtures if use_instantiated_fixtures
957
- end
958
-
959
- def teardown_fixtures
960
- # Rollback changes if a transaction is active.
961
- if run_in_transaction?
962
- @fixture_connections.each do |connection|
963
- connection.rollback_transaction if connection.transaction_open?
964
- end
965
- @fixture_connections.clear
966
- else
967
- ActiveRecord::FixtureSet.reset_cache
968
- end
969
-
970
- ActiveRecord::Base.clear_active_connections!
971
- end
972
-
973
- def enlist_fixture_connections
974
- ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
975
- end
976
-
977
- private
978
- def load_fixtures(config)
979
- fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config)
980
- Hash[fixtures.map { |f| [f.name, f] }]
981
- end
982
-
983
- def instantiate_fixtures
984
- if pre_loaded_fixtures
985
- raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
986
- ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
987
- else
988
- raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
989
- @loaded_fixtures.each_value do |fixture_set|
990
- ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
991
- end
992
- end
993
- end
994
-
995
- def load_instances?
996
- use_instantiated_fixtures != :no_instances
997
- end
998
- end
999
- end
1000
-
1001
- class ActiveRecord::FixtureSet::RenderContext # :nodoc:
1002
- def self.create_subclass
1003
- Class.new ActiveRecord::FixtureSet.context_class do
1004
- def get_binding
1005
- binding()
775
+ raise FixtureClassNotFound, "No class attached to find." unless model_class
776
+ object = model_class.unscoped do
777
+ model_class.find(fixture[model_class.primary_key])
1006
778
  end
779
+ # Fixtures can't be eagerly loaded
780
+ object.instance_variable_set(:@strict_loading, false)
781
+ object
1007
782
  end
1008
783
  end
1009
784
  end