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,75 +1,80 @@
1
- require 'active_support/core_ext/string/conversions'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/conversions"
2
4
 
3
5
  module ActiveRecord
4
6
  module Associations
5
- # Keeps track of table aliases for ActiveRecord::Associations::ClassMethods::JoinDependency and
6
- # ActiveRecord::Associations::ThroughAssociationScope
7
+ # Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
7
8
  class AliasTracker # :nodoc:
8
- attr_reader :aliases, :table_joins, :connection
9
-
10
- # table_joins is an array of arel joins which might conflict with the aliases we assign here
11
- def initialize(connection = ActiveRecord::Model.connection, table_joins = [])
12
- @aliases = Hash.new { |h,k| h[k] = initial_count_for(k) }
13
- @table_joins = table_joins
14
- @connection = connection
9
+ def self.create(connection, initial_table, joins)
10
+ if joins.empty?
11
+ aliases = Hash.new(0)
12
+ else
13
+ aliases = Hash.new { |h, k|
14
+ h[k] = initial_count_for(connection, k, joins)
15
+ }
16
+ end
17
+ aliases[initial_table] = 1
18
+ new(connection, aliases)
15
19
  end
16
20
 
17
- def aliased_table_for(table_name, aliased_name = nil)
18
- table_alias = aliased_name_for(table_name, aliased_name)
21
+ def self.initial_count_for(connection, name, table_joins)
22
+ quoted_name = nil
19
23
 
20
- if table_alias == table_name
21
- Arel::Table.new(table_name)
22
- else
23
- Arel::Table.new(table_name).alias(table_alias)
24
+ counts = table_joins.map do |join|
25
+ if join.is_a?(Arel::Nodes::StringJoin)
26
+ # quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
27
+ quoted_name ||= connection.quote_table_name(name)
28
+
29
+ # Table names + table aliases
30
+ join.left.scan(
31
+ /JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
32
+ ).size
33
+ elsif join.is_a?(Arel::Nodes::Join)
34
+ join.left.name == name ? 1 : 0
35
+ elsif join.is_a?(Hash)
36
+ join[name]
37
+ else
38
+ raise ArgumentError, "joins list should be initialized by list of Arel::Nodes::Join"
39
+ end
24
40
  end
41
+
42
+ counts.sum
25
43
  end
26
44
 
27
- def aliased_name_for(table_name, aliased_name = nil)
28
- aliased_name ||= table_name
45
+ # table_joins is an array of arel joins which might conflict with the aliases we assign here
46
+ def initialize(connection, aliases)
47
+ @aliases = aliases
48
+ @connection = connection
49
+ end
29
50
 
51
+ def aliased_table_for(table_name, aliased_name, type_caster)
30
52
  if aliases[table_name].zero?
31
53
  # If it's zero, we can have our table_name
32
54
  aliases[table_name] = 1
33
- table_name
55
+ Arel::Table.new(table_name, type_caster: type_caster)
34
56
  else
35
57
  # Otherwise, we need to use an alias
36
- aliased_name = connection.table_alias_for(aliased_name)
58
+ aliased_name = @connection.table_alias_for(aliased_name)
37
59
 
38
60
  # Update the count
39
61
  aliases[aliased_name] += 1
40
62
 
41
- if aliases[aliased_name] > 1
63
+ table_alias = if aliases[aliased_name] > 1
42
64
  "#{truncate(aliased_name)}_#{aliases[aliased_name]}"
43
65
  else
44
66
  aliased_name
45
67
  end
68
+ Arel::Table.new(table_name, type_caster: type_caster).alias(table_alias)
46
69
  end
47
70
  end
48
71
 
49
- private
50
-
51
- def initial_count_for(name)
52
- return 0 if Arel::Table === table_joins
53
-
54
- # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase
55
- quoted_name = connection.quote_table_name(name).downcase
72
+ attr_reader :aliases
56
73
 
57
- counts = table_joins.map do |join|
58
- if join.is_a?(Arel::Nodes::StringJoin)
59
- # Table names + table aliases
60
- join.left.downcase.scan(
61
- /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/
62
- ).size
63
- else
64
- join.left.table_name == name ? 1 : 0
65
- end
66
- end
67
-
68
- counts.sum
69
- end
74
+ private
70
75
 
71
76
  def truncate(name)
72
- name.slice(0, connection.table_alias_length - 2)
77
+ name.slice(0, @connection.table_alias_length - 2)
73
78
  end
74
79
  end
75
80
  end
@@ -1,5 +1,6 @@
1
- require 'active_support/core_ext/array/wrap'
2
- require 'active_support/core_ext/object/inclusion'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array/wrap"
3
4
 
4
5
  module ActiveRecord
5
6
  module Associations
@@ -9,47 +10,56 @@ module ActiveRecord
9
10
  #
10
11
  # Association
11
12
  # SingularAssociation
12
- # HasOneAssociation
13
+ # HasOneAssociation + ForeignAssociation
13
14
  # HasOneThroughAssociation + ThroughAssociation
14
15
  # BelongsToAssociation
15
16
  # BelongsToPolymorphicAssociation
16
17
  # CollectionAssociation
17
- # HasAndBelongsToManyAssociation
18
- # HasManyAssociation
18
+ # HasManyAssociation + ForeignAssociation
19
19
  # HasManyThroughAssociation + ThroughAssociation
20
+ #
21
+ # Associations in Active Record are middlemen between the object that
22
+ # holds the association, known as the <tt>owner</tt>, and the associated
23
+ # result set, known as the <tt>target</tt>. Association metadata is available in
24
+ # <tt>reflection</tt>, which is an instance of <tt>ActiveRecord::Reflection::AssociationReflection</tt>.
25
+ #
26
+ # For example, given
27
+ #
28
+ # class Blog < ActiveRecord::Base
29
+ # has_many :posts
30
+ # end
31
+ #
32
+ # blog = Blog.first
33
+ #
34
+ # The association of <tt>blog.posts</tt> has the object +blog+ as its
35
+ # <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
36
+ # the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
20
37
  class Association #:nodoc:
21
38
  attr_reader :owner, :target, :reflection
22
39
 
23
- delegate :options, :to => :reflection
40
+ delegate :options, to: :reflection
24
41
 
25
42
  def initialize(owner, reflection)
26
43
  reflection.check_validity!
27
44
 
28
- @target = nil
29
45
  @owner, @reflection = owner, reflection
30
- @updated = false
31
46
 
32
47
  reset
33
48
  reset_scope
34
49
  end
35
50
 
36
- # Returns the name of the table of the related class:
37
- #
38
- # post.comments.aliased_table_name # => "comments"
39
- #
40
- def aliased_table_name
41
- reflection.klass.table_name
42
- end
43
-
44
51
  # Resets the \loaded flag to +false+ and sets the \target to +nil+.
45
52
  def reset
46
53
  @loaded = false
47
- IdentityMap.remove(target) if IdentityMap.enabled? && target
48
54
  @target = nil
55
+ @stale_state = nil
56
+ @inversed = false
49
57
  end
50
58
 
51
59
  # Reloads the \target and returns +self+ on success.
52
- def reload
60
+ # The QueryCache is cleared if +force+ is true.
61
+ def reload(force = false)
62
+ klass.connection.clear_query_cache if force && klass
53
63
  reset
54
64
  reset_scope
55
65
  load_target
@@ -63,18 +73,19 @@ module ActiveRecord
63
73
 
64
74
  # Asserts the \target has been loaded setting the \loaded flag to +true+.
65
75
  def loaded!
66
- @loaded = true
76
+ @loaded = true
67
77
  @stale_state = stale_state
78
+ @inversed = false
68
79
  end
69
80
 
70
81
  # The target is stale if the target no longer points to the record(s) that the
71
82
  # relevant foreign_key(s) refers to. If stale, the association accessor method
72
83
  # on the owner will reload the target. It's up to subclasses to implement the
73
- # state_state method if relevant.
84
+ # stale_state method if relevant.
74
85
  #
75
86
  # Note that if the target has not been loaded, it is not considered stale.
76
87
  def stale_target?
77
- loaded? && @stale_state != stale_state
88
+ !@inversed && loaded? && @stale_state != stale_state
78
89
  end
79
90
 
80
91
  # Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
@@ -83,20 +94,8 @@ module ActiveRecord
83
94
  loaded!
84
95
  end
85
96
 
86
- def scoped
87
- target_scope.merge(association_scope)
88
- end
89
-
90
- # The scope for this association.
91
- #
92
- # Note that the association_scope is merged into the target_scope only when the
93
- # scoped method is called. This is because at that point the call may be surrounded
94
- # by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
95
- # actually gets built.
96
- def association_scope
97
- if klass
98
- @association_scope ||= AssociationScope.new(self).scope
99
- end
97
+ def scope
98
+ target_scope.merge!(association_scope)
100
99
  end
101
100
 
102
101
  def reset_scope
@@ -105,22 +104,46 @@ module ActiveRecord
105
104
 
106
105
  # Set the inverse association, if possible
107
106
  def set_inverse_instance(record)
108
- if record && invertible_for?(record)
109
- inverse = record.association(inverse_reflection_for(record).name)
110
- inverse.target = owner
107
+ if inverse = inverse_association_for(record)
108
+ inverse.inversed_from(owner)
111
109
  end
110
+ record
112
111
  end
113
112
 
114
- # This class of the target. belongs_to polymorphic overrides this to look at the
113
+ def set_inverse_instance_from_queries(record)
114
+ if inverse = inverse_association_for(record)
115
+ inverse.inversed_from_queries(owner)
116
+ end
117
+ record
118
+ end
119
+
120
+ # Remove the inverse association, if possible
121
+ def remove_inverse_instance(record)
122
+ if inverse = inverse_association_for(record)
123
+ inverse.inversed_from(nil)
124
+ end
125
+ end
126
+
127
+ def inversed_from(record)
128
+ self.target = record
129
+ @inversed = !!record
130
+ end
131
+ alias :inversed_from_queries :inversed_from
132
+
133
+ # Returns the class of the target. belongs_to polymorphic overrides this to look at the
115
134
  # polymorphic_type field on the owner.
116
135
  def klass
117
136
  reflection.klass
118
137
  end
119
138
 
120
- # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
121
- # through association's scope)
122
- def target_scope
123
- klass.scoped
139
+ def extensions
140
+ extensions = klass.default_extensions | reflection.extensions
141
+
142
+ if reflection.scope
143
+ extensions |= reflection.scope_for(klass.unscoped, owner).extensions
144
+ end
145
+
146
+ extensions
124
147
  end
125
148
 
126
149
  # Loads the \target if needed and returns it.
@@ -134,32 +157,80 @@ module ActiveRecord
134
157
  # ActiveRecord::RecordNotFound is rescued within the method, and it is
135
158
  # not reraised. The proxy is \reset and +nil+ is the return value.
136
159
  def load_target
137
- if find_target?
138
- begin
139
- if IdentityMap.enabled? && association_class && association_class.respond_to?(:base_class)
140
- @target = IdentityMap.get(association_class, owner[reflection.foreign_key])
141
- end
142
- rescue NameError
143
- nil
144
- ensure
145
- @target ||= find_target
146
- end
147
- end
160
+ @target = find_target if (@stale_state && stale_target?) || find_target?
161
+
148
162
  loaded! unless loaded?
149
163
  target
150
164
  rescue ActiveRecord::RecordNotFound
151
165
  reset
152
166
  end
153
167
 
154
- def interpolate(sql, record = nil)
155
- if sql.respond_to?(:to_proc)
156
- owner.send(:instance_exec, record, &sql)
157
- else
158
- sql
159
- end
168
+ # We can't dump @reflection and @through_reflection since it contains the scope proc
169
+ def marshal_dump
170
+ ivars = (instance_variables - [:@reflection, :@through_reflection]).map { |name| [name, instance_variable_get(name)] }
171
+ [@reflection.name, ivars]
172
+ end
173
+
174
+ def marshal_load(data)
175
+ reflection_name, ivars = data
176
+ ivars.each { |name, val| instance_variable_set(name, val) }
177
+ @reflection = @owner.class._reflect_on_association(reflection_name)
178
+ end
179
+
180
+ def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
181
+ except_from_scope_attributes ||= {}
182
+ skip_assign = [reflection.foreign_key, reflection.type].compact
183
+ assigned_keys = record.changed_attribute_names_to_save
184
+ assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
185
+ attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
186
+ record.send(:_assign_attributes, attributes) if attributes.any?
187
+ set_inverse_instance(record)
188
+ end
189
+
190
+ def create(attributes = {}, &block)
191
+ _create_record(attributes, &block)
192
+ end
193
+
194
+ def create!(attributes = {}, &block)
195
+ _create_record(attributes, true, &block)
160
196
  end
161
197
 
162
198
  private
199
+ def find_target
200
+ scope = self.scope
201
+ return scope.to_a if skip_statement_cache?(scope)
202
+
203
+ conn = klass.connection
204
+ sc = reflection.association_scope_cache(conn, owner) do |params|
205
+ as = AssociationScope.create { params.bind }
206
+ target_scope.merge!(as.scope(self))
207
+ end
208
+
209
+ binds = AssociationScope.get_bind_values(owner, reflection.chain)
210
+ sc.execute(binds, conn) { |record| set_inverse_instance(record) } || []
211
+ end
212
+
213
+ # The scope for this association.
214
+ #
215
+ # Note that the association_scope is merged into the target_scope only when the
216
+ # scope method is called. This is because at that point the call may be surrounded
217
+ # by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
218
+ # actually gets built.
219
+ def association_scope
220
+ if klass
221
+ @association_scope ||= AssociationScope.scope(self)
222
+ end
223
+ end
224
+
225
+ # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
226
+ # through association's scope)
227
+ def target_scope
228
+ AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
229
+ end
230
+
231
+ def scope_for_create
232
+ scope.scope_for_create
233
+ end
163
234
 
164
235
  def find_target?
165
236
  !loaded? && (!owner.new_record? || foreign_key_present?) && klass
@@ -168,11 +239,11 @@ module ActiveRecord
168
239
  def creation_attributes
169
240
  attributes = {}
170
241
 
171
- if reflection.macro.in?([:has_one, :has_many]) && !options[:through]
242
+ if (reflection.has_one? || reflection.collection?) && !options[:through]
172
243
  attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
173
244
 
174
- if reflection.options[:as]
175
- attributes[reflection.type] = owner.class.base_class.name
245
+ if reflection.type
246
+ attributes[reflection.type] = owner.class.polymorphic_name
176
247
  end
177
248
  end
178
249
 
@@ -184,13 +255,14 @@ module ActiveRecord
184
255
  creation_attributes.each { |key, value| record[key] = value }
185
256
  end
186
257
 
187
- # Should be true if there is a foreign key present on the owner which
258
+ # Returns true if there is a foreign key present on the owner which
188
259
  # references the target. This is used to determine whether we can load
189
260
  # the target if the owner is currently a new record (and therefore
190
- # without a key).
261
+ # without a key). If the owner is a new record then foreign_key must
262
+ # be present in order to load target.
191
263
  #
192
264
  # Currently implemented by belongs_to (vanilla and polymorphic) and
193
- # has_one/has_many :through associations which go through a belongs_to
265
+ # has_one/has_many :through associations which go through a belongs_to.
194
266
  def foreign_key_present?
195
267
  false
196
268
  end
@@ -198,10 +270,20 @@ module ActiveRecord
198
270
  # Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of
199
271
  # the kind of the class of the associated objects. Meant to be used as
200
272
  # a sanity check when you are about to assign an associated record.
201
- def raise_on_type_mismatch(record)
202
- unless record.is_a?(reflection.klass) || record.is_a?(reflection.class_name.constantize)
203
- message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
204
- raise ActiveRecord::AssociationTypeMismatch, message
273
+ def raise_on_type_mismatch!(record)
274
+ unless record.is_a?(reflection.klass)
275
+ fresh_class = reflection.class_name.safe_constantize
276
+ unless fresh_class && record.is_a?(fresh_class)
277
+ message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\
278
+ "got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"
279
+ raise ActiveRecord::AssociationTypeMismatch, message
280
+ end
281
+ end
282
+ end
283
+
284
+ def inverse_association_for(record)
285
+ if invertible_for?(record)
286
+ record.association(inverse_reflection_for(record).name)
205
287
  end
206
288
  end
207
289
 
@@ -212,28 +294,38 @@ module ActiveRecord
212
294
  reflection.inverse_of
213
295
  end
214
296
 
215
- # Is this association invertible? Can be redefined by subclasses.
297
+ # Returns true if inverse association on the given record needs to be set.
298
+ # This method is redefined by subclasses.
216
299
  def invertible_for?(record)
217
- inverse_reflection_for(record)
300
+ foreign_key_for?(record) && inverse_reflection_for(record)
301
+ end
302
+
303
+ # Returns true if record contains the foreign_key
304
+ def foreign_key_for?(record)
305
+ record.has_attribute?(reflection.foreign_key)
218
306
  end
219
307
 
220
308
  # This should be implemented to return the values of the relevant key(s) on the owner,
221
- # so that when state_state is different from the value stored on the last find_target,
309
+ # so that when stale_state is different from the value stored on the last find_target,
222
310
  # the target is stale.
223
311
  #
224
- # This is only relevant to certain associations, which is why it returns nil by default.
312
+ # This is only relevant to certain associations, which is why it returns +nil+ by default.
225
313
  def stale_state
226
314
  end
227
315
 
228
- def association_class
229
- @reflection.klass
316
+ def build_record(attributes)
317
+ reflection.build_association(attributes) do |record|
318
+ initialize_attributes(record, attributes)
319
+ yield(record) if block_given?
320
+ end
230
321
  end
231
322
 
232
- def build_record(attributes, options)
233
- reflection.build_association(attributes, options) do |record|
234
- attributes = create_scope.except(*(record.changed - [reflection.foreign_key]))
235
- record.assign_attributes(attributes, :without_protection => true)
236
- end
323
+ # Returns true if statement cache should be skipped on the association reader.
324
+ def skip_statement_cache?(scope)
325
+ reflection.has_scope? ||
326
+ scope.eager_loading? ||
327
+ klass.scope_attributes? ||
328
+ reflection.source_reflection.active_record.default_scopes.any?
237
329
  end
238
330
  end
239
331
  end