activerecord 5.0.7.2 → 6.0.3.4

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

Potentially problematic release.


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

Files changed (359) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +708 -2040
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +9 -7
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record.rb +37 -22
  8. data/lib/active_record/advisory_lock_base.rb +18 -0
  9. data/lib/active_record/aggregations.rb +249 -247
  10. data/lib/active_record/association_relation.rb +18 -14
  11. data/lib/active_record/associations.rb +1603 -1592
  12. data/lib/active_record/associations/alias_tracker.rb +24 -34
  13. data/lib/active_record/associations/association.rb +114 -55
  14. data/lib/active_record/associations/association_scope.rb +94 -94
  15. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  16. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  17. data/lib/active_record/associations/builder/association.rb +18 -25
  18. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  19. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  20. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
  21. data/lib/active_record/associations/builder/has_many.rb +4 -0
  22. data/lib/active_record/associations/builder/has_one.rb +37 -1
  23. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  24. data/lib/active_record/associations/collection_association.rb +86 -254
  25. data/lib/active_record/associations/collection_proxy.rb +158 -122
  26. data/lib/active_record/associations/foreign_association.rb +9 -0
  27. data/lib/active_record/associations/has_many_association.rb +23 -30
  28. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  29. data/lib/active_record/associations/has_one_association.rb +59 -54
  30. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  31. data/lib/active_record/associations/join_dependency.rb +143 -176
  32. data/lib/active_record/associations/join_dependency/join_association.rb +38 -87
  33. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  34. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  35. data/lib/active_record/associations/preloader.rb +90 -103
  36. data/lib/active_record/associations/preloader/association.rb +86 -100
  37. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  38. data/lib/active_record/associations/singular_association.rb +12 -45
  39. data/lib/active_record/associations/through_association.rb +26 -14
  40. data/lib/active_record/attribute_assignment.rb +54 -61
  41. data/lib/active_record/attribute_decorators.rb +38 -17
  42. data/lib/active_record/attribute_methods.rb +66 -106
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
  44. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  45. data/lib/active_record/attribute_methods/primary_key.rb +85 -92
  46. data/lib/active_record/attribute_methods/query.rb +4 -3
  47. data/lib/active_record/attribute_methods/read.rb +20 -49
  48. data/lib/active_record/attribute_methods/serialization.rb +29 -7
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
  50. data/lib/active_record/attribute_methods/write.rb +34 -33
  51. data/lib/active_record/attributes.rb +38 -25
  52. data/lib/active_record/autosave_association.rb +54 -35
  53. data/lib/active_record/base.rb +27 -24
  54. data/lib/active_record/callbacks.rb +64 -35
  55. data/lib/active_record/coders/json.rb +2 -0
  56. data/lib/active_record/coders/yaml_column.rb +11 -12
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +552 -323
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +228 -147
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -202
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +396 -562
  70. data/lib/active_record/connection_adapters/column.rb +41 -13
  71. data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  73. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  101. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -31
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
  118. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  120. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  121. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  122. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  123. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  124. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  127. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +259 -266
  128. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  129. data/lib/active_record/connection_handling.rb +143 -40
  130. data/lib/active_record/core.rb +201 -163
  131. data/lib/active_record/counter_cache.rb +60 -28
  132. data/lib/active_record/database_configurations.rb +233 -0
  133. data/lib/active_record/database_configurations/database_config.rb +37 -0
  134. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  135. data/lib/active_record/database_configurations/url_config.rb +78 -0
  136. data/lib/active_record/define_callbacks.rb +22 -0
  137. data/lib/active_record/dynamic_matchers.rb +87 -87
  138. data/lib/active_record/enum.rb +60 -23
  139. data/lib/active_record/errors.rb +114 -18
  140. data/lib/active_record/explain.rb +4 -4
  141. data/lib/active_record/explain_registry.rb +3 -1
  142. data/lib/active_record/explain_subscriber.rb +9 -4
  143. data/lib/active_record/fixture_set/file.rb +13 -8
  144. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  145. data/lib/active_record/fixture_set/render_context.rb +17 -0
  146. data/lib/active_record/fixture_set/table_row.rb +152 -0
  147. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  148. data/lib/active_record/fixtures.rb +194 -504
  149. data/lib/active_record/gem_version.rb +5 -3
  150. data/lib/active_record/inheritance.rb +150 -99
  151. data/lib/active_record/insert_all.rb +179 -0
  152. data/lib/active_record/integration.rb +116 -25
  153. data/lib/active_record/internal_metadata.rb +16 -19
  154. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  155. data/lib/active_record/locking/optimistic.rb +77 -87
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +48 -29
  158. data/lib/active_record/middleware/database_selector.rb +74 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +369 -302
  162. data/lib/active_record/migration/command_recorder.rb +134 -100
  163. data/lib/active_record/migration/compatibility.rb +174 -56
  164. data/lib/active_record/migration/join_table.rb +8 -7
  165. data/lib/active_record/model_schema.rb +131 -127
  166. data/lib/active_record/nested_attributes.rb +213 -202
  167. data/lib/active_record/no_touching.rb +12 -3
  168. data/lib/active_record/null_relation.rb +12 -34
  169. data/lib/active_record/persistence.rb +446 -77
  170. data/lib/active_record/query_cache.rb +13 -12
  171. data/lib/active_record/querying.rb +37 -24
  172. data/lib/active_record/railtie.rb +128 -36
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +312 -177
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +214 -252
  179. data/lib/active_record/relation.rb +440 -318
  180. data/lib/active_record/relation/batches.rb +98 -52
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  182. data/lib/active_record/relation/calculations.rb +212 -173
  183. data/lib/active_record/relation/delegation.rb +72 -69
  184. data/lib/active_record/relation/finder_methods.rb +207 -247
  185. data/lib/active_record/relation/from_clause.rb +6 -8
  186. data/lib/active_record/relation/merger.rb +78 -62
  187. data/lib/active_record/relation/predicate_builder.rb +83 -105
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  195. data/lib/active_record/relation/query_attribute.rb +33 -2
  196. data/lib/active_record/relation/query_methods.rb +476 -334
  197. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  198. data/lib/active_record/relation/spawn_methods.rb +8 -8
  199. data/lib/active_record/relation/where_clause.rb +111 -96
  200. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  201. data/lib/active_record/result.rb +69 -40
  202. data/lib/active_record/runtime_registry.rb +5 -3
  203. data/lib/active_record/sanitization.rb +83 -99
  204. data/lib/active_record/schema.rb +7 -14
  205. data/lib/active_record/schema_dumper.rb +71 -69
  206. data/lib/active_record/schema_migration.rb +16 -6
  207. data/lib/active_record/scoping.rb +20 -20
  208. data/lib/active_record/scoping/default.rb +92 -95
  209. data/lib/active_record/scoping/named.rb +47 -27
  210. data/lib/active_record/secure_token.rb +4 -2
  211. data/lib/active_record/serialization.rb +2 -0
  212. data/lib/active_record/statement_cache.rb +63 -28
  213. data/lib/active_record/store.rb +121 -41
  214. data/lib/active_record/suppressor.rb +6 -3
  215. data/lib/active_record/table_metadata.rb +39 -18
  216. data/lib/active_record/tasks/database_tasks.rb +271 -81
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +225 -0
  222. data/lib/active_record/timestamp.rb +70 -36
  223. data/lib/active_record/touch_later.rb +8 -6
  224. data/lib/active_record/transactions.rb +141 -157
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type.rb +23 -18
  227. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  228. data/lib/active_record/type/date.rb +2 -0
  229. data/lib/active_record/type/date_time.rb +2 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  232. data/lib/active_record/type/internal/timezone.rb +2 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +16 -9
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +2 -1
  237. data/lib/active_record/type/type_map.rb +14 -17
  238. data/lib/active_record/type/unsigned_integer.rb +16 -0
  239. data/lib/active_record/type_caster.rb +4 -2
  240. data/lib/active_record/type_caster/connection.rb +17 -12
  241. data/lib/active_record/type_caster/map.rb +5 -4
  242. data/lib/active_record/validations.rb +7 -5
  243. data/lib/active_record/validations/absence.rb +2 -0
  244. data/lib/active_record/validations/associated.rb +4 -3
  245. data/lib/active_record/validations/length.rb +2 -0
  246. data/lib/active_record/validations/presence.rb +4 -2
  247. data/lib/active_record/validations/uniqueness.rb +29 -42
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/arel.rb +62 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +256 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +203 -0
  317. data/lib/arel/visitors/dot.rb +296 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +156 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +158 -0
  323. data/lib/arel/visitors/oracle12.rb +65 -0
  324. data/lib/arel/visitors/postgresql.rb +109 -0
  325. data/lib/arel/visitors/sqlite.rb +38 -0
  326. data/lib/arel/visitors/to_sql.rb +888 -0
  327. data/lib/arel/visitors/visitor.rb +45 -0
  328. data/lib/arel/visitors/where_sql.rb +22 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +7 -5
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  332. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  333. data/lib/rails/generators/active_record/migration.rb +17 -3
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  335. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  336. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  337. data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
  338. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. metadata +137 -52
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  348. data/lib/active_record/attribute.rb +0 -213
  349. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  350. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/attribute_set/builder.rb +0 -132
  353. data/lib/active_record/collection_cache_key.rb +0 -50
  354. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  355. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  356. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  357. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  358. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  359. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,22 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ReadonlyAttributes
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  included do
6
- class_attribute :_attr_readonly, instance_accessor: false
7
- self._attr_readonly = []
8
+ class_attribute :_attr_readonly, instance_accessor: false, default: []
8
9
  end
9
10
 
10
11
  module ClassMethods
11
12
  # Attributes listed as readonly will be used to create a new record but update operations will
12
13
  # ignore these fields.
13
14
  def attr_readonly(*attributes)
14
- self._attr_readonly = Set.new(attributes.map(&:to_s)) + (self._attr_readonly || [])
15
+ self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
15
16
  end
16
17
 
17
18
  # Returns an array of all the attributes that have been specified as readonly.
18
19
  def readonly_attributes
19
- self._attr_readonly
20
+ _attr_readonly
20
21
  end
21
22
  end
22
23
  end
@@ -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,54 @@ 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
+ if type
187
+ klass_scope.where!(type => foreign_klass.polymorphic_name)
188
+ end
189
+
190
+ scope_chain_items.inject(klass_scope, &:merge!)
191
+
192
+ key = join_keys.key
193
+ foreign_key = join_keys.foreign_key
194
+
195
+ klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
196
+
197
+ if klass.finder_needs_type_condition?
198
+ klass_scope.where!(klass.send(:type_condition, table))
199
+ end
200
+
201
+ klass_scope
202
+ end
203
+
204
+ def join_scopes(table, predicate_builder) # :nodoc:
205
+ if scope
206
+ [scope_for(build_scope(table, predicate_builder))]
207
+ else
208
+ []
209
+ end
210
+ end
211
+
212
+ def klass_join_scope(table, predicate_builder) # :nodoc:
213
+ relation = build_scope(table, predicate_builder)
214
+ klass.scope_for_association(relation)
175
215
  end
176
216
 
177
217
  def constraints
178
- scope_chain.flatten
218
+ chain.flat_map(&:scopes)
179
219
  end
180
220
 
181
221
  def counter_cache_column
@@ -247,6 +287,40 @@ module ActiveRecord
247
287
  def chain
248
288
  collect_join_chain
249
289
  end
290
+
291
+ def get_join_keys(association_klass)
292
+ JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
293
+ end
294
+
295
+ def build_scope(table, predicate_builder = predicate_builder(table))
296
+ Relation.create(
297
+ klass,
298
+ table: table,
299
+ predicate_builder: predicate_builder
300
+ )
301
+ end
302
+
303
+ def join_primary_key(*)
304
+ foreign_key
305
+ end
306
+
307
+ def join_foreign_key
308
+ active_record_primary_key
309
+ end
310
+
311
+ protected
312
+ def actual_source_reflection # FIXME: this is a horrible name
313
+ self
314
+ end
315
+
316
+ private
317
+ def predicate_builder(table)
318
+ PredicateBuilder.new(TableMetadata.new(klass, table))
319
+ end
320
+
321
+ def primary_key(klass)
322
+ klass.primary_key || raise(UnknownPrimaryKey.new(klass))
323
+ end
250
324
  end
251
325
 
252
326
  # Base class for AggregateReflection and AssociationReflection. Objects of
@@ -281,7 +355,6 @@ module ActiveRecord
281
355
  end
282
356
 
283
357
  def autosave=(autosave)
284
- @automatic_inverse_of = false
285
358
  @options[:autosave] = autosave
286
359
  parent_reflection = self.parent_reflection
287
360
  if parent_reflection
@@ -293,6 +366,17 @@ module ActiveRecord
293
366
  #
294
367
  # <tt>composed_of :balance, class_name: 'Money'</tt> returns the Money class
295
368
  # <tt>has_many :clients</tt> returns the Client class
369
+ #
370
+ # class Company < ActiveRecord::Base
371
+ # has_many :clients
372
+ # end
373
+ #
374
+ # Company.reflect_on_association(:clients).klass
375
+ # # => Client
376
+ #
377
+ # <b>Note:</b> Do not call +klass.new+ or +klass.create+ to instantiate
378
+ # a new association object. Use +build_association+ or +create_association+
379
+ # instead. This allows plugins to hook into association object creation.
296
380
  def klass
297
381
  @klass ||= compute_class(class_name)
298
382
  end
@@ -311,8 +395,8 @@ module ActiveRecord
311
395
  active_record == other_aggregation.active_record
312
396
  end
313
397
 
314
- def scope_for(klass)
315
- scope ? klass.unscoped.instance_exec(nil, &scope) : klass.unscoped
398
+ def scope_for(relation, owner = nil)
399
+ relation.instance_exec(owner, &scope) || relation
316
400
  end
317
401
 
318
402
  private
@@ -321,8 +405,7 @@ module ActiveRecord
321
405
  end
322
406
  end
323
407
 
324
-
325
- # Holds all the meta-data about an aggregation as it was specified in the
408
+ # Holds all the metadata about an aggregation as it was specified in the
326
409
  # Active Record class.
327
410
  class AggregateReflection < MacroReflection #:nodoc:
328
411
  def mapping
@@ -331,26 +414,13 @@ module ActiveRecord
331
414
  end
332
415
  end
333
416
 
334
- # Holds all the meta-data about an association as it was specified in the
417
+ # Holds all the metadata about an association as it was specified in the
335
418
  # Active Record class.
336
419
  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
420
  def compute_class(name)
421
+ if polymorphic?
422
+ raise ArgumentError, "Polymorphic associations do not support computing the class."
423
+ end
354
424
  active_record.send(:compute_type, name)
355
425
  end
356
426
 
@@ -359,22 +429,22 @@ module ActiveRecord
359
429
 
360
430
  def initialize(name, scope, options, active_record)
361
431
  super
362
- @automatic_inverse_of = nil
363
432
  @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
364
- @foreign_type = options[:foreign_type] || "#{name}_type"
433
+ @foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
365
434
  @constructable = calculate_constructable(macro, options)
366
- @association_scope_cache = {}
367
- @scope_lock = Mutex.new
435
+ @association_scope_cache = Concurrent::Map.new
436
+
437
+ if options[:class_name] && options[:class_name].class == Class
438
+ raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
439
+ end
368
440
  end
369
441
 
370
- def association_scope_cache(conn, owner)
442
+ def association_scope_cache(conn, owner, &block)
371
443
  key = conn.prepared_statements
372
444
  if polymorphic?
373
445
  key = [key, owner._read_attribute(@foreign_type)]
374
446
  end
375
- @association_scope_cache[key] ||= @scope_lock.synchronize {
376
- @association_scope_cache[key] ||= yield
377
- }
447
+ @association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
378
448
  end
379
449
 
380
450
  def constructable? # :nodoc:
@@ -398,10 +468,6 @@ module ActiveRecord
398
468
  options[:primary_key] || primary_key(klass || self.klass)
399
469
  end
400
470
 
401
- def association_primary_key_type
402
- klass.type_for_attribute(association_primary_key.to_s)
403
- end
404
-
405
471
  def active_record_primary_key
406
472
  @active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
407
473
  end
@@ -413,7 +479,7 @@ module ActiveRecord
413
479
  def check_preloadable!
414
480
  return unless scope
415
481
 
416
- if scope.arity > 0
482
+ unless scope.arity == 0
417
483
  raise ArgumentError, <<-MSG.squish
418
484
  The association scope '#{name}' is instance dependent (the scope
419
485
  block takes an argument). Preloading instance dependent scopes is
@@ -424,7 +490,7 @@ module ActiveRecord
424
490
  alias :check_eager_loadable! :check_preloadable!
425
491
 
426
492
  def join_id_for(owner) # :nodoc:
427
- owner[active_record_primary_key]
493
+ owner[join_foreign_key]
428
494
  end
429
495
 
430
496
  def through_reflection
@@ -451,12 +517,6 @@ module ActiveRecord
451
517
  false
452
518
  end
453
519
 
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
520
  def has_scope?
461
521
  scope
462
522
  end
@@ -513,7 +573,7 @@ module ActiveRecord
513
573
  end
514
574
 
515
575
  VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
516
- INVALID_AUTOMATIC_INVERSE_OPTIONS = [:conditions, :through, :polymorphic, :foreign_key]
576
+ INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
517
577
 
518
578
  def add_as_source(seed)
519
579
  seed
@@ -531,32 +591,23 @@ module ActiveRecord
531
591
  Array(options[:extend])
532
592
  end
533
593
 
534
- protected
535
-
536
- def actual_source_reflection # FIXME: this is a horrible name
537
- self
538
- end
539
-
540
594
  private
541
-
542
595
  def calculate_constructable(macro, options)
543
596
  true
544
597
  end
545
598
 
546
599
  # Attempts to find the inverse association name automatically.
547
600
  # If it cannot find a suitable inverse association name, it returns
548
- # nil.
601
+ # +nil+.
549
602
  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
603
+ unless defined?(@inverse_name)
604
+ @inverse_name = options.fetch(:inverse_of) { automatic_inverse_of }
556
605
  end
606
+
607
+ @inverse_name
557
608
  end
558
609
 
559
- # returns either false or the inverse association name that it finds.
610
+ # returns either +nil+ or the inverse association name that it finds.
560
611
  def automatic_inverse_of
561
612
  if can_find_inverse_of_automatically?(self)
562
613
  inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
@@ -570,23 +621,18 @@ module ActiveRecord
570
621
  end
571
622
 
572
623
  if valid_inverse_reflection?(reflection)
573
- return inverse_name
624
+ inverse_name
574
625
  end
575
626
  end
576
-
577
- false
578
627
  end
579
628
 
580
629
  # Checks if the inverse reflection that is returned from the
581
630
  # +automatic_inverse_of+ method is a valid reflection. We must
582
631
  # make sure that the reflection's active_record name matches up
583
632
  # 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
633
  def valid_inverse_reflection?(reflection)
588
634
  reflection &&
589
- klass.name == reflection.active_record.name &&
635
+ klass <= reflection.active_record &&
590
636
  can_find_inverse_of_automatically?(reflection)
591
637
  end
592
638
 
@@ -594,9 +640,8 @@ module ActiveRecord
594
640
  # us from being able to guess the inverse automatically. First, the
595
641
  # <tt>inverse_of</tt> option cannot be set to false. Second, we must
596
642
  # 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.
643
+ # Third, we must not have options such as <tt>:foreign_key</tt>
644
+ # which prevent us from correctly guessing the inverse association.
600
645
  #
601
646
  # Anything with a scope can additionally ruin our attempt at finding an
602
647
  # inverse, so we exclude reflections with scopes.
@@ -626,10 +671,6 @@ module ActiveRecord
626
671
  def derive_join_table
627
672
  ModelSchema.derive_join_table_name active_record.table_name, klass.table_name
628
673
  end
629
-
630
- def primary_key(klass)
631
- klass.primary_key || raise(UnknownPrimaryKey.new(klass))
632
- end
633
674
  end
634
675
 
635
676
  class HasManyReflection < AssociationReflection # :nodoc:
@@ -664,7 +705,6 @@ module ActiveRecord
664
705
  end
665
706
 
666
707
  private
667
-
668
708
  def calculate_constructable(macro, options)
669
709
  !options[:through]
670
710
  end
@@ -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