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