activerecord 5.0.7.2 → 6.0.3.4

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 (359) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +708 -2040
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +9 -7
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record.rb +37 -22
  8. data/lib/active_record/advisory_lock_base.rb +18 -0
  9. data/lib/active_record/aggregations.rb +249 -247
  10. data/lib/active_record/association_relation.rb +18 -14
  11. data/lib/active_record/associations.rb +1603 -1592
  12. data/lib/active_record/associations/alias_tracker.rb +24 -34
  13. data/lib/active_record/associations/association.rb +114 -55
  14. data/lib/active_record/associations/association_scope.rb +94 -94
  15. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  16. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  17. data/lib/active_record/associations/builder/association.rb +18 -25
  18. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  19. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  20. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
  21. data/lib/active_record/associations/builder/has_many.rb +4 -0
  22. data/lib/active_record/associations/builder/has_one.rb +37 -1
  23. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  24. data/lib/active_record/associations/collection_association.rb +86 -254
  25. data/lib/active_record/associations/collection_proxy.rb +158 -122
  26. data/lib/active_record/associations/foreign_association.rb +9 -0
  27. data/lib/active_record/associations/has_many_association.rb +23 -30
  28. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  29. data/lib/active_record/associations/has_one_association.rb +59 -54
  30. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  31. data/lib/active_record/associations/join_dependency.rb +143 -176
  32. data/lib/active_record/associations/join_dependency/join_association.rb +38 -87
  33. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  34. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  35. data/lib/active_record/associations/preloader.rb +90 -103
  36. data/lib/active_record/associations/preloader/association.rb +86 -100
  37. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  38. data/lib/active_record/associations/singular_association.rb +12 -45
  39. data/lib/active_record/associations/through_association.rb +26 -14
  40. data/lib/active_record/attribute_assignment.rb +54 -61
  41. data/lib/active_record/attribute_decorators.rb +38 -17
  42. data/lib/active_record/attribute_methods.rb +66 -106
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
  44. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  45. data/lib/active_record/attribute_methods/primary_key.rb +85 -92
  46. data/lib/active_record/attribute_methods/query.rb +4 -3
  47. data/lib/active_record/attribute_methods/read.rb +20 -49
  48. data/lib/active_record/attribute_methods/serialization.rb +29 -7
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
  50. data/lib/active_record/attribute_methods/write.rb +34 -33
  51. data/lib/active_record/attributes.rb +38 -25
  52. data/lib/active_record/autosave_association.rb +54 -35
  53. data/lib/active_record/base.rb +27 -24
  54. data/lib/active_record/callbacks.rb +64 -35
  55. data/lib/active_record/coders/json.rb +2 -0
  56. data/lib/active_record/coders/yaml_column.rb +11 -12
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +552 -323
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +228 -147
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -202
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +396 -562
  70. data/lib/active_record/connection_adapters/column.rb +41 -13
  71. data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  73. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  101. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -31
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  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 +8 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
  118. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  120. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  121. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  122. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  123. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  124. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  127. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +259 -266
  128. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  129. data/lib/active_record/connection_handling.rb +143 -40
  130. data/lib/active_record/core.rb +201 -163
  131. data/lib/active_record/counter_cache.rb +60 -28
  132. data/lib/active_record/database_configurations.rb +233 -0
  133. data/lib/active_record/database_configurations/database_config.rb +37 -0
  134. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  135. data/lib/active_record/database_configurations/url_config.rb +78 -0
  136. data/lib/active_record/define_callbacks.rb +22 -0
  137. data/lib/active_record/dynamic_matchers.rb +87 -87
  138. data/lib/active_record/enum.rb +60 -23
  139. data/lib/active_record/errors.rb +114 -18
  140. data/lib/active_record/explain.rb +4 -4
  141. data/lib/active_record/explain_registry.rb +3 -1
  142. data/lib/active_record/explain_subscriber.rb +9 -4
  143. data/lib/active_record/fixture_set/file.rb +13 -8
  144. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  145. data/lib/active_record/fixture_set/render_context.rb +17 -0
  146. data/lib/active_record/fixture_set/table_row.rb +152 -0
  147. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  148. data/lib/active_record/fixtures.rb +194 -504
  149. data/lib/active_record/gem_version.rb +5 -3
  150. data/lib/active_record/inheritance.rb +150 -99
  151. data/lib/active_record/insert_all.rb +179 -0
  152. data/lib/active_record/integration.rb +116 -25
  153. data/lib/active_record/internal_metadata.rb +16 -19
  154. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  155. data/lib/active_record/locking/optimistic.rb +77 -87
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +48 -29
  158. data/lib/active_record/middleware/database_selector.rb +74 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +369 -302
  162. data/lib/active_record/migration/command_recorder.rb +134 -100
  163. data/lib/active_record/migration/compatibility.rb +174 -56
  164. data/lib/active_record/migration/join_table.rb +8 -7
  165. data/lib/active_record/model_schema.rb +131 -127
  166. data/lib/active_record/nested_attributes.rb +213 -202
  167. data/lib/active_record/no_touching.rb +12 -3
  168. data/lib/active_record/null_relation.rb +12 -34
  169. data/lib/active_record/persistence.rb +446 -77
  170. data/lib/active_record/query_cache.rb +13 -12
  171. data/lib/active_record/querying.rb +37 -24
  172. data/lib/active_record/railtie.rb +128 -36
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +312 -177
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +214 -252
  179. data/lib/active_record/relation.rb +440 -318
  180. data/lib/active_record/relation/batches.rb +98 -52
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  182. data/lib/active_record/relation/calculations.rb +212 -173
  183. data/lib/active_record/relation/delegation.rb +72 -69
  184. data/lib/active_record/relation/finder_methods.rb +207 -247
  185. data/lib/active_record/relation/from_clause.rb +6 -8
  186. data/lib/active_record/relation/merger.rb +78 -62
  187. data/lib/active_record/relation/predicate_builder.rb +83 -105
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  195. data/lib/active_record/relation/query_attribute.rb +33 -2
  196. data/lib/active_record/relation/query_methods.rb +476 -334
  197. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  198. data/lib/active_record/relation/spawn_methods.rb +8 -8
  199. data/lib/active_record/relation/where_clause.rb +111 -96
  200. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  201. data/lib/active_record/result.rb +69 -40
  202. data/lib/active_record/runtime_registry.rb +5 -3
  203. data/lib/active_record/sanitization.rb +83 -99
  204. data/lib/active_record/schema.rb +7 -14
  205. data/lib/active_record/schema_dumper.rb +71 -69
  206. data/lib/active_record/schema_migration.rb +16 -6
  207. data/lib/active_record/scoping.rb +20 -20
  208. data/lib/active_record/scoping/default.rb +92 -95
  209. data/lib/active_record/scoping/named.rb +47 -27
  210. data/lib/active_record/secure_token.rb +4 -2
  211. data/lib/active_record/serialization.rb +2 -0
  212. data/lib/active_record/statement_cache.rb +63 -28
  213. data/lib/active_record/store.rb +121 -41
  214. data/lib/active_record/suppressor.rb +6 -3
  215. data/lib/active_record/table_metadata.rb +39 -18
  216. data/lib/active_record/tasks/database_tasks.rb +271 -81
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +225 -0
  222. data/lib/active_record/timestamp.rb +70 -36
  223. data/lib/active_record/touch_later.rb +8 -6
  224. data/lib/active_record/transactions.rb +141 -157
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type.rb +23 -18
  227. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  228. data/lib/active_record/type/date.rb +2 -0
  229. data/lib/active_record/type/date_time.rb +2 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  232. data/lib/active_record/type/internal/timezone.rb +2 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +16 -9
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +2 -1
  237. data/lib/active_record/type/type_map.rb +14 -17
  238. data/lib/active_record/type/unsigned_integer.rb +16 -0
  239. data/lib/active_record/type_caster.rb +4 -2
  240. data/lib/active_record/type_caster/connection.rb +17 -12
  241. data/lib/active_record/type_caster/map.rb +5 -4
  242. data/lib/active_record/validations.rb +7 -5
  243. data/lib/active_record/validations/absence.rb +2 -0
  244. data/lib/active_record/validations/associated.rb +4 -3
  245. data/lib/active_record/validations/length.rb +2 -0
  246. data/lib/active_record/validations/presence.rb +4 -2
  247. data/lib/active_record/validations/uniqueness.rb +29 -42
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/arel.rb +62 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +256 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +203 -0
  317. data/lib/arel/visitors/dot.rb +296 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +156 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +158 -0
  323. data/lib/arel/visitors/oracle12.rb +65 -0
  324. data/lib/arel/visitors/postgresql.rb +109 -0
  325. data/lib/arel/visitors/sqlite.rb +38 -0
  326. data/lib/arel/visitors/to_sql.rb +888 -0
  327. data/lib/arel/visitors/visitor.rb +45 -0
  328. data/lib/arel/visitors/where_sql.rb +22 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +7 -5
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  332. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  333. data/lib/rails/generators/active_record/migration.rb +17 -3
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  335. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  336. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  337. data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
  338. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. metadata +137 -52
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  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 -15
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  348. data/lib/active_record/attribute.rb +0 -213
  349. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  350. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/attribute_set/builder.rb +0 -132
  353. data/lib/active_record/collection_cache_key.rb +0 -50
  354. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  355. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  356. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  357. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  358. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  359. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/fixture_set/table_row"
4
+ require "active_record/fixture_set/model_metadata"
5
+
6
+ module ActiveRecord
7
+ class FixtureSet
8
+ class TableRows # :nodoc:
9
+ def initialize(table_name, model_class:, fixtures:, config:)
10
+ @model_class = model_class
11
+
12
+ # track any join tables we need to insert later
13
+ @tables = Hash.new { |h, table| h[table] = [] }
14
+
15
+ # ensure this table is loaded before any HABTM associations
16
+ @tables[table_name] = nil
17
+
18
+ build_table_rows_from(table_name, fixtures, config)
19
+ end
20
+
21
+ attr_reader :tables, :model_class
22
+
23
+ def to_hash
24
+ @tables.transform_values { |rows| rows.map(&:to_hash) }
25
+ end
26
+
27
+ def model_metadata
28
+ @model_metadata ||= ModelMetadata.new(model_class)
29
+ end
30
+
31
+ private
32
+ def build_table_rows_from(table_name, fixtures, config)
33
+ now = config.default_timezone == :utc ? Time.now.utc : Time.now
34
+
35
+ @tables[table_name] = fixtures.map do |label, fixture|
36
+ TableRow.new(
37
+ fixture,
38
+ table_rows: self,
39
+ label: label,
40
+ now: now,
41
+ )
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -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,189 @@ 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] = {} }
421
-
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
442
+ MAX_ID = 2**30 - 1
433
443
 
434
- def self.reset_cache
435
- @@all_cached_fixtures.clear
436
- end
444
+ @@all_cached_fixtures = Hash.new { |h, k| h[k] = {} }
437
445
 
438
- def self.cache_for_connection(connection)
439
- @@all_cached_fixtures[connection]
440
- end
446
+ cattr_accessor :all_loaded_fixtures, default: {}
441
447
 
442
- def self.fixture_is_cached?(connection, table_name)
443
- cache_for_connection(connection)[table_name]
444
- end
448
+ class ClassCache
449
+ def initialize(class_names, config)
450
+ @class_names = class_names.stringify_keys
451
+ @config = config
445
452
 
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
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
451
457
  end
452
- end
453
458
 
454
- def self.cache_fixtures(connection, fixtures_map)
455
- cache_for_connection(connection).update(fixtures_map)
456
- end
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
464
+ end
457
465
 
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
466
+ private
467
+ def insert_class(class_names, name, klass)
468
+ # We only want to deal with AR objects.
469
+ if klass && klass < ActiveRecord::Base
470
+ class_names[name] = klass
471
+ else
472
+ class_names[name] = nil
465
473
  end
466
474
  end
467
- end
468
- end
469
475
 
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
476
+ def default_fixture_model(fs_name, config)
477
+ ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
478
+ end
474
479
  end
475
480
 
476
- cattr_accessor :all_loaded_fixtures
477
- self.all_loaded_fixtures = {}
481
+ class << self
482
+ def default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
483
+ config.pluralize_table_names ?
484
+ fixture_set_name.singularize.camelize :
485
+ fixture_set_name.camelize
486
+ end
478
487
 
479
- class ClassCache
480
- def initialize(class_names, config)
481
- @class_names = class_names.stringify_keys
482
- @config = config
488
+ def default_fixture_table_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
489
+ "#{ config.table_name_prefix }"\
490
+ "#{ fixture_set_name.tr('/', '_') }"\
491
+ "#{ config.table_name_suffix }".to_sym
492
+ end
483
493
 
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) }
494
+ def reset_cache
495
+ @@all_cached_fixtures.clear
486
496
  end
487
497
 
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
- }
498
+ def cache_for_connection(connection)
499
+ @@all_cached_fixtures[connection]
493
500
  end
494
501
 
495
- private
502
+ def fixture_is_cached?(connection, table_name)
503
+ cache_for_connection(connection)[table_name]
504
+ end
496
505
 
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
506
+ def cached_fixtures(connection, keys_to_fetch = nil)
507
+ if keys_to_fetch
508
+ cache_for_connection(connection).values_at(*keys_to_fetch)
501
509
  else
502
- class_names[name] = nil
510
+ cache_for_connection(connection).values
503
511
  end
504
512
  end
505
513
 
506
- def default_fixture_model(fs_name, config)
507
- ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
514
+ def cache_fixtures(connection, fixtures_map)
515
+ cache_for_connection(connection).update(fixtures_map)
516
+ end
517
+
518
+ def instantiate_fixtures(object, fixture_set, load_instances = true)
519
+ return unless load_instances
520
+ fixture_set.each do |fixture_name, fixture|
521
+ object.instance_variable_set "@#{fixture_name}", fixture.find
522
+ rescue FixtureClassNotFound
523
+ nil
524
+ end
525
+ end
526
+
527
+ def instantiate_all_loaded_fixtures(object, load_instances = true)
528
+ all_loaded_fixtures.each_value do |fixture_set|
529
+ instantiate_fixtures(object, fixture_set, load_instances)
530
+ end
508
531
  end
509
- end
510
532
 
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
533
+ def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
534
+ fixture_set_names = Array(fixture_set_names).map(&:to_s)
535
+ class_names = ClassCache.new class_names, config
514
536
 
515
- # FIXME: Apparently JK uses this.
516
- connection = block_given? ? yield : ActiveRecord::Base.connection
537
+ # FIXME: Apparently JK uses this.
538
+ connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
517
539
 
518
- files_to_read = fixture_set_names.reject { |fs_name|
519
- fixture_is_cached?(connection, fs_name)
520
- }
540
+ fixture_files_to_read = fixture_set_names.reject do |fs_name|
541
+ fixture_is_cached?(connection.call, fs_name)
542
+ end
521
543
 
522
- unless files_to_read.empty?
523
- connection.disable_referential_integrity do
524
- fixtures_map = {}
544
+ if fixture_files_to_read.any?
545
+ fixtures_map = read_and_insert(
546
+ fixtures_directory,
547
+ fixture_files_to_read,
548
+ class_names,
549
+ connection,
550
+ )
551
+ cache_fixtures(connection.call, fixtures_map)
552
+ end
553
+ cached_fixtures(connection.call, fixture_set_names)
554
+ end
555
+
556
+ # Returns a consistent, platform-independent identifier for +label+.
557
+ # Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
558
+ def identify(label, column_type = :integer)
559
+ if column_type == :uuid
560
+ Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
561
+ else
562
+ Zlib.crc32(label.to_s) % MAX_ID
563
+ end
564
+ end
525
565
 
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,
566
+ # Superclass for the evaluation contexts used by ERB fixtures.
567
+ def context_class
568
+ @context_class ||= Class.new
569
+ end
570
+
571
+ private
572
+ def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc:
573
+ fixtures_map = {}
574
+ fixture_sets = fixture_files.map do |fixture_set_name|
575
+ klass = class_names[fixture_set_name]
576
+ fixtures_map[fixture_set_name] = new( # ActiveRecord::FixtureSet.new
577
+ nil,
578
+ fixture_set_name,
532
579
  klass,
533
- ::File.join(fixtures_directory, fs_name))
580
+ ::File.join(fixtures_directory, fixture_set_name)
581
+ )
534
582
  end
583
+ update_all_loaded_fixtures(fixtures_map)
535
584
 
536
- update_all_loaded_fixtures fixtures_map
585
+ insert(fixture_sets, connection)
537
586
 
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
587
+ fixtures_map
588
+ end
543
589
 
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
590
+ def insert(fixture_sets, connection) # :nodoc:
591
+ fixture_sets_by_connection = fixture_sets.group_by do |fixture_set|
592
+ if fixture_set.model_class
593
+ fixture_set.model_class.connection
594
+ else
595
+ connection.call
596
+ end
597
+ end
550
598
 
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
599
+ fixture_sets_by_connection.each do |conn, set|
600
+ table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
556
601
 
557
- # Cap primary key sequences to max(pk).
558
- if conn.respond_to?(:reset_pk_sequence!)
559
- conn.reset_pk_sequence!(fs.table_name)
602
+ set.each do |fixture_set|
603
+ fixture_set.table_rows.each do |table, rows|
604
+ table_rows_for_connection[table].unshift(*rows)
560
605
  end
561
606
  end
562
- end
563
607
 
564
- cache_fixtures(connection, fixtures_map)
565
- end
566
- end
567
- cached_fixtures(connection, fixture_set_names)
568
- end
608
+ conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
569
609
 
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
610
+ # Cap primary key sequences to max(pk).
611
+ if conn.respond_to?(:reset_pk_sequence!)
612
+ set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
613
+ end
614
+ end
615
+ end
584
616
 
585
- def self.update_all_loaded_fixtures(fixtures_map) # :nodoc:
586
- all_loaded_fixtures.update(fixtures_map)
617
+ def update_all_loaded_fixtures(fixtures_map) # :nodoc:
618
+ all_loaded_fixtures.update(fixtures_map)
619
+ end
587
620
  end
588
621
 
589
622
  attr_reader :table_name, :name, :fixtures, :model_class, :config
590
623
 
591
- def initialize(connection, name, class_name, path, config = ActiveRecord::Base)
624
+ def initialize(_, name, class_name, path, config = ActiveRecord::Base)
592
625
  @name = name
593
626
  @path = path
594
627
  @config = config
@@ -597,18 +630,14 @@ module ActiveRecord
597
630
 
598
631
  @fixtures = read_fixture_files(path)
599
632
 
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) )
633
+ @table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
605
634
  end
606
635
 
607
636
  def [](x)
608
637
  fixtures[x]
609
638
  end
610
639
 
611
- def []=(k,v)
640
+ def []=(k, v)
612
641
  fixtures[k] = v
613
642
  end
614
643
 
@@ -623,153 +652,18 @@ module ActiveRecord
623
652
  # Returns a hash of rows to be inserted. The key is the table, the value is
624
653
  # a list of rows to insert to that table.
625
654
  def table_rows
626
- now = config.default_timezone == :utc ? Time.now.utc : Time.now
627
-
628
655
  # 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
656
+ fixtures.delete("DEFAULTS")
669
657
 
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
715
-
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
658
+ TableRows.new(
659
+ table_name,
660
+ model_class: model_class,
661
+ fixtures: fixtures,
662
+ config: config,
663
+ ).to_hash
728
664
  end
729
665
 
730
666
  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
-
773
667
  def model_class=(class_name)
774
668
  if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
775
669
  @model_class = class_name
@@ -799,7 +693,6 @@ module ActiveRecord
799
693
  def yaml_file_path(path)
800
694
  "#{path}.yml"
801
695
  end
802
-
803
696
  end
804
697
 
805
698
  class Fixture #:nodoc:
@@ -833,212 +726,9 @@ module ActiveRecord
833
726
  alias :to_hash :fixture
834
727
 
835
728
  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()
729
+ raise FixtureClassNotFound, "No class attached to find." unless model_class
730
+ model_class.unscoped do
731
+ model_class.find(fixture[model_class.primary_key])
1042
732
  end
1043
733
  end
1044
734
  end