activerecord 3.2.6 → 6.0.0

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 (371) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +611 -6417
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +44 -47
  5. data/examples/performance.rb +79 -71
  6. data/examples/simple.rb +6 -5
  7. data/lib/active_record/aggregations.rb +268 -238
  8. data/lib/active_record/association_relation.rb +40 -0
  9. data/lib/active_record/associations/alias_tracker.rb +47 -42
  10. data/lib/active_record/associations/association.rb +173 -81
  11. data/lib/active_record/associations/association_scope.rb +124 -92
  12. data/lib/active_record/associations/belongs_to_association.rb +83 -38
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +11 -9
  14. data/lib/active_record/associations/builder/association.rb +113 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +105 -60
  16. data/lib/active_record/associations/builder/collection_association.rb +53 -56
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +98 -41
  18. data/lib/active_record/associations/builder/has_many.rb +11 -63
  19. data/lib/active_record/associations/builder/has_one.rb +47 -45
  20. data/lib/active_record/associations/builder/singular_association.rb +30 -18
  21. data/lib/active_record/associations/collection_association.rb +217 -295
  22. data/lib/active_record/associations/collection_proxy.rb +1074 -77
  23. data/lib/active_record/associations/foreign_association.rb +20 -0
  24. data/lib/active_record/associations/has_many_association.rb +78 -50
  25. data/lib/active_record/associations/has_many_through_association.rb +99 -61
  26. data/lib/active_record/associations/has_one_association.rb +75 -30
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +45 -119
  29. data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
  30. data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
  31. data/lib/active_record/associations/join_dependency.rb +208 -164
  32. data/lib/active_record/associations/preloader/association.rb +93 -87
  33. data/lib/active_record/associations/preloader/through_association.rb +87 -38
  34. data/lib/active_record/associations/preloader.rb +134 -110
  35. data/lib/active_record/associations/singular_association.rb +19 -24
  36. data/lib/active_record/associations/through_association.rb +61 -27
  37. data/lib/active_record/associations.rb +1766 -1505
  38. data/lib/active_record/attribute_assignment.rb +57 -193
  39. data/lib/active_record/attribute_decorators.rb +90 -0
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +58 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +187 -67
  42. data/lib/active_record/attribute_methods/primary_key.rb +100 -78
  43. data/lib/active_record/attribute_methods/query.rb +10 -8
  44. data/lib/active_record/attribute_methods/read.rb +29 -118
  45. data/lib/active_record/attribute_methods/serialization.rb +60 -72
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -42
  47. data/lib/active_record/attribute_methods/write.rb +36 -44
  48. data/lib/active_record/attribute_methods.rb +306 -161
  49. data/lib/active_record/attributes.rb +279 -0
  50. data/lib/active_record/autosave_association.rb +324 -238
  51. data/lib/active_record/base.rb +114 -507
  52. data/lib/active_record/callbacks.rb +147 -83
  53. data/lib/active_record/coders/json.rb +15 -0
  54. data/lib/active_record/coders/yaml_column.rb +32 -23
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +962 -279
  56. data/lib/active_record/connection_adapters/abstract/database_limits.rb +32 -5
  57. data/lib/active_record/connection_adapters/abstract/database_statements.rb +331 -209
  58. data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -23
  59. data/lib/active_record/connection_adapters/abstract/quoting.rb +201 -65
  60. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +510 -289
  63. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1182 -313
  65. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  66. data/lib/active_record/connection_adapters/abstract_adapter.rb +585 -120
  67. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +610 -463
  68. data/lib/active_record/connection_adapters/column.rb +58 -233
  69. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  70. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  71. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
  73. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  74. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  79. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +75 -207
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  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 +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  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 +41 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +695 -1052
  116. data/lib/active_record/connection_adapters/schema_cache.rb +115 -24
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +528 -26
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +267 -0
  128. data/lib/active_record/core.rb +599 -0
  129. data/lib/active_record/counter_cache.rb +177 -103
  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 +107 -64
  136. data/lib/active_record/enum.rb +274 -0
  137. data/lib/active_record/errors.rb +254 -61
  138. data/lib/active_record/explain.rb +35 -70
  139. data/lib/active_record/explain_registry.rb +32 -0
  140. data/lib/active_record/explain_subscriber.rb +18 -8
  141. data/lib/active_record/fixture_set/file.rb +82 -0
  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 +291 -475
  147. data/lib/active_record/gem_version.rb +17 -0
  148. data/lib/active_record/inheritance.rb +219 -100
  149. data/lib/active_record/insert_all.rb +179 -0
  150. data/lib/active_record/integration.rb +175 -17
  151. data/lib/active_record/internal_metadata.rb +53 -0
  152. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  153. data/lib/active_record/locale/en.yml +9 -1
  154. data/lib/active_record/locking/optimistic.rb +106 -92
  155. data/lib/active_record/locking/pessimistic.rb +23 -11
  156. data/lib/active_record/log_subscriber.rb +80 -30
  157. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  158. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  159. data/lib/active_record/middleware/database_selector.rb +75 -0
  160. data/lib/active_record/migration/command_recorder.rb +235 -56
  161. data/lib/active_record/migration/compatibility.rb +244 -0
  162. data/lib/active_record/migration/join_table.rb +17 -0
  163. data/lib/active_record/migration.rb +917 -301
  164. data/lib/active_record/model_schema.rb +351 -175
  165. data/lib/active_record/nested_attributes.rb +366 -235
  166. data/lib/active_record/no_touching.rb +65 -0
  167. data/lib/active_record/null_relation.rb +68 -0
  168. data/lib/active_record/persistence.rb +761 -166
  169. data/lib/active_record/query_cache.rb +22 -44
  170. data/lib/active_record/querying.rb +55 -31
  171. data/lib/active_record/railtie.rb +185 -47
  172. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  173. data/lib/active_record/railties/console_sandbox.rb +5 -4
  174. data/lib/active_record/railties/controller_runtime.rb +35 -33
  175. data/lib/active_record/railties/databases.rake +366 -463
  176. data/lib/active_record/readonly_attributes.rb +4 -6
  177. data/lib/active_record/reflection.rb +736 -228
  178. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  179. data/lib/active_record/relation/batches.rb +252 -52
  180. data/lib/active_record/relation/calculations.rb +340 -270
  181. data/lib/active_record/relation/delegation.rb +117 -36
  182. data/lib/active_record/relation/finder_methods.rb +439 -286
  183. data/lib/active_record/relation/from_clause.rb +26 -0
  184. data/lib/active_record/relation/merger.rb +184 -0
  185. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  186. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  187. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  188. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  189. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  190. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  191. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder.rb +131 -39
  193. data/lib/active_record/relation/query_attribute.rb +50 -0
  194. data/lib/active_record/relation/query_methods.rb +1163 -221
  195. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  196. data/lib/active_record/relation/spawn_methods.rb +49 -120
  197. data/lib/active_record/relation/where_clause.rb +190 -0
  198. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  199. data/lib/active_record/relation.rb +671 -349
  200. data/lib/active_record/result.rb +149 -15
  201. data/lib/active_record/runtime_registry.rb +24 -0
  202. data/lib/active_record/sanitization.rb +153 -133
  203. data/lib/active_record/schema.rb +22 -19
  204. data/lib/active_record/schema_dumper.rb +178 -112
  205. data/lib/active_record/schema_migration.rb +60 -0
  206. data/lib/active_record/scoping/default.rb +107 -98
  207. data/lib/active_record/scoping/named.rb +130 -115
  208. data/lib/active_record/scoping.rb +77 -123
  209. data/lib/active_record/secure_token.rb +40 -0
  210. data/lib/active_record/serialization.rb +10 -6
  211. data/lib/active_record/statement_cache.rb +148 -0
  212. data/lib/active_record/store.rb +256 -16
  213. data/lib/active_record/suppressor.rb +61 -0
  214. data/lib/active_record/table_metadata.rb +75 -0
  215. data/lib/active_record/tasks/database_tasks.rb +506 -0
  216. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  217. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  218. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  219. data/lib/active_record/test_databases.rb +23 -0
  220. data/lib/active_record/test_fixtures.rb +224 -0
  221. data/lib/active_record/timestamp.rb +93 -39
  222. data/lib/active_record/touch_later.rb +66 -0
  223. data/lib/active_record/transactions.rb +260 -129
  224. data/lib/active_record/translation.rb +3 -1
  225. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  226. data/lib/active_record/type/date.rb +9 -0
  227. data/lib/active_record/type/date_time.rb +9 -0
  228. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  229. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  230. data/lib/active_record/type/internal/timezone.rb +17 -0
  231. data/lib/active_record/type/json.rb +30 -0
  232. data/lib/active_record/type/serialized.rb +71 -0
  233. data/lib/active_record/type/text.rb +11 -0
  234. data/lib/active_record/type/time.rb +21 -0
  235. data/lib/active_record/type/type_map.rb +62 -0
  236. data/lib/active_record/type/unsigned_integer.rb +17 -0
  237. data/lib/active_record/type.rb +78 -0
  238. data/lib/active_record/type_caster/connection.rb +34 -0
  239. data/lib/active_record/type_caster/map.rb +20 -0
  240. data/lib/active_record/type_caster.rb +9 -0
  241. data/lib/active_record/validations/absence.rb +25 -0
  242. data/lib/active_record/validations/associated.rb +35 -18
  243. data/lib/active_record/validations/length.rb +26 -0
  244. data/lib/active_record/validations/presence.rb +68 -0
  245. data/lib/active_record/validations/uniqueness.rb +123 -77
  246. data/lib/active_record/validations.rb +54 -43
  247. data/lib/active_record/version.rb +7 -7
  248. data/lib/active_record.rb +97 -49
  249. data/lib/arel/alias_predication.rb +9 -0
  250. data/lib/arel/attributes/attribute.rb +37 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/collectors/bind.rb +24 -0
  253. data/lib/arel/collectors/composite.rb +31 -0
  254. data/lib/arel/collectors/plain_string.rb +20 -0
  255. data/lib/arel/collectors/sql_string.rb +20 -0
  256. data/lib/arel/collectors/substitute_binds.rb +28 -0
  257. data/lib/arel/crud.rb +42 -0
  258. data/lib/arel/delete_manager.rb +18 -0
  259. data/lib/arel/errors.rb +9 -0
  260. data/lib/arel/expressions.rb +29 -0
  261. data/lib/arel/factory_methods.rb +49 -0
  262. data/lib/arel/insert_manager.rb +49 -0
  263. data/lib/arel/math.rb +45 -0
  264. data/lib/arel/nodes/and.rb +32 -0
  265. data/lib/arel/nodes/ascending.rb +23 -0
  266. data/lib/arel/nodes/binary.rb +52 -0
  267. data/lib/arel/nodes/bind_param.rb +36 -0
  268. data/lib/arel/nodes/case.rb +55 -0
  269. data/lib/arel/nodes/casted.rb +50 -0
  270. data/lib/arel/nodes/comment.rb +29 -0
  271. data/lib/arel/nodes/count.rb +12 -0
  272. data/lib/arel/nodes/delete_statement.rb +45 -0
  273. data/lib/arel/nodes/descending.rb +23 -0
  274. data/lib/arel/nodes/equality.rb +18 -0
  275. data/lib/arel/nodes/extract.rb +24 -0
  276. data/lib/arel/nodes/false.rb +16 -0
  277. data/lib/arel/nodes/full_outer_join.rb +8 -0
  278. data/lib/arel/nodes/function.rb +44 -0
  279. data/lib/arel/nodes/grouping.rb +8 -0
  280. data/lib/arel/nodes/in.rb +8 -0
  281. data/lib/arel/nodes/infix_operation.rb +80 -0
  282. data/lib/arel/nodes/inner_join.rb +8 -0
  283. data/lib/arel/nodes/insert_statement.rb +37 -0
  284. data/lib/arel/nodes/join_source.rb +20 -0
  285. data/lib/arel/nodes/matches.rb +18 -0
  286. data/lib/arel/nodes/named_function.rb +23 -0
  287. data/lib/arel/nodes/node.rb +50 -0
  288. data/lib/arel/nodes/node_expression.rb +13 -0
  289. data/lib/arel/nodes/outer_join.rb +8 -0
  290. data/lib/arel/nodes/over.rb +15 -0
  291. data/lib/arel/nodes/regexp.rb +16 -0
  292. data/lib/arel/nodes/right_outer_join.rb +8 -0
  293. data/lib/arel/nodes/select_core.rb +67 -0
  294. data/lib/arel/nodes/select_statement.rb +41 -0
  295. data/lib/arel/nodes/sql_literal.rb +16 -0
  296. data/lib/arel/nodes/string_join.rb +11 -0
  297. data/lib/arel/nodes/table_alias.rb +27 -0
  298. data/lib/arel/nodes/terminal.rb +16 -0
  299. data/lib/arel/nodes/true.rb +16 -0
  300. data/lib/arel/nodes/unary.rb +45 -0
  301. data/lib/arel/nodes/unary_operation.rb +20 -0
  302. data/lib/arel/nodes/unqualified_column.rb +22 -0
  303. data/lib/arel/nodes/update_statement.rb +41 -0
  304. data/lib/arel/nodes/values_list.rb +9 -0
  305. data/lib/arel/nodes/window.rb +126 -0
  306. data/lib/arel/nodes/with.rb +11 -0
  307. data/lib/arel/nodes.rb +68 -0
  308. data/lib/arel/order_predications.rb +13 -0
  309. data/lib/arel/predications.rb +257 -0
  310. data/lib/arel/select_manager.rb +271 -0
  311. data/lib/arel/table.rb +110 -0
  312. data/lib/arel/tree_manager.rb +72 -0
  313. data/lib/arel/update_manager.rb +34 -0
  314. data/lib/arel/visitors/depth_first.rb +204 -0
  315. data/lib/arel/visitors/dot.rb +297 -0
  316. data/lib/arel/visitors/ibm_db.rb +34 -0
  317. data/lib/arel/visitors/informix.rb +62 -0
  318. data/lib/arel/visitors/mssql.rb +157 -0
  319. data/lib/arel/visitors/mysql.rb +83 -0
  320. data/lib/arel/visitors/oracle.rb +159 -0
  321. data/lib/arel/visitors/oracle12.rb +66 -0
  322. data/lib/arel/visitors/postgresql.rb +110 -0
  323. data/lib/arel/visitors/sqlite.rb +39 -0
  324. data/lib/arel/visitors/to_sql.rb +889 -0
  325. data/lib/arel/visitors/visitor.rb +46 -0
  326. data/lib/arel/visitors/where_sql.rb +23 -0
  327. data/lib/arel/visitors.rb +20 -0
  328. data/lib/arel/window_predications.rb +9 -0
  329. data/lib/arel.rb +51 -0
  330. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  331. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  332. data/lib/rails/generators/active_record/migration/migration_generator.rb +59 -9
  333. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  334. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  335. data/lib/rails/generators/active_record/migration.rb +41 -8
  336. data/lib/rails/generators/active_record/model/model_generator.rb +24 -22
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
  339. data/lib/rails/generators/active_record.rb +10 -16
  340. metadata +285 -149
  341. data/examples/associations.png +0 -0
  342. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  343. data/lib/active_record/associations/join_helper.rb +0 -55
  344. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  345. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  346. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  347. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  348. data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
  349. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  350. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  351. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  352. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  353. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -188
  354. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -426
  355. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -579
  356. data/lib/active_record/dynamic_finder_match.rb +0 -68
  357. data/lib/active_record/dynamic_scope_match.rb +0 -23
  358. data/lib/active_record/fixtures/file.rb +0 -65
  359. data/lib/active_record/identity_map.rb +0 -162
  360. data/lib/active_record/observer.rb +0 -121
  361. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  362. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  363. data/lib/active_record/session_store.rb +0 -358
  364. data/lib/active_record/test_case.rb +0 -73
  365. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
  366. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  367. data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
  368. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  369. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  370. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  371. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,36 +1,30 @@
1
- require 'erb'
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"
2
14
 
3
- begin
4
- require 'psych'
5
- rescue LoadError
6
- end
7
-
8
- require 'yaml'
9
- require 'zlib'
10
- require 'active_support/dependencies'
11
- require 'active_support/core_ext/array/wrap'
12
- require 'active_support/core_ext/object/blank'
13
- require 'active_support/core_ext/logger'
14
- require 'active_support/ordered_hash'
15
- require 'active_record/fixtures/file'
16
-
17
- if defined? ActiveRecord
15
+ module ActiveRecord
18
16
  class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
19
17
  end
20
- else
21
- class FixtureClassNotFound < StandardError #:nodoc:
22
- end
23
- end
24
18
 
25
- module ActiveRecord
26
19
  # \Fixtures are a way of organizing data that you want to test against; in short, sample data.
27
20
  #
28
21
  # They are stored in YAML files, one file per model, which are placed in the directory
29
22
  # appointed by <tt>ActiveSupport::TestCase.fixture_path=(path)</tt> (this is automatically
30
23
  # configured for Rails, so you can just put your files in <tt><your-rails-app>/test/fixtures/</tt>).
31
- # The fixture file ends with the <tt>.yml</tt> file extension (Rails example:
32
- # <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>). The format of a fixture file looks
33
- # like this:
24
+ # The fixture file ends with the +.yml+ file extension, for example:
25
+ # <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
26
+ #
27
+ # The format of a fixture file looks like this:
34
28
  #
35
29
  # rubyonrails:
36
30
  # id: 1
@@ -46,7 +40,7 @@ module ActiveRecord
46
40
  # is followed by an indented list of key/value pairs in the "key: value" format. Records are
47
41
  # separated by a blank line for your viewing pleasure.
48
42
  #
49
- # Note that fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
43
+ # Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
50
44
  # See http://yaml.org/type/omap.html
51
45
  # for the specification. You will need ordered fixtures when you have foreign key constraints
52
46
  # on keys in the same table. This is commonly needed for tree structures. Example:
@@ -74,20 +68,39 @@ module ActiveRecord
74
68
  # end
75
69
  # end
76
70
  #
77
- # By default, <tt>test_helper.rb</tt> will load all of your fixtures into your test database,
78
- # so this test will succeed.
71
+ # By default, +test_helper.rb+ will load all of your fixtures into your test
72
+ # database, so this test will succeed.
79
73
  #
80
- # 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
81
75
  # test. To ensure consistent data, the environment deletes the fixtures before running the load.
82
76
  #
83
77
  # In addition to being available in the database, the fixture's data may also be accessed by
84
- # using a special dynamic method, which has the same name as the model, and accepts the
85
- # name of the fixture to instantiate:
78
+ # using a special dynamic method, which has the same name as the model.
79
+ #
80
+ # Passing in a fixture name to this dynamic method returns the fixture matching this name:
86
81
  #
87
- # test "find" do
82
+ # test "find one" do
88
83
  # assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
89
84
  # end
90
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
+ #
91
104
  # Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the
92
105
  # following tests:
93
106
  #
@@ -96,11 +109,11 @@ module ActiveRecord
96
109
  # end
97
110
  #
98
111
  # test "find_alt_method_2" do
99
- # assert_equal "Ruby on Rails", @rubyonrails.news
112
+ # assert_equal "Ruby on Rails", @rubyonrails.name
100
113
  # end
101
114
  #
102
- # In order to use these methods to access fixtured data within your testcases, you must specify one of the
103
- # following in your <tt>ActiveSupport::TestCase</tt>-derived class:
115
+ # In order to use these methods to access fixtured data within your test cases, you must specify one of the
116
+ # following in your ActiveSupport::TestCase-derived class:
104
117
  #
105
118
  # - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
106
119
  # self.use_instantiated_fixtures = true
@@ -114,14 +127,14 @@ module ActiveRecord
114
127
  #
115
128
  # = Dynamic fixtures with ERB
116
129
  #
117
- # 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.
118
131
  # In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
119
132
  # testing, like:
120
133
  #
121
134
  # <% 1.upto(1000) do |i| %>
122
135
  # fix_<%= i %>:
123
136
  # id: <%= i %>
124
- # name: guy_<%= 1 %>
137
+ # name: guy_<%= i %>
125
138
  # <% end %>
126
139
  #
127
140
  # This will create 1000 very simple fixtures.
@@ -133,34 +146,51 @@ module ActiveRecord
133
146
  # perhaps you should reexamine whether your application is properly testable. Hence, dynamic values
134
147
  # in fixtures are to be considered a code smell.
135
148
  #
136
- # = Transactional Fixtures
149
+ # Helper methods defined in a fixture will not be available in other fixtures, to prevent against
150
+ # unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module
151
+ # that is included in ActiveRecord::FixtureSet.context_class.
152
+ #
153
+ # - define a helper method in <tt>test_helper.rb</tt>
154
+ # module FixtureFileHelpers
155
+ # def file_sha(path)
156
+ # Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
157
+ # end
158
+ # end
159
+ # ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
160
+ #
161
+ # - use the helper method in a fixture
162
+ # photo:
163
+ # name: kitten.png
164
+ # sha: <%= file_sha 'files/kitten.png' %>
165
+ #
166
+ # = Transactional Tests
137
167
  #
138
168
  # Test cases can use begin+rollback to isolate their changes to the database instead of having to
139
169
  # delete+insert for every test case.
140
170
  #
141
171
  # class FooTest < ActiveSupport::TestCase
142
- # self.use_transactional_fixtures = true
172
+ # self.use_transactional_tests = true
143
173
  #
144
174
  # test "godzilla" do
145
- # assert !Foo.all.empty?
175
+ # assert_not_empty Foo.all
146
176
  # Foo.destroy_all
147
- # assert Foo.all.empty?
177
+ # assert_empty Foo.all
148
178
  # end
149
179
  #
150
180
  # test "godzilla aftermath" do
151
- # assert !Foo.all.empty?
181
+ # assert_not_empty Foo.all
152
182
  # end
153
183
  # end
154
184
  #
155
- # If you preload your test database with all fixture data (probably in the rake task) and use
156
- # transactional fixtures, 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
157
187
  # all the data's already there and every case rolls back its changes.
158
188
  #
159
189
  # In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to
160
190
  # true. This will provide access to fixture data for every table that has been loaded through
161
191
  # fixtures (depending on the value of +use_instantiated_fixtures+).
162
192
  #
163
- # When *not* to use transactional fixtures:
193
+ # When *not* to use transactional tests:
164
194
  #
165
195
  # 1. You're testing whether a transaction works correctly. Nested transactions don't commit until
166
196
  # all parent transactions commit, particularly, the fixtures transaction which is begun in setup
@@ -176,6 +206,9 @@ module ActiveRecord
176
206
  # * Stable, autogenerated IDs
177
207
  # * Label references for associations (belongs_to, has_one, has_many)
178
208
  # * HABTM associations as inline lists
209
+ #
210
+ # There are some more advanced features available even if the id is specified:
211
+ #
179
212
  # * Autofilled timestamp columns
180
213
  # * Fixture label interpolation
181
214
  # * Support for YAML defaults
@@ -262,7 +295,7 @@ module ActiveRecord
262
295
  #
263
296
  # ### in fruit.rb
264
297
  #
265
- # belongs_to :eater, :polymorphic => true
298
+ # belongs_to :eater, polymorphic: true
266
299
  #
267
300
  # ### in fruits.yml
268
301
  #
@@ -358,201 +391,255 @@ module ActiveRecord
358
391
  # geeksomnia:
359
392
  # name: Geeksomnia's Account
360
393
  # subdomain: $LABEL
394
+ # email: $LABEL@email.com
361
395
  #
362
396
  # Also, sometimes (like when porting older join table fixtures) you'll need
363
397
  # to be able to get a hold of the identifier for a given label. ERB
364
398
  # to the rescue:
365
399
  #
366
400
  # george_reginald:
367
- # monkey_id: <%= ActiveRecord::Fixtures.identify(:reginald) %>
368
- # pirate_id: <%= ActiveRecord::Fixtures.identify(:george) %>
401
+ # monkey_id: <%= ActiveRecord::FixtureSet.identify(:reginald) %>
402
+ # pirate_id: <%= ActiveRecord::FixtureSet.identify(:george) %>
369
403
  #
370
404
  # == Support for YAML defaults
371
405
  #
372
- # You probably already know how to use YAML to set and reuse defaults in
373
- # your <tt>database.yml</tt> file. You can use the same technique in your fixtures:
406
+ # You can set and reuse defaults in your fixtures YAML file.
407
+ # This is the same technique used in the +database.yml+ file to specify
408
+ # defaults:
374
409
  #
375
410
  # DEFAULTS: &DEFAULTS
376
411
  # created_on: <%= 3.weeks.ago.to_s(:db) %>
377
412
  #
378
413
  # first:
379
414
  # name: Smurf
380
- # *DEFAULTS
415
+ # <<: *DEFAULTS
381
416
  #
382
417
  # second:
383
418
  # name: Fraggle
384
- # *DEFAULTS
419
+ # <<: *DEFAULTS
385
420
  #
386
421
  # Any fixture labeled "DEFAULTS" is safely ignored.
387
- class Fixtures
388
- MAX_ID = 2 ** 30 - 1
422
+ #
423
+ # == Configure the fixture model class
424
+ #
425
+ # It's possible to set the fixture's model class directly in the YAML file.
426
+ # This is helpful when fixtures are loaded outside tests and
427
+ # +set_fixture_class+ is not available (e.g.
428
+ # when running <tt>rails db:fixtures:load</tt>).
429
+ #
430
+ # _fixture:
431
+ # model_class: User
432
+ # david:
433
+ # name: David
434
+ #
435
+ # Any fixtures labeled "_fixture" are safely ignored.
436
+ class FixtureSet
437
+ #--
438
+ # An instance of FixtureSet is normally stored in a single YAML file and
439
+ # possibly in a folder with the same name.
440
+ #++
389
441
 
390
- @@all_cached_fixtures = Hash.new { |h,k| h[k] = {} }
442
+ MAX_ID = 2**30 - 1
391
443
 
392
- def self.find_table_name(table_name) # :nodoc:
393
- ActiveRecord::Base.pluralize_table_names ?
394
- table_name.to_s.singularize.camelize :
395
- table_name.to_s.camelize
396
- end
444
+ @@all_cached_fixtures = Hash.new { |h, k| h[k] = {} }
397
445
 
398
- def self.reset_cache
399
- @@all_cached_fixtures.clear
400
- end
446
+ cattr_accessor :all_loaded_fixtures, default: {}
401
447
 
402
- def self.cache_for_connection(connection)
403
- @@all_cached_fixtures[connection]
404
- end
448
+ class ClassCache
449
+ def initialize(class_names, config)
450
+ @class_names = class_names.stringify_keys
451
+ @config = config
405
452
 
406
- def self.fixture_is_cached?(connection, table_name)
407
- cache_for_connection(connection)[table_name]
408
- 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
409
458
 
410
- def self.cached_fixtures(connection, keys_to_fetch = nil)
411
- if keys_to_fetch
412
- cache_for_connection(connection).values_at(*keys_to_fetch)
413
- else
414
- 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
415
464
  end
416
- end
417
465
 
418
- def self.cache_fixtures(connection, fixtures_map)
419
- cache_for_connection(connection).update(fixtures_map)
420
- end
466
+ private
421
467
 
422
- #--
423
- # TODO:NOTE: in the next version, the __with_new_arity suffix and
424
- # the method with the old arity will be removed.
425
- #++
426
- def self.instantiate_fixtures__with_new_arity(object, fixture_set, load_instances = true) # :nodoc:
427
- if load_instances
428
- fixture_set.each do |fixture_name, fixture|
429
- begin
430
- object.instance_variable_set "@#{fixture_name}", fixture.find
431
- rescue FixtureClassNotFound
432
- 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
433
474
  end
434
475
  end
435
- end
476
+
477
+ def default_fixture_model(fs_name, config)
478
+ ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
479
+ end
436
480
  end
437
481
 
438
- # The use with parameters <tt>(object, fixture_set_name, fixture_set, load_instances = true)</tt> is deprecated, +fixture_set_name+ parameter is not used.
439
- # Use as:
440
- #
441
- # instantiate_fixtures(object, fixture_set, load_instances = true)
442
- def self.instantiate_fixtures(object, fixture_set, load_instances = true, rails_3_2_compatibility_argument = true)
443
- unless load_instances == true || load_instances == false
444
- ActiveSupport::Deprecation.warn(
445
- "ActiveRecord::Fixtures.instantiate_fixtures with parameters (object, fixture_set_name, fixture_set, load_instances = true) is deprecated and shall be removed from future releases. Use it with parameters (object, fixture_set, load_instances = true) instead (skip fixture_set_name).",
446
- caller)
447
- fixture_set = load_instances
448
- load_instances = rails_3_2_compatibility_argument
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
449
487
  end
450
- instantiate_fixtures__with_new_arity(object, fixture_set, load_instances)
451
- end
452
488
 
453
- def self.instantiate_all_loaded_fixtures(object, load_instances = true)
454
- all_loaded_fixtures.each_value do |fixture_set|
455
- ActiveRecord::Fixtures.instantiate_fixtures(object, fixture_set, load_instances)
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
494
+
495
+ def reset_cache
496
+ @@all_cached_fixtures.clear
456
497
  end
457
- end
458
498
 
459
- cattr_accessor :all_loaded_fixtures
460
- self.all_loaded_fixtures = {}
499
+ def cache_for_connection(connection)
500
+ @@all_cached_fixtures[connection]
501
+ end
461
502
 
462
- def self.create_fixtures(fixtures_directory, table_names, class_names = {})
463
- table_names = [table_names].flatten.map { |n| n.to_s }
464
- table_names.each { |n|
465
- class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/')
466
- }
503
+ def fixture_is_cached?(connection, table_name)
504
+ cache_for_connection(connection)[table_name]
505
+ end
467
506
 
468
- # FIXME: Apparently JK uses this.
469
- connection = block_given? ? yield : ActiveRecord::Base.connection
507
+ def cached_fixtures(connection, keys_to_fetch = nil)
508
+ if keys_to_fetch
509
+ cache_for_connection(connection).values_at(*keys_to_fetch)
510
+ else
511
+ cache_for_connection(connection).values
512
+ end
513
+ end
470
514
 
471
- files_to_read = table_names.reject { |table_name|
472
- fixture_is_cached?(connection, table_name)
473
- }
515
+ def cache_fixtures(connection, fixtures_map)
516
+ cache_for_connection(connection).update(fixtures_map)
517
+ end
474
518
 
475
- unless files_to_read.empty?
476
- connection.disable_referential_integrity do
477
- fixtures_map = {}
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
527
+
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
478
533
 
479
- fixture_files = files_to_read.map do |path|
480
- table_name = path.tr '/', '_'
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
537
+
538
+ # FIXME: Apparently JK uses this.
539
+ connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
540
+
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
481
571
 
482
- fixtures_map[path] = ActiveRecord::Fixtures.new(
483
- connection,
484
- table_name,
485
- class_names[table_name.to_sym] || table_name.classify,
486
- ::File.join(fixtures_directory, path))
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,
581
+ klass,
582
+ ::File.join(fixtures_directory, fixture_set_name)
583
+ )
487
584
  end
585
+ update_all_loaded_fixtures(fixtures_map)
488
586
 
489
- all_loaded_fixtures.update(fixtures_map)
587
+ insert(fixture_sets, connection)
490
588
 
491
- connection.transaction(:requires_new => true) do
492
- fixture_files.each do |ff|
493
- conn = ff.model_class.respond_to?(:connection) ? ff.model_class.connection : connection
494
- table_rows = ff.table_rows
589
+ fixtures_map
590
+ end
495
591
 
496
- table_rows.keys.each do |table|
497
- conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
498
- 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
600
+
601
+ fixture_sets_by_connection.each do |conn, set|
602
+ table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
499
603
 
500
- table_rows.each do |table_name,rows|
501
- rows.each do |row|
502
- conn.insert_fixture(row, table_name)
503
- end
604
+ set.each do |fixture_set|
605
+ fixture_set.table_rows.each do |table, rows|
606
+ table_rows_for_connection[table].unshift(*rows)
504
607
  end
505
608
  end
506
609
 
610
+ conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
611
+
507
612
  # Cap primary key sequences to max(pk).
508
- if connection.respond_to?(:reset_pk_sequence!)
509
- table_names.each do |table_name|
510
- connection.reset_pk_sequence!(table_name.tr('/', '_'))
511
- end
613
+ if conn.respond_to?(:reset_pk_sequence!)
614
+ set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
512
615
  end
513
616
  end
617
+ end
514
618
 
515
- cache_fixtures(connection, fixtures_map)
619
+ def update_all_loaded_fixtures(fixtures_map) # :nodoc:
620
+ all_loaded_fixtures.update(fixtures_map)
516
621
  end
517
- end
518
- cached_fixtures(connection, table_names)
519
622
  end
520
623
 
521
- # Returns a consistent, platform-independent identifier for +label+.
522
- # Identifiers are positive integers less than 2^32.
523
- def self.identify(label)
524
- Zlib.crc32(label.to_s) % MAX_ID
525
- end
624
+ attr_reader :table_name, :name, :fixtures, :model_class, :config
526
625
 
527
- attr_reader :table_name, :name, :fixtures, :model_class
528
-
529
- def initialize(connection, table_name, class_name, fixture_path)
530
- @connection = connection
531
- @table_name = table_name
532
- @fixture_path = fixture_path
533
- @name = table_name # preserve fixture base name
534
- @class_name = class_name
535
-
536
- @fixtures = ActiveSupport::OrderedHash.new
537
- @table_name = "#{ActiveRecord::Base.table_name_prefix}#{@table_name}#{ActiveRecord::Base.table_name_suffix}"
538
-
539
- # Should be an AR::Base type class
540
- if class_name.is_a?(Class)
541
- @table_name = class_name.table_name
542
- @connection = class_name.connection
543
- @model_class = class_name
544
- else
545
- @model_class = class_name.constantize rescue nil
546
- end
626
+ def initialize(_, name, class_name, path, config = ActiveRecord::Base)
627
+ @name = name
628
+ @path = path
629
+ @config = config
630
+
631
+ self.model_class = class_name
632
+
633
+ @fixtures = read_fixture_files(path)
547
634
 
548
- read_fixture_files
635
+ @table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
549
636
  end
550
637
 
551
638
  def [](x)
552
639
  fixtures[x]
553
640
  end
554
641
 
555
- def []=(k,v)
642
+ def []=(k, v)
556
643
  fixtures[k] = v
557
644
  end
558
645
 
@@ -564,120 +651,51 @@ module ActiveRecord
564
651
  fixtures.size
565
652
  end
566
653
 
567
- # Return a hash of rows to be inserted. The key is the table, the value is
654
+ # Returns a hash of rows to be inserted. The key is the table, the value is
568
655
  # a list of rows to insert to that table.
569
656
  def table_rows
570
- now = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
571
- now = now.to_s(:db)
572
-
573
657
  # allow a standard key to be used for doing defaults in YAML
574
- fixtures.delete('DEFAULTS')
575
-
576
- # track any join tables we need to insert later
577
- rows = Hash.new { |h,table| h[table] = [] }
578
-
579
- rows[table_name] = fixtures.map do |label, fixture|
580
- row = fixture.to_hash
581
-
582
- if model_class && model_class < ActiveRecord::Base
583
- # fill in timestamp columns if they aren't specified and the model is set to record_timestamps
584
- if model_class.record_timestamps
585
- timestamp_column_names.each do |name|
586
- row[name] = now unless row.key?(name)
587
- end
588
- end
589
-
590
- # interpolate the fixture label
591
- row.each do |key, value|
592
- row[key] = label if value == "$LABEL"
593
- end
594
-
595
- # generate a primary key if necessary
596
- if has_primary_key_column? && !row.include?(primary_key_name)
597
- row[primary_key_name] = ActiveRecord::Fixtures.identify(label)
598
- end
599
-
600
- # If STI is used, find the correct subclass for association reflection
601
- reflection_class =
602
- if row.include?(inheritance_column_name)
603
- row[inheritance_column_name].constantize rescue model_class
604
- else
605
- model_class
606
- end
607
-
608
- reflection_class.reflect_on_all_associations.each do |association|
609
- case association.macro
610
- when :belongs_to
611
- # Do not replace association name with association foreign key if they are named the same
612
- fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
613
-
614
- if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
615
- if association.options[:polymorphic] && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
616
- # support polymorphic belongs_to as "label (Type)"
617
- row[association.foreign_type] = $1
618
- end
619
-
620
- row[fk_name] = ActiveRecord::Fixtures.identify(value)
621
- end
622
- when :has_and_belongs_to_many
623
- if (targets = row.delete(association.name.to_s))
624
- targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
625
- table_name = association.options[:join_table]
626
- rows[table_name].concat targets.map { |target|
627
- { association.foreign_key => row[primary_key_name],
628
- association.association_foreign_key => ActiveRecord::Fixtures.identify(target) }
629
- }
630
- end
631
- end
632
- end
633
- end
634
-
635
- row
636
- end
637
- rows
658
+ fixtures.delete("DEFAULTS")
659
+
660
+ TableRows.new(
661
+ table_name,
662
+ model_class: model_class,
663
+ fixtures: fixtures,
664
+ config: config,
665
+ ).to_hash
638
666
  end
639
667
 
640
668
  private
641
- def primary_key_name
642
- @primary_key_name ||= model_class && model_class.primary_key
643
- end
644
-
645
- def has_primary_key_column?
646
- @has_primary_key_column ||= primary_key_name &&
647
- model_class.columns.any? { |c| c.name == primary_key_name }
648
- end
649
-
650
- def timestamp_column_names
651
- @timestamp_column_names ||=
652
- %w(created_at created_on updated_at updated_on) & column_names
653
- end
654
669
 
655
- def inheritance_column_name
656
- @inheritance_column_name ||= model_class && model_class.inheritance_column
657
- end
658
-
659
- def column_names
660
- @column_names ||= @connection.columns(@table_name).collect { |c| c.name }
670
+ def model_class=(class_name)
671
+ if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
672
+ @model_class = class_name
673
+ else
674
+ @model_class = class_name.safe_constantize if class_name
675
+ end
661
676
  end
662
677
 
663
- def read_fixture_files
664
- yaml_files = Dir["#{@fixture_path}/**/*.yml"].select { |f|
678
+ # Loads the fixtures from the YAML file at +path+.
679
+ # If the file sets the +model_class+ and current instance value is not set,
680
+ # it uses the file value.
681
+ def read_fixture_files(path)
682
+ yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
665
683
  ::File.file?(f)
666
- } + [yaml_file_path]
684
+ } + [yaml_file_path(path)]
667
685
 
668
- yaml_files.each do |file|
669
- Fixtures::File.open(file) do |fh|
670
- fh.each do |name, row|
671
- fixtures[name] = ActiveRecord::Fixture.new(row, model_class)
686
+ yaml_files.each_with_object({}) do |file, fixtures|
687
+ FixtureSet::File.open(file) do |fh|
688
+ self.model_class ||= fh.model_class if fh.model_class
689
+ fh.each do |fixture_name, row|
690
+ fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
672
691
  end
673
692
  end
674
693
  end
675
694
  end
676
695
 
677
- def yaml_file_path
678
- "#{@fixture_path}.yml"
696
+ def yaml_file_path(path)
697
+ "#{path}.yml"
679
698
  end
680
-
681
699
  end
682
700
 
683
701
  class Fixture #:nodoc:
@@ -711,212 +729,10 @@ module ActiveRecord
711
729
  alias :to_hash :fixture
712
730
 
713
731
  def find
714
- if model_class
732
+ raise FixtureClassNotFound, "No class attached to find." unless model_class
733
+ model_class.unscoped do
715
734
  model_class.find(fixture[model_class.primary_key])
716
- else
717
- raise FixtureClassNotFound, "No class attached to find."
718
- end
719
- end
720
- end
721
- end
722
-
723
- module ActiveRecord
724
- module TestFixtures
725
- extend ActiveSupport::Concern
726
-
727
- included do
728
- setup :setup_fixtures
729
- teardown :teardown_fixtures
730
-
731
- class_attribute :fixture_path
732
- class_attribute :fixture_table_names
733
- class_attribute :fixture_class_names
734
- class_attribute :use_transactional_fixtures
735
- class_attribute :use_instantiated_fixtures # true, false, or :no_instances
736
- class_attribute :pre_loaded_fixtures
737
-
738
- self.fixture_table_names = []
739
- self.use_transactional_fixtures = true
740
- self.use_instantiated_fixtures = false
741
- self.pre_loaded_fixtures = false
742
-
743
- self.fixture_class_names = Hash.new do |h, table_name|
744
- h[table_name] = ActiveRecord::Fixtures.find_table_name(table_name)
745
- end
746
- end
747
-
748
- module ClassMethods
749
- def set_fixture_class(class_names = {})
750
- self.fixture_class_names = self.fixture_class_names.merge(class_names)
751
- end
752
-
753
- def fixtures(*fixture_names)
754
- if fixture_names.first == :all
755
- fixture_names = Dir["#{fixture_path}/**/*.{yml}"]
756
- fixture_names.map! { |f| f[(fixture_path.size + 1)..-5] }
757
- else
758
- fixture_names = fixture_names.flatten.map { |n| n.to_s }
759
- end
760
-
761
- self.fixture_table_names |= fixture_names
762
- require_fixture_classes(fixture_names)
763
- setup_fixture_accessors(fixture_names)
764
- end
765
-
766
- def try_to_load_dependency(file_name)
767
- require_dependency file_name
768
- rescue LoadError => e
769
- # Let's hope the developer has included it himself
770
-
771
- # Let's warn in case this is a subdependency, otherwise
772
- # subdependency error messages are totally cryptic
773
- if ActiveRecord::Base.logger
774
- ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
775
- end
776
- end
777
-
778
- def require_fixture_classes(fixture_names = nil)
779
- (fixture_names || fixture_table_names).each do |fixture_name|
780
- file_name = fixture_name.to_s
781
- file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names
782
- try_to_load_dependency(file_name)
783
- end
784
- end
785
-
786
- def setup_fixture_accessors(fixture_names = nil)
787
- fixture_names = Array.wrap(fixture_names || fixture_table_names)
788
- methods = Module.new do
789
- fixture_names.each do |fixture_name|
790
- fixture_name = fixture_name.to_s.tr('./', '_')
791
-
792
- define_method(fixture_name) do |*fixtures|
793
- force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
794
-
795
- @fixture_cache[fixture_name] ||= {}
796
-
797
- instances = fixtures.map do |fixture|
798
- @fixture_cache[fixture_name].delete(fixture) if force_reload
799
-
800
- if @loaded_fixtures[fixture_name][fixture.to_s]
801
- ActiveRecord::IdentityMap.without do
802
- @fixture_cache[fixture_name][fixture] ||= @loaded_fixtures[fixture_name][fixture.to_s].find
803
- end
804
- else
805
- raise StandardError, "No fixture with name '#{fixture}' found for table '#{fixture_name}'"
806
- end
807
- end
808
-
809
- instances.size == 1 ? instances.first : instances
810
- end
811
- private fixture_name
812
- end
813
- end
814
- include methods
815
735
  end
816
-
817
- def uses_transaction(*methods)
818
- @uses_transaction = [] unless defined?(@uses_transaction)
819
- @uses_transaction.concat methods.map { |m| m.to_s }
820
- end
821
-
822
- def uses_transaction?(method)
823
- @uses_transaction = [] unless defined?(@uses_transaction)
824
- @uses_transaction.include?(method.to_s)
825
- end
826
- end
827
-
828
- def run_in_transaction?
829
- use_transactional_fixtures &&
830
- !self.class.uses_transaction?(method_name)
831
736
  end
832
-
833
- def setup_fixtures
834
- return unless !ActiveRecord::Base.configurations.blank?
835
-
836
- if pre_loaded_fixtures && !use_transactional_fixtures
837
- raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
838
- end
839
-
840
- @fixture_cache = {}
841
- @fixture_connections = []
842
- @@already_loaded_fixtures ||= {}
843
-
844
- # Load fixtures once and begin transaction.
845
- if run_in_transaction?
846
- if @@already_loaded_fixtures[self.class]
847
- @loaded_fixtures = @@already_loaded_fixtures[self.class]
848
- else
849
- @loaded_fixtures = load_fixtures
850
- @@already_loaded_fixtures[self.class] = @loaded_fixtures
851
- end
852
- @fixture_connections = enlist_fixture_connections
853
- @fixture_connections.each do |connection|
854
- connection.increment_open_transactions
855
- connection.transaction_joinable = false
856
- connection.begin_db_transaction
857
- end
858
- # Load fixtures for every test.
859
- else
860
- ActiveRecord::Fixtures.reset_cache
861
- @@already_loaded_fixtures[self.class] = nil
862
- @loaded_fixtures = load_fixtures
863
- end
864
-
865
- # Instantiate fixtures for every test if requested.
866
- instantiate_fixtures if use_instantiated_fixtures
867
- end
868
-
869
- def teardown_fixtures
870
- return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
871
-
872
- unless run_in_transaction?
873
- ActiveRecord::Fixtures.reset_cache
874
- end
875
-
876
- # Rollback changes if a transaction is active.
877
- if run_in_transaction?
878
- @fixture_connections.each do |connection|
879
- if connection.open_transactions != 0
880
- connection.rollback_db_transaction
881
- connection.decrement_open_transactions
882
- end
883
- end
884
- @fixture_connections.clear
885
- end
886
- ActiveRecord::Base.clear_active_connections!
887
- end
888
-
889
- def enlist_fixture_connections
890
- ActiveRecord::Base.connection_handler.connection_pools.values.map(&:connection)
891
- end
892
-
893
- private
894
- def load_fixtures
895
- fixtures = ActiveRecord::Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names)
896
- Hash[fixtures.map { |f| [f.name, f] }]
897
- end
898
-
899
- # for pre_loaded_fixtures, only require the classes once. huge speed improvement
900
- @@required_fixture_classes = false
901
-
902
- def instantiate_fixtures
903
- if pre_loaded_fixtures
904
- raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::Fixtures.all_loaded_fixtures.empty?
905
- unless @@required_fixture_classes
906
- self.class.require_fixture_classes ActiveRecord::Fixtures.all_loaded_fixtures.keys
907
- @@required_fixture_classes = true
908
- end
909
- ActiveRecord::Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
910
- else
911
- raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
912
- @loaded_fixtures.each_value do |fixture_set|
913
- ActiveRecord::Fixtures.instantiate_fixtures(self, fixture_set, load_instances?)
914
- end
915
- end
916
- end
917
-
918
- def load_instances?
919
- use_instantiated_fixtures != :no_instances
920
- end
921
737
  end
922
738
  end