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