activerecord 5.0.6 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (358) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +638 -2023
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +8 -6
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record/aggregations.rb +249 -246
  8. data/lib/active_record/association_relation.rb +24 -13
  9. data/lib/active_record/associations/alias_tracker.rb +24 -33
  10. data/lib/active_record/associations/association.rb +119 -56
  11. data/lib/active_record/associations/association_scope.rb +94 -94
  12. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  14. data/lib/active_record/associations/builder/association.rb +18 -25
  15. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  16. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -61
  18. data/lib/active_record/associations/builder/has_many.rb +4 -0
  19. data/lib/active_record/associations/builder/has_one.rb +37 -1
  20. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  21. data/lib/active_record/associations/collection_association.rb +80 -252
  22. data/lib/active_record/associations/collection_proxy.rb +158 -121
  23. data/lib/active_record/associations/foreign_association.rb +9 -0
  24. data/lib/active_record/associations/has_many_association.rb +23 -29
  25. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  26. data/lib/active_record/associations/has_one_association.rb +59 -54
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +38 -90
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +134 -176
  32. data/lib/active_record/associations/preloader/association.rb +84 -125
  33. data/lib/active_record/associations/preloader/through_association.rb +82 -75
  34. data/lib/active_record/associations/preloader.rb +90 -102
  35. data/lib/active_record/associations/singular_association.rb +12 -45
  36. data/lib/active_record/associations/through_association.rb +26 -14
  37. data/lib/active_record/associations.rb +1603 -1592
  38. data/lib/active_record/attribute_assignment.rb +54 -60
  39. data/lib/active_record/attribute_decorators.rb +38 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -7
  41. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -91
  43. data/lib/active_record/attribute_methods/query.rb +4 -3
  44. data/lib/active_record/attribute_methods/read.rb +21 -49
  45. data/lib/active_record/attribute_methods/serialization.rb +30 -7
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -64
  47. data/lib/active_record/attribute_methods/write.rb +35 -33
  48. data/lib/active_record/attribute_methods.rb +66 -106
  49. data/lib/active_record/attributes.rb +38 -24
  50. data/lib/active_record/autosave_association.rb +53 -32
  51. data/lib/active_record/base.rb +27 -24
  52. data/lib/active_record/callbacks.rb +63 -33
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +11 -11
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +553 -321
  56. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  57. data/lib/active_record/connection_adapters/abstract/database_statements.rb +213 -94
  58. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -28
  59. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
  60. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -27
  62. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -126
  63. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  64. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +369 -199
  65. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
  66. data/lib/active_record/connection_adapters/abstract_adapter.rb +363 -202
  67. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -551
  68. data/lib/active_record/connection_adapters/column.rb +41 -13
  69. data/lib/active_record/connection_adapters/connection_specification.rb +172 -138
  70. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  71. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +143 -49
  73. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -22
  74. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  75. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +50 -45
  76. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  77. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  78. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  79. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +49 -30
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +22 -7
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +60 -54
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -10
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -17
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  98. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +31 -9
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -30
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -4
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +35 -32
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +380 -300
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +10 -6
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +382 -275
  116. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +74 -19
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +254 -262
  126. data/lib/active_record/connection_adapters/statement_pool.rb +9 -7
  127. data/lib/active_record/connection_handling.rb +159 -40
  128. data/lib/active_record/core.rb +202 -162
  129. data/lib/active_record/counter_cache.rb +57 -28
  130. data/lib/active_record/database_configurations/database_config.rb +37 -0
  131. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  132. data/lib/active_record/database_configurations/url_config.rb +79 -0
  133. data/lib/active_record/database_configurations.rb +233 -0
  134. data/lib/active_record/define_callbacks.rb +22 -0
  135. data/lib/active_record/dynamic_matchers.rb +87 -86
  136. data/lib/active_record/enum.rb +60 -23
  137. data/lib/active_record/errors.rb +114 -18
  138. data/lib/active_record/explain.rb +4 -3
  139. data/lib/active_record/explain_registry.rb +3 -1
  140. data/lib/active_record/explain_subscriber.rb +9 -4
  141. data/lib/active_record/fixture_set/file.rb +13 -8
  142. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  143. data/lib/active_record/fixture_set/render_context.rb +17 -0
  144. data/lib/active_record/fixture_set/table_row.rb +153 -0
  145. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  146. data/lib/active_record/fixtures.rb +195 -502
  147. data/lib/active_record/gem_version.rb +4 -2
  148. data/lib/active_record/inheritance.rb +151 -97
  149. data/lib/active_record/insert_all.rb +179 -0
  150. data/lib/active_record/integration.rb +116 -25
  151. data/lib/active_record/internal_metadata.rb +15 -18
  152. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  153. data/lib/active_record/locking/optimistic.rb +78 -87
  154. data/lib/active_record/locking/pessimistic.rb +18 -6
  155. data/lib/active_record/log_subscriber.rb +48 -29
  156. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  157. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/migration/command_recorder.rb +143 -97
  160. data/lib/active_record/migration/compatibility.rb +174 -56
  161. data/lib/active_record/migration/join_table.rb +8 -6
  162. data/lib/active_record/migration.rb +367 -300
  163. data/lib/active_record/model_schema.rb +145 -139
  164. data/lib/active_record/nested_attributes.rb +214 -201
  165. data/lib/active_record/no_touching.rb +10 -1
  166. data/lib/active_record/null_relation.rb +13 -34
  167. data/lib/active_record/persistence.rb +442 -72
  168. data/lib/active_record/query_cache.rb +15 -14
  169. data/lib/active_record/querying.rb +36 -23
  170. data/lib/active_record/railtie.rb +128 -36
  171. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  172. data/lib/active_record/railties/console_sandbox.rb +2 -0
  173. data/lib/active_record/railties/controller_runtime.rb +34 -33
  174. data/lib/active_record/railties/databases.rake +309 -177
  175. data/lib/active_record/readonly_attributes.rb +5 -4
  176. data/lib/active_record/reflection.rb +211 -249
  177. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  178. data/lib/active_record/relation/batches.rb +99 -52
  179. data/lib/active_record/relation/calculations.rb +211 -172
  180. data/lib/active_record/relation/delegation.rb +67 -65
  181. data/lib/active_record/relation/finder_methods.rb +208 -247
  182. data/lib/active_record/relation/from_clause.rb +2 -8
  183. data/lib/active_record/relation/merger.rb +78 -61
  184. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  185. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  186. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  187. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  188. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  189. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  190. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  191. data/lib/active_record/relation/predicate_builder.rb +86 -104
  192. data/lib/active_record/relation/query_attribute.rb +33 -2
  193. data/lib/active_record/relation/query_methods.rb +458 -329
  194. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  195. data/lib/active_record/relation/spawn_methods.rb +8 -7
  196. data/lib/active_record/relation/where_clause.rb +111 -95
  197. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  198. data/lib/active_record/relation.rb +429 -318
  199. data/lib/active_record/result.rb +69 -39
  200. data/lib/active_record/runtime_registry.rb +5 -3
  201. data/lib/active_record/sanitization.rb +83 -99
  202. data/lib/active_record/schema.rb +7 -14
  203. data/lib/active_record/schema_dumper.rb +71 -69
  204. data/lib/active_record/schema_migration.rb +15 -5
  205. data/lib/active_record/scoping/default.rb +93 -95
  206. data/lib/active_record/scoping/named.rb +45 -25
  207. data/lib/active_record/scoping.rb +20 -19
  208. data/lib/active_record/secure_token.rb +4 -2
  209. data/lib/active_record/serialization.rb +2 -0
  210. data/lib/active_record/statement_cache.rb +63 -28
  211. data/lib/active_record/store.rb +121 -41
  212. data/lib/active_record/suppressor.rb +4 -1
  213. data/lib/active_record/table_metadata.rb +26 -20
  214. data/lib/active_record/tasks/database_tasks.rb +276 -85
  215. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -90
  216. data/lib/active_record/tasks/postgresql_database_tasks.rb +78 -47
  217. data/lib/active_record/tasks/sqlite_database_tasks.rb +34 -16
  218. data/lib/active_record/test_databases.rb +23 -0
  219. data/lib/active_record/test_fixtures.rb +224 -0
  220. data/lib/active_record/timestamp.rb +70 -35
  221. data/lib/active_record/touch_later.rb +7 -4
  222. data/lib/active_record/transactions.rb +133 -149
  223. data/lib/active_record/translation.rb +3 -1
  224. data/lib/active_record/type/adapter_specific_registry.rb +44 -45
  225. data/lib/active_record/type/date.rb +2 -0
  226. data/lib/active_record/type/date_time.rb +2 -0
  227. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  228. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  229. data/lib/active_record/type/internal/timezone.rb +2 -0
  230. data/lib/active_record/type/json.rb +30 -0
  231. data/lib/active_record/type/serialized.rb +16 -8
  232. data/lib/active_record/type/text.rb +11 -0
  233. data/lib/active_record/type/time.rb +2 -1
  234. data/lib/active_record/type/type_map.rb +13 -15
  235. data/lib/active_record/type/unsigned_integer.rb +17 -0
  236. data/lib/active_record/type.rb +23 -17
  237. data/lib/active_record/type_caster/connection.rb +17 -12
  238. data/lib/active_record/type_caster/map.rb +5 -4
  239. data/lib/active_record/type_caster.rb +4 -2
  240. data/lib/active_record/validations/absence.rb +2 -0
  241. data/lib/active_record/validations/associated.rb +3 -1
  242. data/lib/active_record/validations/length.rb +2 -0
  243. data/lib/active_record/validations/presence.rb +4 -2
  244. data/lib/active_record/validations/uniqueness.rb +29 -42
  245. data/lib/active_record/validations.rb +7 -4
  246. data/lib/active_record/version.rb +3 -1
  247. data/lib/active_record.rb +36 -22
  248. data/lib/arel/alias_predication.rb +9 -0
  249. data/lib/arel/attributes/attribute.rb +37 -0
  250. data/lib/arel/attributes.rb +22 -0
  251. data/lib/arel/collectors/bind.rb +24 -0
  252. data/lib/arel/collectors/composite.rb +31 -0
  253. data/lib/arel/collectors/plain_string.rb +20 -0
  254. data/lib/arel/collectors/sql_string.rb +20 -0
  255. data/lib/arel/collectors/substitute_binds.rb +28 -0
  256. data/lib/arel/crud.rb +42 -0
  257. data/lib/arel/delete_manager.rb +18 -0
  258. data/lib/arel/errors.rb +9 -0
  259. data/lib/arel/expressions.rb +29 -0
  260. data/lib/arel/factory_methods.rb +49 -0
  261. data/lib/arel/insert_manager.rb +49 -0
  262. data/lib/arel/math.rb +45 -0
  263. data/lib/arel/nodes/and.rb +32 -0
  264. data/lib/arel/nodes/ascending.rb +23 -0
  265. data/lib/arel/nodes/binary.rb +52 -0
  266. data/lib/arel/nodes/bind_param.rb +36 -0
  267. data/lib/arel/nodes/case.rb +55 -0
  268. data/lib/arel/nodes/casted.rb +50 -0
  269. data/lib/arel/nodes/comment.rb +29 -0
  270. data/lib/arel/nodes/count.rb +12 -0
  271. data/lib/arel/nodes/delete_statement.rb +45 -0
  272. data/lib/arel/nodes/descending.rb +23 -0
  273. data/lib/arel/nodes/equality.rb +18 -0
  274. data/lib/arel/nodes/extract.rb +24 -0
  275. data/lib/arel/nodes/false.rb +16 -0
  276. data/lib/arel/nodes/full_outer_join.rb +8 -0
  277. data/lib/arel/nodes/function.rb +44 -0
  278. data/lib/arel/nodes/grouping.rb +8 -0
  279. data/lib/arel/nodes/in.rb +8 -0
  280. data/lib/arel/nodes/infix_operation.rb +80 -0
  281. data/lib/arel/nodes/inner_join.rb +8 -0
  282. data/lib/arel/nodes/insert_statement.rb +37 -0
  283. data/lib/arel/nodes/join_source.rb +20 -0
  284. data/lib/arel/nodes/matches.rb +18 -0
  285. data/lib/arel/nodes/named_function.rb +23 -0
  286. data/lib/arel/nodes/node.rb +50 -0
  287. data/lib/arel/nodes/node_expression.rb +13 -0
  288. data/lib/arel/nodes/outer_join.rb +8 -0
  289. data/lib/arel/nodes/over.rb +15 -0
  290. data/lib/arel/nodes/regexp.rb +16 -0
  291. data/lib/arel/nodes/right_outer_join.rb +8 -0
  292. data/lib/arel/nodes/select_core.rb +67 -0
  293. data/lib/arel/nodes/select_statement.rb +41 -0
  294. data/lib/arel/nodes/sql_literal.rb +16 -0
  295. data/lib/arel/nodes/string_join.rb +11 -0
  296. data/lib/arel/nodes/table_alias.rb +27 -0
  297. data/lib/arel/nodes/terminal.rb +16 -0
  298. data/lib/arel/nodes/true.rb +16 -0
  299. data/lib/arel/nodes/unary.rb +45 -0
  300. data/lib/arel/nodes/unary_operation.rb +20 -0
  301. data/lib/arel/nodes/unqualified_column.rb +22 -0
  302. data/lib/arel/nodes/update_statement.rb +41 -0
  303. data/lib/arel/nodes/values_list.rb +9 -0
  304. data/lib/arel/nodes/window.rb +126 -0
  305. data/lib/arel/nodes/with.rb +11 -0
  306. data/lib/arel/nodes.rb +68 -0
  307. data/lib/arel/order_predications.rb +13 -0
  308. data/lib/arel/predications.rb +257 -0
  309. data/lib/arel/select_manager.rb +271 -0
  310. data/lib/arel/table.rb +110 -0
  311. data/lib/arel/tree_manager.rb +72 -0
  312. data/lib/arel/update_manager.rb +34 -0
  313. data/lib/arel/visitors/depth_first.rb +204 -0
  314. data/lib/arel/visitors/dot.rb +297 -0
  315. data/lib/arel/visitors/ibm_db.rb +34 -0
  316. data/lib/arel/visitors/informix.rb +62 -0
  317. data/lib/arel/visitors/mssql.rb +157 -0
  318. data/lib/arel/visitors/mysql.rb +83 -0
  319. data/lib/arel/visitors/oracle.rb +159 -0
  320. data/lib/arel/visitors/oracle12.rb +66 -0
  321. data/lib/arel/visitors/postgresql.rb +110 -0
  322. data/lib/arel/visitors/sqlite.rb +39 -0
  323. data/lib/arel/visitors/to_sql.rb +889 -0
  324. data/lib/arel/visitors/visitor.rb +46 -0
  325. data/lib/arel/visitors/where_sql.rb +23 -0
  326. data/lib/arel/visitors.rb +20 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +58 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  330. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  332. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  334. data/lib/rails/generators/active_record/migration.rb +17 -2
  335. data/lib/rails/generators/active_record/model/model_generator.rb +9 -29
  336. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  337. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +133 -50
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  347. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  348. data/lib/active_record/attribute.rb +0 -213
  349. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  350. data/lib/active_record/attribute_set/builder.rb +0 -130
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/collection_cache_key.rb +0 -50
  353. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  354. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  355. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  356. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  357. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  358. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,5 +1,7 @@
1
- require 'thread'
2
- require 'active_support/core_ext/string/filters'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/filters"
4
+ require "concurrent/map"
3
5
 
4
6
  module ActiveRecord
5
7
  # = Active Record Reflection
@@ -7,37 +9,41 @@ module ActiveRecord
7
9
  extend ActiveSupport::Concern
8
10
 
9
11
  included do
10
- class_attribute :_reflections, instance_writer: false
11
- class_attribute :aggregate_reflections, instance_writer: false
12
- self._reflections = {}
13
- self.aggregate_reflections = {}
12
+ class_attribute :_reflections, instance_writer: false, default: {}
13
+ class_attribute :aggregate_reflections, instance_writer: false, default: {}
14
14
  end
15
15
 
16
- def self.create(macro, name, scope, options, ar)
17
- klass = case macro
18
- when :composed_of
19
- AggregateReflection
20
- when :has_many
21
- HasManyReflection
22
- when :has_one
23
- HasOneReflection
24
- when :belongs_to
25
- BelongsToReflection
26
- else
27
- raise "Unsupported Macro: #{macro}"
28
- end
29
-
30
- reflection = klass.new(name, scope, options, ar)
31
- options[:through] ? ThroughReflection.new(reflection) : reflection
32
- end
16
+ class << self
17
+ def create(macro, name, scope, options, ar)
18
+ reflection = reflection_class_for(macro).new(name, scope, options, ar)
19
+ options[:through] ? ThroughReflection.new(reflection) : reflection
20
+ end
33
21
 
34
- def self.add_reflection(ar, name, reflection)
35
- ar.clear_reflections_cache
36
- ar._reflections = ar._reflections.merge(name.to_s => reflection)
37
- end
22
+ def add_reflection(ar, name, reflection)
23
+ ar.clear_reflections_cache
24
+ name = -name.to_s
25
+ ar._reflections = ar._reflections.except(name).merge!(name => reflection)
26
+ end
38
27
 
39
- def self.add_aggregate_reflection(ar, name, reflection)
40
- ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection)
28
+ def add_aggregate_reflection(ar, name, reflection)
29
+ ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)
30
+ end
31
+
32
+ private
33
+ def reflection_class_for(macro)
34
+ case macro
35
+ when :composed_of
36
+ AggregateReflection
37
+ when :has_many
38
+ HasManyReflection
39
+ when :has_one
40
+ HasOneReflection
41
+ when :belongs_to
42
+ BelongsToReflection
43
+ else
44
+ raise "Unsupported Macro: #{macro}"
45
+ end
46
+ end
41
47
  end
42
48
 
43
49
  # \Reflection enables the ability to examine the associations and aggregations of
@@ -135,8 +141,8 @@ module ActiveRecord
135
141
  # BelongsToReflection
136
142
  # HasAndBelongsToManyReflection
137
143
  # ThroughReflection
138
- # PolymorphicReflection
139
- # RuntimeReflection
144
+ # PolymorphicReflection
145
+ # RuntimeReflection
140
146
  class AbstractReflection # :nodoc:
141
147
  def through_reflection?
142
148
  false
@@ -152,14 +158,6 @@ module ActiveRecord
152
158
  klass.new(attributes, &block)
153
159
  end
154
160
 
155
- def quoted_table_name
156
- klass.quoted_table_name
157
- end
158
-
159
- def primary_key_type
160
- klass.type_for_attribute(klass.primary_key)
161
- end
162
-
163
161
  # Returns the class name for the macro.
164
162
  #
165
163
  # <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
@@ -170,12 +168,52 @@ module ActiveRecord
170
168
 
171
169
  JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
172
170
 
173
- def join_keys(association_klass)
174
- JoinKeys.new(foreign_key, active_record_primary_key)
171
+ def join_keys
172
+ @join_keys ||= get_join_keys(klass)
173
+ end
174
+
175
+ # Returns a list of scopes that should be applied for this Reflection
176
+ # object when querying the database.
177
+ def scopes
178
+ scope ? [scope] : []
179
+ end
180
+
181
+ def join_scope(table, foreign_table, foreign_klass)
182
+ predicate_builder = predicate_builder(table)
183
+ scope_chain_items = join_scopes(table, predicate_builder)
184
+ klass_scope = klass_join_scope(table, predicate_builder)
185
+
186
+ key = join_keys.key
187
+ foreign_key = join_keys.foreign_key
188
+
189
+ klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
190
+
191
+ if type
192
+ klass_scope.where!(type => foreign_klass.polymorphic_name)
193
+ end
194
+
195
+ if klass.finder_needs_type_condition?
196
+ klass_scope.where!(klass.send(:type_condition, table))
197
+ end
198
+
199
+ scope_chain_items.inject(klass_scope, &:merge!)
200
+ end
201
+
202
+ def join_scopes(table, predicate_builder) # :nodoc:
203
+ if scope
204
+ [scope_for(build_scope(table, predicate_builder))]
205
+ else
206
+ []
207
+ end
208
+ end
209
+
210
+ def klass_join_scope(table, predicate_builder) # :nodoc:
211
+ relation = build_scope(table, predicate_builder)
212
+ klass.scope_for_association(relation)
175
213
  end
176
214
 
177
215
  def constraints
178
- scope_chain.flatten
216
+ chain.flat_map(&:scopes)
179
217
  end
180
218
 
181
219
  def counter_cache_column
@@ -247,6 +285,40 @@ module ActiveRecord
247
285
  def chain
248
286
  collect_join_chain
249
287
  end
288
+
289
+ def get_join_keys(association_klass)
290
+ JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
291
+ end
292
+
293
+ def build_scope(table, predicate_builder = predicate_builder(table))
294
+ Relation.create(
295
+ klass,
296
+ table: table,
297
+ predicate_builder: predicate_builder
298
+ )
299
+ end
300
+
301
+ def join_primary_key(*)
302
+ foreign_key
303
+ end
304
+
305
+ def join_foreign_key
306
+ active_record_primary_key
307
+ end
308
+
309
+ protected
310
+ def actual_source_reflection # FIXME: this is a horrible name
311
+ self
312
+ end
313
+
314
+ private
315
+ def predicate_builder(table)
316
+ PredicateBuilder.new(TableMetadata.new(klass, table))
317
+ end
318
+
319
+ def primary_key(klass)
320
+ klass.primary_key || raise(UnknownPrimaryKey.new(klass))
321
+ end
250
322
  end
251
323
 
252
324
  # Base class for AggregateReflection and AssociationReflection. Objects of
@@ -281,7 +353,6 @@ module ActiveRecord
281
353
  end
282
354
 
283
355
  def autosave=(autosave)
284
- @automatic_inverse_of = false
285
356
  @options[:autosave] = autosave
286
357
  parent_reflection = self.parent_reflection
287
358
  if parent_reflection
@@ -293,6 +364,17 @@ module ActiveRecord
293
364
  #
294
365
  # <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
295
366
  # <tt>has_many :clients</tt> returns the Client class
367
+ #
368
+ # class Company < ActiveRecord::Base
369
+ # has_many :clients
370
+ # end
371
+ #
372
+ # Company.reflect_on_association(:clients).klass
373
+ # # => Client
374
+ #
375
+ # <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
376
+ # a new association object. Use +build_association+ or +create_association+
377
+ # instead. This allows plugins to hook into association object creation.
296
378
  def klass
297
379
  @klass ||= compute_class(class_name)
298
380
  end
@@ -311,8 +393,8 @@ module ActiveRecord
311
393
  active_record == other_aggregation.active_record
312
394
  end
313
395
 
314
- def scope_for(klass)
315
- scope ? klass.unscoped.instance_exec(nil, &scope) : klass.unscoped
396
+ def scope_for(relation, owner = nil)
397
+ relation.instance_exec(owner, &scope) || relation
316
398
  end
317
399
 
318
400
  private
@@ -321,8 +403,7 @@ module ActiveRecord
321
403
  end
322
404
  end
323
405
 
324
-
325
- # Holds all the meta-data about an aggregation as it was specified in the
406
+ # Holds all the metadata about an aggregation as it was specified in the
326
407
  # Active Record class.
327
408
  class AggregateReflection < MacroReflection #:nodoc:
328
409
  def mapping
@@ -331,26 +412,13 @@ module ActiveRecord
331
412
  end
332
413
  end
333
414
 
334
- # Holds all the meta-data about an association as it was specified in the
415
+ # Holds all the metadata about an association as it was specified in the
335
416
  # Active Record class.
336
417
  class AssociationReflection < MacroReflection #:nodoc:
337
- # Returns the target association's class.
338
- #
339
- # class Author < ActiveRecord::Base
340
- # has_many :books
341
- # end
342
- #
343
- # Author.reflect_on_association(:books).klass
344
- # # => Book
345
- #
346
- # <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
347
- # a new association object. Use +build_association+ or +create_association+
348
- # instead. This allows plugins to hook into association object creation.
349
- def klass
350
- @klass ||= compute_class(class_name)
351
- end
352
-
353
418
  def compute_class(name)
419
+ if polymorphic?
420
+ raise ArgumentError, "Polymorphic associations do not support computing the class."
421
+ end
354
422
  active_record.send(:compute_type, name)
355
423
  end
356
424
 
@@ -359,22 +427,22 @@ module ActiveRecord
359
427
 
360
428
  def initialize(name, scope, options, active_record)
361
429
  super
362
- @automatic_inverse_of = nil
363
430
  @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
364
- @foreign_type = options[:foreign_type] || "#{name}_type"
431
+ @foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
365
432
  @constructable = calculate_constructable(macro, options)
366
- @association_scope_cache = {}
367
- @scope_lock = Mutex.new
433
+ @association_scope_cache = Concurrent::Map.new
434
+
435
+ if options[:class_name] && options[:class_name].class == Class
436
+ raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
437
+ end
368
438
  end
369
439
 
370
- def association_scope_cache(conn, owner)
440
+ def association_scope_cache(conn, owner, &block)
371
441
  key = conn.prepared_statements
372
442
  if polymorphic?
373
443
  key = [key, owner._read_attribute(@foreign_type)]
374
444
  end
375
- @association_scope_cache[key] ||= @scope_lock.synchronize {
376
- @association_scope_cache[key] ||= yield
377
- }
445
+ @association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
378
446
  end
379
447
 
380
448
  def constructable? # :nodoc:
@@ -398,10 +466,6 @@ module ActiveRecord
398
466
  options[:primary_key] || primary_key(klass || self.klass)
399
467
  end
400
468
 
401
- def association_primary_key_type
402
- klass.type_for_attribute(association_primary_key.to_s)
403
- end
404
-
405
469
  def active_record_primary_key
406
470
  @active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
407
471
  end
@@ -413,7 +477,7 @@ module ActiveRecord
413
477
  def check_preloadable!
414
478
  return unless scope
415
479
 
416
- if scope.arity > 0
480
+ unless scope.arity == 0
417
481
  raise ArgumentError, <<-MSG.squish
418
482
  The association scope '#{name}' is instance dependent (the scope
419
483
  block takes an argument). Preloading instance dependent scopes is
@@ -424,7 +488,7 @@ module ActiveRecord
424
488
  alias :check_eager_loadable! :check_preloadable!
425
489
 
426
490
  def join_id_for(owner) # :nodoc:
427
- owner[active_record_primary_key]
491
+ owner[join_foreign_key]
428
492
  end
429
493
 
430
494
  def through_reflection
@@ -451,12 +515,6 @@ module ActiveRecord
451
515
  false
452
516
  end
453
517
 
454
- # An array of arrays of scopes. Each item in the outside array corresponds to a reflection
455
- # in the #chain.
456
- def scope_chain
457
- scope ? [[scope]] : [[]]
458
- end
459
-
460
518
  def has_scope?
461
519
  scope
462
520
  end
@@ -513,7 +571,7 @@ module ActiveRecord
513
571
  end
514
572
 
515
573
  VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
516
- INVALID_AUTOMATIC_INVERSE_OPTIONS = [:conditions, :through, :polymorphic, :foreign_key]
574
+ INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
517
575
 
518
576
  def add_as_source(seed)
519
577
  seed
@@ -531,12 +589,6 @@ module ActiveRecord
531
589
  Array(options[:extend])
532
590
  end
533
591
 
534
- protected
535
-
536
- def actual_source_reflection # FIXME: this is a horrible name
537
- self
538
- end
539
-
540
592
  private
541
593
 
542
594
  def calculate_constructable(macro, options)
@@ -545,18 +597,16 @@ module ActiveRecord
545
597
 
546
598
  # Attempts to find the inverse association name automatically.
547
599
  # If it cannot find a suitable inverse association name, it returns
548
- # nil.
600
+ # +nil+.
549
601
  def inverse_name
550
- options.fetch(:inverse_of) do
551
- if @automatic_inverse_of == false
552
- nil
553
- else
554
- @automatic_inverse_of ||= automatic_inverse_of
555
- end
602
+ unless defined?(@inverse_name)
603
+ @inverse_name = options.fetch(:inverse_of) { automatic_inverse_of }
556
604
  end
605
+
606
+ @inverse_name
557
607
  end
558
608
 
559
- # returns either false or the inverse association name that it finds.
609
+ # returns either +nil+ or the inverse association name that it finds.
560
610
  def automatic_inverse_of
561
611
  if can_find_inverse_of_automatically?(self)
562
612
  inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
@@ -573,20 +623,15 @@ module ActiveRecord
573
623
  return inverse_name
574
624
  end
575
625
  end
576
-
577
- false
578
626
  end
579
627
 
580
628
  # Checks if the inverse reflection that is returned from the
581
629
  # +automatic_inverse_of+ method is a valid reflection. We must
582
630
  # make sure that the reflection's active_record name matches up
583
631
  # with the current reflection's klass name.
584
- #
585
- # Note: klass will always be valid because when there's a NameError
586
- # from calling +klass+, +reflection+ will already be set to false.
587
632
  def valid_inverse_reflection?(reflection)
588
633
  reflection &&
589
- klass.name == reflection.active_record.name &&
634
+ klass <= reflection.active_record &&
590
635
  can_find_inverse_of_automatically?(reflection)
591
636
  end
592
637
 
@@ -594,9 +639,8 @@ module ActiveRecord
594
639
  # us from being able to guess the inverse automatically. First, the
595
640
  # <tt>inverse_of</tt> option cannot be set to false. Second, we must
596
641
  # have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
597
- # Third, we must not have options such as <tt>:polymorphic</tt> or
598
- # <tt>:foreign_key</tt> which prevent us from correctly guessing the
599
- # inverse association.
642
+ # Third, we must not have options such as <tt>:foreign_key</tt>
643
+ # which prevent us from correctly guessing the inverse association.
600
644
  #
601
645
  # Anything with a scope can additionally ruin our attempt at finding an
602
646
  # inverse, so we exclude reflections with scopes.
@@ -626,10 +670,6 @@ module ActiveRecord
626
670
  def derive_join_table
627
671
  ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
628
672
  end
629
-
630
- def primary_key(klass)
631
- klass.primary_key || raise(UnknownPrimaryKey.new(klass))
632
- end
633
673
  end
634
674
 
635
675
  class HasManyReflection < AssociationReflection # :nodoc:
@@ -683,16 +723,18 @@ module ActiveRecord
683
723
  end
684
724
  end
685
725
 
686
- def join_keys(association_klass)
687
- key = polymorphic? ? association_primary_key(association_klass) : association_primary_key
688
- JoinKeys.new(key, foreign_key)
726
+ def join_primary_key(klass = nil)
727
+ polymorphic? ? association_primary_key(klass) : association_primary_key
689
728
  end
690
729
 
691
- def join_id_for(owner) # :nodoc:
692
- owner[foreign_key]
730
+ def join_foreign_key
731
+ foreign_key
693
732
  end
694
733
 
695
734
  private
735
+ def can_find_inverse_of_automatically?(_)
736
+ !polymorphic? && super
737
+ end
696
738
 
697
739
  def calculate_constructable(macro, options)
698
740
  !polymorphic?
@@ -700,10 +742,6 @@ module ActiveRecord
700
742
  end
701
743
 
702
744
  class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
703
- def initialize(name, scope, options, active_record)
704
- super
705
- end
706
-
707
745
  def macro; :has_and_belongs_to_many; end
708
746
 
709
747
  def collection?
@@ -711,16 +749,15 @@ module ActiveRecord
711
749
  end
712
750
  end
713
751
 
714
- # Holds all the meta-data about a :through association as it was specified
752
+ # Holds all the metadata about a :through association as it was specified
715
753
  # in the Active Record class.
716
754
  class ThroughReflection < AbstractReflection #:nodoc:
717
- attr_reader :delegate_reflection
718
- delegate :foreign_key, :foreign_type, :association_foreign_key,
719
- :active_record_primary_key, :type, :to => :source_reflection
755
+ delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
756
+ :active_record_primary_key, :type, :get_join_keys, to: :source_reflection
720
757
 
721
758
  def initialize(delegate_reflection)
722
759
  @delegate_reflection = delegate_reflection
723
- @klass = delegate_reflection.options[:anonymous_class]
760
+ @klass = delegate_reflection.options[:anonymous_class]
724
761
  @source_reflection_name = delegate_reflection.options[:source]
725
762
  end
726
763
 
@@ -798,45 +835,12 @@ module ActiveRecord
798
835
  through_reflection.clear_association_scope_cache
799
836
  end
800
837
 
801
- # Consider the following example:
802
- #
803
- # class Person
804
- # has_many :articles
805
- # has_many :comment_tags, through: :articles
806
- # end
807
- #
808
- # class Article
809
- # has_many :comments
810
- # has_many :comment_tags, through: :comments, source: :tags
811
- # end
812
- #
813
- # class Comment
814
- # has_many :tags
815
- # end
816
- #
817
- # There may be scopes on Person.comment_tags, Article.comment_tags and/or Comment.tags,
818
- # but only Comment.tags will be represented in the #chain. So this method creates an array
819
- # of scopes corresponding to the chain.
820
- def scope_chain
821
- @scope_chain ||= begin
822
- scope_chain = source_reflection.scope_chain.map(&:dup)
823
-
824
- # Add to it the scope from this reflection (if any)
825
- scope_chain.first << scope if scope
826
-
827
- through_scope_chain = through_reflection.scope_chain.map(&:dup)
828
-
829
- if options[:source_type]
830
- type = foreign_type
831
- source_type = options[:source_type]
832
- through_scope_chain.first << lambda { |object|
833
- where(type => source_type)
834
- }
835
- end
838
+ def scopes
839
+ source_reflection.scopes + super
840
+ end
836
841
 
837
- # Recursively fill out the rest of the array from the through reflection
838
- scope_chain + through_scope_chain
839
- end
842
+ def join_scopes(table, predicate_builder) # :nodoc:
843
+ source_reflection.join_scopes(table, predicate_builder) + super
840
844
  end
841
845
 
842
846
  def has_scope?
@@ -845,10 +849,6 @@ module ActiveRecord
845
849
  through_reflection.has_scope?
846
850
  end
847
851
 
848
- def join_keys(association_klass)
849
- source_reflection.join_keys(association_klass)
850
- end
851
-
852
852
  # A through association is nested if there would be more than one join table
853
853
  def nested?
854
854
  source_reflection.through_reflection? || through_reflection.through_reflection?
@@ -863,10 +863,6 @@ module ActiveRecord
863
863
  actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
864
864
  end
865
865
 
866
- def association_primary_key_type
867
- klass.type_for_attribute(association_primary_key.to_s)
868
- end
869
-
870
866
  # Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
871
867
  #
872
868
  # class Post < ActiveRecord::Base
@@ -891,15 +887,13 @@ module ActiveRecord
891
887
  }
892
888
 
893
889
  if names.length > 1
894
- example_options = options.dup
895
- example_options[:source] = source_reflection_names.first
896
- ActiveSupport::Deprecation.warn \
897
- "Ambiguous source reflection for through association. Please " \
898
- "specify a :source directive on your declaration like:\n" \
899
- "\n" \
900
- " class #{active_record.name} < ActiveRecord::Base\n" \
901
- " #{macro} :#{name}, #{example_options}\n" \
902
- " end"
890
+ raise AmbiguousSourceReflectionForThroughAssociation.new(
891
+ active_record.name,
892
+ macro,
893
+ name,
894
+ options,
895
+ source_reflection_names
896
+ )
903
897
  end
904
898
 
905
899
  @source_reflection_name = names.first
@@ -913,10 +907,6 @@ module ActiveRecord
913
907
  through_reflection.options
914
908
  end
915
909
 
916
- def join_id_for(owner) # :nodoc:
917
- source_reflection.join_id_for(owner)
918
- end
919
-
920
910
  def check_validity!
921
911
  if through_reflection.nil?
922
912
  raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
@@ -946,6 +936,14 @@ module ActiveRecord
946
936
  raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection)
947
937
  end
948
938
 
939
+ if parent_reflection.nil?
940
+ reflections = active_record.reflections.keys.map(&:to_sym)
941
+
942
+ if reflections.index(through_reflection.name) > reflections.index(name)
943
+ raise HasManyThroughOrderError.new(active_record.name, self, through_reflection)
944
+ end
945
+ end
946
+
949
947
  check_validity_of_inverse!
950
948
  end
951
949
 
@@ -967,28 +965,25 @@ module ActiveRecord
967
965
  collect_join_reflections(seed + [self])
968
966
  end
969
967
 
970
- def collect_join_reflections(seed)
971
- a = source_reflection.add_as_source seed
972
- if options[:source_type]
973
- through_reflection.add_as_polymorphic_through self, a
974
- else
975
- through_reflection.add_as_through a
976
- end
977
- end
978
-
979
968
  protected
980
-
981
969
  def actual_source_reflection # FIXME: this is a horrible name
982
- source_reflection.send(:actual_source_reflection)
970
+ source_reflection.actual_source_reflection
983
971
  end
984
972
 
985
- def primary_key(klass)
986
- klass.primary_key || raise(UnknownPrimaryKey.new(klass))
973
+ private
974
+ attr_reader :delegate_reflection
975
+
976
+ def collect_join_reflections(seed)
977
+ a = source_reflection.add_as_source seed
978
+ if options[:source_type]
979
+ through_reflection.add_as_polymorphic_through self, a
980
+ else
981
+ through_reflection.add_as_through a
982
+ end
987
983
  end
988
984
 
989
985
  def inverse_name; delegate_reflection.send(:inverse_name); end
990
986
 
991
- private
992
987
  def derive_class_name
993
988
  # get the class_name of the belongs_to association of the through reflection
994
989
  options[:source_type] || source_reflection.class_name
@@ -998,52 +993,35 @@ module ActiveRecord
998
993
  public_instance_methods
999
994
 
1000
995
  delegate(*delegate_methods, to: :delegate_reflection)
1001
-
1002
996
  end
1003
997
 
1004
- class PolymorphicReflection < ThroughReflection # :nodoc:
998
+ class PolymorphicReflection < AbstractReflection # :nodoc:
999
+ delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
1000
+
1005
1001
  def initialize(reflection, previous_reflection)
1006
1002
  @reflection = reflection
1007
1003
  @previous_reflection = previous_reflection
1008
1004
  end
1009
1005
 
1010
- def klass
1011
- @reflection.klass
1012
- end
1013
-
1014
- def scope
1015
- @reflection.scope
1016
- end
1017
-
1018
- def table_name
1019
- @reflection.table_name
1020
- end
1021
-
1022
- def plural_name
1023
- @reflection.plural_name
1024
- end
1025
-
1026
- def join_keys(association_klass)
1027
- @reflection.join_keys(association_klass)
1028
- end
1029
-
1030
- def type
1031
- @reflection.type
1006
+ def join_scopes(table, predicate_builder) # :nodoc:
1007
+ scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
1008
+ scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
1032
1009
  end
1033
1010
 
1034
1011
  def constraints
1035
- @reflection.constraints + [source_type_info]
1012
+ @reflection.constraints + [source_type_scope]
1036
1013
  end
1037
1014
 
1038
- def source_type_info
1039
- type = @previous_reflection.foreign_type
1040
- source_type = @previous_reflection.options[:source_type]
1041
- lambda { |object| where(type => source_type) }
1042
- end
1015
+ private
1016
+ def source_type_scope
1017
+ type = @previous_reflection.foreign_type
1018
+ source_type = @previous_reflection.options[:source_type]
1019
+ lambda { |object| where(type => source_type) }
1020
+ end
1043
1021
  end
1044
1022
 
1045
- class RuntimeReflection < PolymorphicReflection # :nodoc:
1046
- attr_accessor :next
1023
+ class RuntimeReflection < AbstractReflection # :nodoc:
1024
+ delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
1047
1025
 
1048
1026
  def initialize(reflection, association)
1049
1027
  @reflection = reflection
@@ -1054,24 +1032,8 @@ module ActiveRecord
1054
1032
  @association.klass
1055
1033
  end
1056
1034
 
1057
- def table_name
1058
- klass.table_name
1059
- end
1060
-
1061
- def constraints
1062
- @reflection.constraints
1063
- end
1064
-
1065
- def source_type_info
1066
- @reflection.source_type_info
1067
- end
1068
-
1069
- def alias_candidate(name)
1070
- "#{plural_name}_#{name}_join"
1071
- end
1072
-
1073
- def alias_name
1074
- Arel::Table.new(table_name)
1035
+ def aliased_table
1036
+ @aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
1075
1037
  end
1076
1038
 
1077
1039
  def all_includes; yield; end