activerecord 5.2.8 → 7.0.2

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 (364) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1393 -587
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +10 -9
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +122 -47
  10. data/lib/active_record/associations/association_scope.rb +24 -24
  11. data/lib/active_record/associations/belongs_to_association.rb +67 -49
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -7
  13. data/lib/active_record/associations/builder/association.rb +52 -23
  14. data/lib/active_record/associations/builder/belongs_to.rb +44 -61
  15. data/lib/active_record/associations/builder/collection_association.rb +17 -19
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +10 -3
  18. data/lib/active_record/associations/builder/has_one.rb +35 -3
  19. data/lib/active_record/associations/builder/singular_association.rb +5 -3
  20. data/lib/active_record/associations/collection_association.rb +59 -50
  21. data/lib/active_record/associations/collection_proxy.rb +32 -23
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/foreign_association.rb +20 -0
  24. data/lib/active_record/associations/has_many_association.rb +27 -14
  25. data/lib/active_record/associations/has_many_through_association.rb +26 -19
  26. data/lib/active_record/associations/has_one_association.rb +52 -37
  27. data/lib/active_record/associations/has_one_through_association.rb +6 -6
  28. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  29. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  30. data/lib/active_record/associations/join_dependency.rb +97 -62
  31. data/lib/active_record/associations/preloader/association.rb +220 -60
  32. data/lib/active_record/associations/preloader/batch.rb +48 -0
  33. data/lib/active_record/associations/preloader/branch.rb +147 -0
  34. data/lib/active_record/associations/preloader/through_association.rb +85 -40
  35. data/lib/active_record/associations/preloader.rb +44 -105
  36. data/lib/active_record/associations/singular_association.rb +9 -17
  37. data/lib/active_record/associations/through_association.rb +4 -4
  38. data/lib/active_record/associations.rb +207 -66
  39. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  40. data/lib/active_record/attribute_assignment.rb +17 -19
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +19 -8
  42. data/lib/active_record/attribute_methods/dirty.rb +141 -47
  43. data/lib/active_record/attribute_methods/primary_key.rb +22 -27
  44. data/lib/active_record/attribute_methods/query.rb +6 -10
  45. data/lib/active_record/attribute_methods/read.rb +15 -55
  46. data/lib/active_record/attribute_methods/serialization.rb +77 -18
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +16 -18
  48. data/lib/active_record/attribute_methods/write.rb +18 -37
  49. data/lib/active_record/attribute_methods.rb +90 -153
  50. data/lib/active_record/attributes.rb +38 -12
  51. data/lib/active_record/autosave_association.rb +50 -50
  52. data/lib/active_record/base.rb +23 -18
  53. data/lib/active_record/callbacks.rb +159 -44
  54. data/lib/active_record/coders/yaml_column.rb +12 -3
  55. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
  58. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +92 -464
  59. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -51
  60. data/lib/active_record/connection_adapters/abstract/database_statements.rb +209 -164
  61. data/lib/active_record/connection_adapters/abstract/query_cache.rb +38 -22
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +103 -82
  63. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +140 -110
  65. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -94
  66. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +16 -5
  67. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +456 -159
  68. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -162
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +311 -327
  71. data/lib/active_record/connection_adapters/column.rb +33 -11
  72. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  73. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  74. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  75. data/lib/active_record/connection_adapters/mysql/database_statements.rb +113 -45
  76. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  77. data/lib/active_record/connection_adapters/mysql/quoting.rb +71 -5
  78. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  79. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  80. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +25 -8
  81. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +143 -19
  82. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  83. data/lib/active_record/connection_adapters/mysql2_adapter.rb +63 -22
  84. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  85. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +53 -28
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +56 -63
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +54 -16
  95. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +26 -12
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -52
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -2
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +39 -4
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +128 -91
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -1
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +149 -113
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +386 -182
  116. data/lib/active_record/connection_adapters/schema_cache.rb +161 -22
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +152 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +65 -18
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +92 -26
  122. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +251 -204
  123. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  124. data/lib/active_record/connection_adapters.rb +53 -0
  125. data/lib/active_record/connection_handling.rb +292 -38
  126. data/lib/active_record/core.rb +385 -158
  127. data/lib/active_record/counter_cache.rb +8 -30
  128. data/lib/active_record/database_configurations/connection_url_resolver.rb +100 -0
  129. data/lib/active_record/database_configurations/database_config.rb +83 -0
  130. data/lib/active_record/database_configurations/hash_config.rb +154 -0
  131. data/lib/active_record/database_configurations/url_config.rb +53 -0
  132. data/lib/active_record/database_configurations.rb +256 -0
  133. data/lib/active_record/delegated_type.rb +250 -0
  134. data/lib/active_record/destroy_association_async_job.rb +36 -0
  135. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  136. data/lib/active_record/dynamic_matchers.rb +4 -5
  137. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  138. data/lib/active_record/encryption/cipher.rb +53 -0
  139. data/lib/active_record/encryption/config.rb +44 -0
  140. data/lib/active_record/encryption/configurable.rb +61 -0
  141. data/lib/active_record/encryption/context.rb +35 -0
  142. data/lib/active_record/encryption/contexts.rb +72 -0
  143. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  144. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  145. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  146. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  147. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  148. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  149. data/lib/active_record/encryption/encryptor.rb +155 -0
  150. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  151. data/lib/active_record/encryption/errors.rb +15 -0
  152. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  153. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  154. data/lib/active_record/encryption/key.rb +28 -0
  155. data/lib/active_record/encryption/key_generator.rb +42 -0
  156. data/lib/active_record/encryption/key_provider.rb +46 -0
  157. data/lib/active_record/encryption/message.rb +33 -0
  158. data/lib/active_record/encryption/message_serializer.rb +90 -0
  159. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  160. data/lib/active_record/encryption/properties.rb +76 -0
  161. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  162. data/lib/active_record/encryption/scheme.rb +99 -0
  163. data/lib/active_record/encryption.rb +55 -0
  164. data/lib/active_record/enum.rb +130 -51
  165. data/lib/active_record/errors.rb +129 -23
  166. data/lib/active_record/explain.rb +10 -6
  167. data/lib/active_record/explain_registry.rb +11 -6
  168. data/lib/active_record/explain_subscriber.rb +1 -1
  169. data/lib/active_record/fixture_set/file.rb +22 -15
  170. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  171. data/lib/active_record/fixture_set/render_context.rb +17 -0
  172. data/lib/active_record/fixture_set/table_row.rb +187 -0
  173. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  174. data/lib/active_record/fixtures.rb +206 -490
  175. data/lib/active_record/future_result.rb +139 -0
  176. data/lib/active_record/gem_version.rb +3 -3
  177. data/lib/active_record/inheritance.rb +104 -37
  178. data/lib/active_record/insert_all.rb +278 -0
  179. data/lib/active_record/integration.rb +69 -18
  180. data/lib/active_record/internal_metadata.rb +24 -9
  181. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  182. data/lib/active_record/locking/optimistic.rb +41 -26
  183. data/lib/active_record/locking/pessimistic.rb +18 -8
  184. data/lib/active_record/log_subscriber.rb +46 -35
  185. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  186. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  187. data/lib/active_record/middleware/database_selector.rb +82 -0
  188. data/lib/active_record/middleware/shard_selector.rb +60 -0
  189. data/lib/active_record/migration/command_recorder.rb +96 -44
  190. data/lib/active_record/migration/compatibility.rb +246 -64
  191. data/lib/active_record/migration/join_table.rb +1 -2
  192. data/lib/active_record/migration.rb +266 -187
  193. data/lib/active_record/model_schema.rb +165 -52
  194. data/lib/active_record/nested_attributes.rb +17 -19
  195. data/lib/active_record/no_touching.rb +11 -4
  196. data/lib/active_record/null_relation.rb +2 -7
  197. data/lib/active_record/persistence.rb +467 -92
  198. data/lib/active_record/query_cache.rb +21 -4
  199. data/lib/active_record/query_logs.rb +138 -0
  200. data/lib/active_record/querying.rb +51 -24
  201. data/lib/active_record/railtie.rb +224 -57
  202. data/lib/active_record/railties/console_sandbox.rb +2 -4
  203. data/lib/active_record/railties/controller_runtime.rb +31 -36
  204. data/lib/active_record/railties/databases.rake +369 -101
  205. data/lib/active_record/readonly_attributes.rb +15 -0
  206. data/lib/active_record/reflection.rb +170 -137
  207. data/lib/active_record/relation/batches/batch_enumerator.rb +44 -14
  208. data/lib/active_record/relation/batches.rb +46 -37
  209. data/lib/active_record/relation/calculations.rb +168 -96
  210. data/lib/active_record/relation/delegation.rb +37 -52
  211. data/lib/active_record/relation/finder_methods.rb +79 -58
  212. data/lib/active_record/relation/from_clause.rb +5 -1
  213. data/lib/active_record/relation/merger.rb +50 -51
  214. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  215. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  216. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  217. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  218. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  219. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  220. data/lib/active_record/relation/predicate_builder.rb +58 -46
  221. data/lib/active_record/relation/query_attribute.rb +9 -10
  222. data/lib/active_record/relation/query_methods.rb +685 -208
  223. data/lib/active_record/relation/record_fetch_warning.rb +9 -11
  224. data/lib/active_record/relation/spawn_methods.rb +10 -10
  225. data/lib/active_record/relation/where_clause.rb +108 -64
  226. data/lib/active_record/relation.rb +515 -151
  227. data/lib/active_record/result.rb +78 -42
  228. data/lib/active_record/runtime_registry.rb +9 -13
  229. data/lib/active_record/sanitization.rb +29 -44
  230. data/lib/active_record/schema.rb +37 -31
  231. data/lib/active_record/schema_dumper.rb +74 -23
  232. data/lib/active_record/schema_migration.rb +7 -9
  233. data/lib/active_record/scoping/default.rb +62 -17
  234. data/lib/active_record/scoping/named.rb +17 -32
  235. data/lib/active_record/scoping.rb +70 -41
  236. data/lib/active_record/secure_token.rb +16 -8
  237. data/lib/active_record/serialization.rb +6 -4
  238. data/lib/active_record/signed_id.rb +116 -0
  239. data/lib/active_record/statement_cache.rb +49 -6
  240. data/lib/active_record/store.rb +88 -9
  241. data/lib/active_record/suppressor.rb +13 -17
  242. data/lib/active_record/table_metadata.rb +42 -43
  243. data/lib/active_record/tasks/database_tasks.rb +352 -94
  244. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  245. data/lib/active_record/tasks/postgresql_database_tasks.rb +41 -39
  246. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  247. data/lib/active_record/test_databases.rb +24 -0
  248. data/lib/active_record/test_fixtures.rb +287 -0
  249. data/lib/active_record/timestamp.rb +44 -34
  250. data/lib/active_record/touch_later.rb +23 -22
  251. data/lib/active_record/transactions.rb +67 -128
  252. data/lib/active_record/translation.rb +3 -3
  253. data/lib/active_record/type/adapter_specific_registry.rb +34 -19
  254. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  255. data/lib/active_record/type/internal/timezone.rb +2 -2
  256. data/lib/active_record/type/serialized.rb +7 -4
  257. data/lib/active_record/type/time.rb +10 -0
  258. data/lib/active_record/type/type_map.rb +17 -21
  259. data/lib/active_record/type/unsigned_integer.rb +0 -1
  260. data/lib/active_record/type.rb +9 -5
  261. data/lib/active_record/type_caster/connection.rb +15 -15
  262. data/lib/active_record/type_caster/map.rb +8 -8
  263. data/lib/active_record/validations/associated.rb +2 -3
  264. data/lib/active_record/validations/numericality.rb +35 -0
  265. data/lib/active_record/validations/uniqueness.rb +39 -31
  266. data/lib/active_record/validations.rb +4 -3
  267. data/lib/active_record.rb +209 -32
  268. data/lib/arel/alias_predication.rb +9 -0
  269. data/lib/arel/attributes/attribute.rb +33 -0
  270. data/lib/arel/collectors/bind.rb +29 -0
  271. data/lib/arel/collectors/composite.rb +39 -0
  272. data/lib/arel/collectors/plain_string.rb +20 -0
  273. data/lib/arel/collectors/sql_string.rb +27 -0
  274. data/lib/arel/collectors/substitute_binds.rb +35 -0
  275. data/lib/arel/crud.rb +48 -0
  276. data/lib/arel/delete_manager.rb +32 -0
  277. data/lib/arel/errors.rb +9 -0
  278. data/lib/arel/expressions.rb +29 -0
  279. data/lib/arel/factory_methods.rb +49 -0
  280. data/lib/arel/filter_predications.rb +9 -0
  281. data/lib/arel/insert_manager.rb +48 -0
  282. data/lib/arel/math.rb +45 -0
  283. data/lib/arel/nodes/and.rb +32 -0
  284. data/lib/arel/nodes/ascending.rb +23 -0
  285. data/lib/arel/nodes/binary.rb +126 -0
  286. data/lib/arel/nodes/bind_param.rb +44 -0
  287. data/lib/arel/nodes/case.rb +55 -0
  288. data/lib/arel/nodes/casted.rb +62 -0
  289. data/lib/arel/nodes/comment.rb +29 -0
  290. data/lib/arel/nodes/count.rb +12 -0
  291. data/lib/arel/nodes/delete_statement.rb +44 -0
  292. data/lib/arel/nodes/descending.rb +23 -0
  293. data/lib/arel/nodes/equality.rb +15 -0
  294. data/lib/arel/nodes/extract.rb +24 -0
  295. data/lib/arel/nodes/false.rb +16 -0
  296. data/lib/arel/nodes/filter.rb +10 -0
  297. data/lib/arel/nodes/full_outer_join.rb +8 -0
  298. data/lib/arel/nodes/function.rb +45 -0
  299. data/lib/arel/nodes/grouping.rb +11 -0
  300. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  301. data/lib/arel/nodes/in.rb +15 -0
  302. data/lib/arel/nodes/infix_operation.rb +92 -0
  303. data/lib/arel/nodes/inner_join.rb +8 -0
  304. data/lib/arel/nodes/insert_statement.rb +37 -0
  305. data/lib/arel/nodes/join_source.rb +20 -0
  306. data/lib/arel/nodes/matches.rb +18 -0
  307. data/lib/arel/nodes/named_function.rb +23 -0
  308. data/lib/arel/nodes/node.rb +51 -0
  309. data/lib/arel/nodes/node_expression.rb +13 -0
  310. data/lib/arel/nodes/ordering.rb +27 -0
  311. data/lib/arel/nodes/outer_join.rb +8 -0
  312. data/lib/arel/nodes/over.rb +15 -0
  313. data/lib/arel/nodes/regexp.rb +16 -0
  314. data/lib/arel/nodes/right_outer_join.rb +8 -0
  315. data/lib/arel/nodes/select_core.rb +67 -0
  316. data/lib/arel/nodes/select_statement.rb +41 -0
  317. data/lib/arel/nodes/sql_literal.rb +19 -0
  318. data/lib/arel/nodes/string_join.rb +11 -0
  319. data/lib/arel/nodes/table_alias.rb +31 -0
  320. data/lib/arel/nodes/terminal.rb +16 -0
  321. data/lib/arel/nodes/true.rb +16 -0
  322. data/lib/arel/nodes/unary.rb +44 -0
  323. data/lib/arel/nodes/unary_operation.rb +20 -0
  324. data/lib/arel/nodes/unqualified_column.rb +22 -0
  325. data/lib/arel/nodes/update_statement.rb +46 -0
  326. data/lib/arel/nodes/values_list.rb +9 -0
  327. data/lib/arel/nodes/window.rb +126 -0
  328. data/lib/arel/nodes/with.rb +11 -0
  329. data/lib/arel/nodes.rb +71 -0
  330. data/lib/arel/order_predications.rb +13 -0
  331. data/lib/arel/predications.rb +258 -0
  332. data/lib/arel/select_manager.rb +276 -0
  333. data/lib/arel/table.rb +117 -0
  334. data/lib/arel/tree_manager.rb +60 -0
  335. data/lib/arel/update_manager.rb +48 -0
  336. data/lib/arel/visitors/dot.rb +298 -0
  337. data/lib/arel/visitors/mysql.rb +99 -0
  338. data/lib/arel/visitors/postgresql.rb +110 -0
  339. data/lib/arel/visitors/sqlite.rb +38 -0
  340. data/lib/arel/visitors/to_sql.rb +955 -0
  341. data/lib/arel/visitors/visitor.rb +45 -0
  342. data/lib/arel/visitors.rb +13 -0
  343. data/lib/arel/window_predications.rb +9 -0
  344. data/lib/arel.rb +55 -0
  345. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  346. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  347. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  348. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  349. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  350. data/lib/rails/generators/active_record/migration.rb +19 -2
  351. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  352. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  353. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  354. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  355. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  356. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  357. metadata +162 -32
  358. data/lib/active_record/attribute_decorators.rb +0 -90
  359. data/lib/active_record/collection_cache_key.rb +0 -53
  360. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  361. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  362. data/lib/active_record/define_callbacks.rb +0 -22
  363. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  364. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -11,6 +11,17 @@ module ActiveRecord
11
11
  module ClassMethods
12
12
  # Attributes listed as readonly will be used to create a new record but update operations will
13
13
  # ignore these fields.
14
+ #
15
+ # You can assign a new value to a readonly attribute, but it will be ignored when the record is updated.
16
+ #
17
+ # ==== Examples
18
+ #
19
+ # class Post < ActiveRecord::Base
20
+ # attr_readonly :title
21
+ # end
22
+ #
23
+ # post = Post.create!(title: "Introducing Ruby on Rails!")
24
+ # post.update(title: "a different title") # change to title will be ignored
14
25
  def attr_readonly(*attributes)
15
26
  self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
16
27
  end
@@ -19,6 +30,10 @@ module ActiveRecord
19
30
  def readonly_attributes
20
31
  _attr_readonly
21
32
  end
33
+
34
+ def readonly_attribute?(name) # :nodoc:
35
+ _attr_readonly.include?(name)
36
+ end
22
37
  end
23
38
  end
24
39
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/string/filters"
4
- require "concurrent/map"
5
4
 
6
5
  module ActiveRecord
7
6
  # = Active Record Reflection
@@ -11,35 +10,40 @@ module ActiveRecord
11
10
  included do
12
11
  class_attribute :_reflections, instance_writer: false, default: {}
13
12
  class_attribute :aggregate_reflections, instance_writer: false, default: {}
13
+ class_attribute :automatic_scope_inversing, instance_writer: false, default: false
14
14
  end
15
15
 
16
- def self.create(macro, name, scope, options, ar)
17
- klass = \
18
- case macro
19
- when :composed_of
20
- AggregateReflection
21
- when :has_many
22
- HasManyReflection
23
- when :has_one
24
- HasOneReflection
25
- when :belongs_to
26
- BelongsToReflection
27
- else
28
- raise "Unsupported Macro: #{macro}"
29
- 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
30
21
 
31
- reflection = klass.new(name, scope, options, ar)
32
- options[:through] ? ThroughReflection.new(reflection) : reflection
33
- 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
34
27
 
35
- def self.add_reflection(ar, name, reflection)
36
- ar.clear_reflections_cache
37
- name = name.to_s
38
- ar._reflections = ar._reflections.except(name).merge!(name => reflection)
39
- end
28
+ def add_aggregate_reflection(ar, name, reflection)
29
+ ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)
30
+ end
40
31
 
41
- def self.add_aggregate_reflection(ar, name, reflection)
42
- ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection)
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
43
47
  end
44
48
 
45
49
  # \Reflection enables the ability to examine the associations and aggregations of
@@ -112,7 +116,7 @@ module ActiveRecord
112
116
  reflections[association.to_s]
113
117
  end
114
118
 
115
- def _reflect_on_association(association) #:nodoc:
119
+ def _reflect_on_association(association) # :nodoc:
116
120
  _reflections[association.to_s]
117
121
  end
118
122
 
@@ -159,13 +163,7 @@ module ActiveRecord
159
163
  # <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
160
164
  # <tt>has_many :clients</tt> returns <tt>'Client'</tt>
161
165
  def class_name
162
- @class_name ||= (options[:class_name] || derive_class_name).to_s
163
- end
164
-
165
- JoinKeys = Struct.new(:key, :foreign_key) # :nodoc:
166
-
167
- def join_keys
168
- @join_keys ||= get_join_keys(klass)
166
+ @class_name ||= -(options[:class_name] || derive_class_name).to_s
169
167
  end
170
168
 
171
169
  # Returns a list of scopes that should be applied for this Reflection
@@ -179,25 +177,27 @@ module ActiveRecord
179
177
  scope_chain_items = join_scopes(table, predicate_builder)
180
178
  klass_scope = klass_join_scope(table, predicate_builder)
181
179
 
182
- key = join_keys.key
183
- foreign_key = join_keys.foreign_key
184
-
185
- klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
186
-
187
180
  if type
188
181
  klass_scope.where!(type => foreign_klass.polymorphic_name)
189
182
  end
190
183
 
184
+ scope_chain_items.inject(klass_scope, &:merge!)
185
+
186
+ primary_key = join_primary_key
187
+ foreign_key = join_foreign_key
188
+
189
+ klass_scope.where!(table[primary_key].eq(foreign_table[foreign_key]))
190
+
191
191
  if klass.finder_needs_type_condition?
192
192
  klass_scope.where!(klass.send(:type_condition, table))
193
193
  end
194
194
 
195
- scope_chain_items.inject(klass_scope, &:merge!)
195
+ klass_scope
196
196
  end
197
197
 
198
- def join_scopes(table, predicate_builder) # :nodoc:
198
+ def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
199
199
  if scope
200
- [scope_for(build_scope(table, predicate_builder))]
200
+ [scope_for(build_scope(table, predicate_builder, klass), record)]
201
201
  else
202
202
  []
203
203
  end
@@ -213,14 +213,14 @@ module ActiveRecord
213
213
  end
214
214
 
215
215
  def counter_cache_column
216
- if belongs_to?
216
+ @counter_cache_column ||= if belongs_to?
217
217
  if options[:counter_cache] == true
218
- "#{active_record.name.demodulize.underscore.pluralize}_count"
218
+ -"#{active_record.name.demodulize.underscore.pluralize}_count"
219
219
  elsif options[:counter_cache]
220
- options[:counter_cache].to_s
220
+ -options[:counter_cache].to_s
221
221
  end
222
222
  else
223
- options[:counter_cache] ? options[:counter_cache].to_s : "#{name}_count"
223
+ -(options[:counter_cache]&.to_s || "#{name}_count")
224
224
  end
225
225
  end
226
226
 
@@ -235,10 +235,13 @@ module ActiveRecord
235
235
  if has_inverse? && inverse_of.nil?
236
236
  raise InverseOfAssociationNotFoundError.new(self)
237
237
  end
238
+ if has_inverse? && inverse_of == self
239
+ raise InverseOfAssociationRecursiveError.new(self)
240
+ end
238
241
  end
239
242
  end
240
243
 
241
- # This shit is nasty. We need to avoid the following situation:
244
+ # We need to avoid the following situation:
242
245
  #
243
246
  # * An associated record is deleted via record.destroy
244
247
  # * Hence the callbacks run, and they find a belongs_to on the record with a
@@ -267,7 +270,7 @@ module ActiveRecord
267
270
  def has_cached_counter?
268
271
  options[:counter_cache] ||
269
272
  inverse_which_updates_counter_cache && inverse_which_updates_counter_cache.options[:counter_cache] &&
270
- !!active_record.columns_hash[counter_cache_column]
273
+ active_record.has_attribute?(counter_cache_column)
271
274
  end
272
275
 
273
276
  def counter_must_be_updated_by_has_many?
@@ -282,11 +285,7 @@ module ActiveRecord
282
285
  collect_join_chain
283
286
  end
284
287
 
285
- def get_join_keys(association_klass)
286
- JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
287
- end
288
-
289
- def build_scope(table, predicate_builder = predicate_builder(table))
288
+ def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)
290
289
  Relation.create(
291
290
  klass,
292
291
  table: table,
@@ -294,12 +293,8 @@ module ActiveRecord
294
293
  )
295
294
  end
296
295
 
297
- def join_primary_key(*)
298
- foreign_key
299
- end
300
-
301
- def join_foreign_key
302
- active_record_primary_key
296
+ def strict_loading?
297
+ options[:strict_loading]
303
298
  end
304
299
 
305
300
  protected
@@ -315,6 +310,12 @@ module ActiveRecord
315
310
  def primary_key(klass)
316
311
  klass.primary_key || raise(UnknownPrimaryKey.new(klass))
317
312
  end
313
+
314
+ def ensure_option_not_given_as_class!(option_name)
315
+ if options[option_name] && options[option_name].class == Class
316
+ raise ArgumentError, "A class was passed to `:#{option_name}` but we are expecting a string."
317
+ end
318
+ end
318
319
  end
319
320
 
320
321
  # Base class for AggregateReflection and AssociationReflection. Objects of
@@ -401,7 +402,7 @@ module ActiveRecord
401
402
 
402
403
  # Holds all the metadata about an aggregation as it was specified in the
403
404
  # Active Record class.
404
- class AggregateReflection < MacroReflection #:nodoc:
405
+ class AggregateReflection < MacroReflection # :nodoc:
405
406
  def mapping
406
407
  mapping = options[:mapping] || [name, name]
407
408
  mapping.first.is_a?(Array) ? mapping : [mapping]
@@ -410,12 +411,29 @@ module ActiveRecord
410
411
 
411
412
  # Holds all the metadata about an association as it was specified in the
412
413
  # Active Record class.
413
- class AssociationReflection < MacroReflection #:nodoc:
414
+ class AssociationReflection < MacroReflection # :nodoc:
414
415
  def compute_class(name)
415
416
  if polymorphic?
416
- raise ArgumentError, "Polymorphic association does not support to compute class."
417
+ raise ArgumentError, "Polymorphic associations do not support computing the class."
418
+ end
419
+
420
+ msg = <<-MSG.squish
421
+ Rails couldn't find a valid model for #{name} association.
422
+ Please provide the :class_name option on the association declaration.
423
+ If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.
424
+ MSG
425
+
426
+ begin
427
+ klass = active_record.send(:compute_type, name)
428
+
429
+ unless klass < ActiveRecord::Base
430
+ raise ArgumentError, msg
431
+ end
432
+
433
+ klass
434
+ rescue NameError
435
+ raise NameError, msg
417
436
  end
418
- active_record.send(:compute_type, name)
419
437
  end
420
438
 
421
439
  attr_reader :type, :foreign_type
@@ -423,65 +441,63 @@ module ActiveRecord
423
441
 
424
442
  def initialize(name, scope, options, active_record)
425
443
  super
426
- @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
427
- @foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
428
- @constructable = calculate_constructable(macro, options)
429
- @association_scope_cache = Concurrent::Map.new
444
+ @type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
445
+ @foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
430
446
 
431
- if options[:class_name] && options[:class_name].class == Class
432
- raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
433
- end
447
+ ensure_option_not_given_as_class!(:class_name)
434
448
  end
435
449
 
436
- def association_scope_cache(conn, owner, &block)
437
- key = conn.prepared_statements
450
+ def association_scope_cache(klass, owner, &block)
451
+ key = self
438
452
  if polymorphic?
439
453
  key = [key, owner._read_attribute(@foreign_type)]
440
454
  end
441
- @association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
442
- end
443
-
444
- def constructable? # :nodoc:
445
- @constructable
455
+ klass.cached_find_by_statement(key, &block)
446
456
  end
447
457
 
448
458
  def join_table
449
- @join_table ||= options[:join_table] || derive_join_table
459
+ @join_table ||= -(options[:join_table]&.to_s || derive_join_table)
450
460
  end
451
461
 
452
462
  def foreign_key
453
- @foreign_key ||= options[:foreign_key] || derive_foreign_key.freeze
463
+ @foreign_key ||= -(options[:foreign_key]&.to_s || derive_foreign_key)
454
464
  end
455
465
 
456
466
  def association_foreign_key
457
- @association_foreign_key ||= options[:association_foreign_key] || class_name.foreign_key
467
+ @association_foreign_key ||= -(options[:association_foreign_key]&.to_s || class_name.foreign_key)
458
468
  end
459
469
 
460
- # klass option is necessary to support loading polymorphic associations
461
470
  def association_primary_key(klass = nil)
462
- options[:primary_key] || primary_key(klass || self.klass)
471
+ primary_key(klass || self.klass)
463
472
  end
464
473
 
465
474
  def active_record_primary_key
466
- @active_record_primary_key ||= options[:primary_key] || primary_key(active_record)
475
+ @active_record_primary_key ||= -(options[:primary_key]&.to_s || primary_key(active_record))
476
+ end
477
+
478
+ def join_primary_key(klass = nil)
479
+ foreign_key
480
+ end
481
+
482
+ def join_foreign_key
483
+ active_record_primary_key
467
484
  end
468
485
 
469
486
  def check_validity!
470
487
  check_validity_of_inverse!
471
488
  end
472
489
 
473
- def check_preloadable!
490
+ def check_eager_loadable!
474
491
  return unless scope
475
492
 
476
- if scope.arity > 0
493
+ unless scope.arity == 0
477
494
  raise ArgumentError, <<-MSG.squish
478
495
  The association scope '#{name}' is instance dependent (the scope
479
- block takes an argument). Preloading instance dependent scopes is
480
- not supported.
496
+ block takes an argument). Eager loading instance dependent scopes
497
+ is not supported.
481
498
  MSG
482
499
  end
483
500
  end
484
- alias :check_eager_loadable! :check_preloadable!
485
501
 
486
502
  def join_id_for(owner) # :nodoc:
487
503
  owner[join_foreign_key]
@@ -504,7 +520,7 @@ module ActiveRecord
504
520
  # This is for clearing cache on the reflection. Useful for tests that need to compare
505
521
  # SQL queries on associations.
506
522
  def clear_association_scope_cache # :nodoc:
507
- @association_scope_cache.clear
523
+ klass.initialize_find_by_cache
508
524
  end
509
525
 
510
526
  def nested?
@@ -566,9 +582,6 @@ module ActiveRecord
566
582
  options[:polymorphic]
567
583
  end
568
584
 
569
- VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
570
- INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
571
-
572
585
  def add_as_source(seed)
573
586
  seed
574
587
  end
@@ -586,11 +599,6 @@ module ActiveRecord
586
599
  end
587
600
 
588
601
  private
589
-
590
- def calculate_constructable(macro, options)
591
- true
592
- end
593
-
594
602
  # Attempts to find the inverse association name automatically.
595
603
  # If it cannot find a suitable inverse association name, it returns
596
604
  # +nil+.
@@ -616,7 +624,7 @@ module ActiveRecord
616
624
  end
617
625
 
618
626
  if valid_inverse_reflection?(reflection)
619
- return inverse_name
627
+ inverse_name
620
628
  end
621
629
  end
622
630
  end
@@ -627,8 +635,10 @@ module ActiveRecord
627
635
  # with the current reflection's klass name.
628
636
  def valid_inverse_reflection?(reflection)
629
637
  reflection &&
638
+ reflection != self &&
639
+ foreign_key == reflection.foreign_key &&
630
640
  klass <= reflection.active_record &&
631
- can_find_inverse_of_automatically?(reflection)
641
+ can_find_inverse_of_automatically?(reflection, true)
632
642
  end
633
643
 
634
644
  # Checks to see if the reflection doesn't have any options that prevent
@@ -637,14 +647,25 @@ module ActiveRecord
637
647
  # have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
638
648
  # Third, we must not have options such as <tt>:foreign_key</tt>
639
649
  # which prevent us from correctly guessing the inverse association.
640
- #
641
- # Anything with a scope can additionally ruin our attempt at finding an
642
- # inverse, so we exclude reflections with scopes.
643
- def can_find_inverse_of_automatically?(reflection)
650
+ def can_find_inverse_of_automatically?(reflection, inverse_reflection = false)
644
651
  reflection.options[:inverse_of] != false &&
645
- VALID_AUTOMATIC_INVERSE_MACROS.include?(reflection.macro) &&
646
- !INVALID_AUTOMATIC_INVERSE_OPTIONS.any? { |opt| reflection.options[opt] } &&
652
+ !reflection.options[:through] &&
653
+ !reflection.options[:foreign_key] &&
654
+ scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
655
+ end
656
+
657
+ # Scopes on the potential inverse reflection prevent automatic
658
+ # <tt>inverse_of</tt>, since the scope could exclude the owner record
659
+ # we would inverse from. Scopes on the reflection itself allow for
660
+ # automatic <tt>inverse_of</tt> as long as
661
+ # <tt>config.active_record.automatic_scope_inversing<tt> is set to
662
+ # +true+ (the default for new applications).
663
+ def scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
664
+ if inverse_reflection
647
665
  !reflection.scope
666
+ else
667
+ !reflection.scope || reflection.klass.automatic_scope_inversing
668
+ end
648
669
  end
649
670
 
650
671
  def derive_class_name
@@ -659,7 +680,7 @@ module ActiveRecord
659
680
  elsif options[:as]
660
681
  "#{options[:as]}_id"
661
682
  else
662
- active_record.name.foreign_key
683
+ active_record.model_name.to_s.foreign_key
663
684
  end
664
685
  end
665
686
 
@@ -680,10 +701,6 @@ module ActiveRecord
680
701
  Associations::HasManyAssociation
681
702
  end
682
703
  end
683
-
684
- def association_primary_key(klass = nil)
685
- primary_key(klass || self.klass)
686
- end
687
704
  end
688
705
 
689
706
  class HasOneReflection < AssociationReflection # :nodoc:
@@ -698,12 +715,6 @@ module ActiveRecord
698
715
  Associations::HasOneAssociation
699
716
  end
700
717
  end
701
-
702
- private
703
-
704
- def calculate_constructable(macro, options)
705
- !options[:through]
706
- end
707
718
  end
708
719
 
709
720
  class BelongsToReflection < AssociationReflection # :nodoc:
@@ -719,6 +730,15 @@ module ActiveRecord
719
730
  end
720
731
  end
721
732
 
733
+ # klass option is necessary to support loading polymorphic associations
734
+ def association_primary_key(klass = nil)
735
+ if primary_key = options[:primary_key]
736
+ @association_primary_key ||= -primary_key.to_s
737
+ else
738
+ primary_key(klass || self.klass)
739
+ end
740
+ end
741
+
722
742
  def join_primary_key(klass = nil)
723
743
  polymorphic? ? association_primary_key(klass) : association_primary_key
724
744
  end
@@ -727,14 +747,14 @@ module ActiveRecord
727
747
  foreign_key
728
748
  end
729
749
 
750
+ def join_foreign_type
751
+ foreign_type
752
+ end
753
+
730
754
  private
731
- def can_find_inverse_of_automatically?(_)
755
+ def can_find_inverse_of_automatically?(*)
732
756
  !polymorphic? && super
733
757
  end
734
-
735
- def calculate_constructable(macro, options)
736
- !polymorphic?
737
- end
738
758
  end
739
759
 
740
760
  class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
@@ -747,14 +767,16 @@ module ActiveRecord
747
767
 
748
768
  # Holds all the metadata about a :through association as it was specified
749
769
  # in the Active Record class.
750
- class ThroughReflection < AbstractReflection #:nodoc:
751
- delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for,
752
- :active_record_primary_key, :type, :get_join_keys, to: :source_reflection
770
+ class ThroughReflection < AbstractReflection # :nodoc:
771
+ delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type,
772
+ :active_record_primary_key, :join_foreign_key, to: :source_reflection
753
773
 
754
774
  def initialize(delegate_reflection)
755
775
  @delegate_reflection = delegate_reflection
756
776
  @klass = delegate_reflection.options[:anonymous_class]
757
777
  @source_reflection_name = delegate_reflection.options[:source]
778
+
779
+ ensure_option_not_given_as_class!(:source_type)
758
780
  end
759
781
 
760
782
  def through_reflection?
@@ -835,8 +857,8 @@ module ActiveRecord
835
857
  source_reflection.scopes + super
836
858
  end
837
859
 
838
- def join_scopes(table, predicate_builder) # :nodoc:
839
- source_reflection.join_scopes(table, predicate_builder) + super
860
+ def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
861
+ source_reflection.join_scopes(table, predicate_builder, klass, record) + super
840
862
  end
841
863
 
842
864
  def has_scope?
@@ -856,7 +878,15 @@ module ActiveRecord
856
878
  def association_primary_key(klass = nil)
857
879
  # Get the "actual" source reflection if the immediate source reflection has a
858
880
  # source reflection itself
859
- actual_source_reflection.options[:primary_key] || primary_key(klass || self.klass)
881
+ if primary_key = actual_source_reflection.options[:primary_key]
882
+ @association_primary_key ||= -primary_key.to_s
883
+ else
884
+ primary_key(klass || self.klass)
885
+ end
886
+ end
887
+
888
+ def join_primary_key(klass = self.klass)
889
+ source_reflection.join_primary_key(klass)
860
890
  end
861
891
 
862
892
  # Gets an array of possible <tt>:through</tt> source reflection names in both singular and plural form.
@@ -905,7 +935,7 @@ module ActiveRecord
905
935
 
906
936
  def check_validity!
907
937
  if through_reflection.nil?
908
- raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
938
+ raise HasManyThroughAssociationNotFoundError.new(active_record, self)
909
939
  end
910
940
 
911
941
  if through_reflection.polymorphic?
@@ -961,16 +991,14 @@ module ActiveRecord
961
991
  collect_join_reflections(seed + [self])
962
992
  end
963
993
 
964
- # TODO Change this to private once we've dropped Ruby 2.2 support.
965
- # Workaround for Ruby 2.2 "private attribute?" warning.
966
994
  protected
967
- attr_reader :delegate_reflection
968
-
969
995
  def actual_source_reflection # FIXME: this is a horrible name
970
996
  source_reflection.actual_source_reflection
971
997
  end
972
998
 
973
999
  private
1000
+ attr_reader :delegate_reflection
1001
+
974
1002
  def collect_join_reflections(seed)
975
1003
  a = source_reflection.add_as_source seed
976
1004
  if options[:source_type]
@@ -994,16 +1022,17 @@ module ActiveRecord
994
1022
  end
995
1023
 
996
1024
  class PolymorphicReflection < AbstractReflection # :nodoc:
997
- delegate :klass, :scope, :plural_name, :type, :get_join_keys, :scope_for, to: :@reflection
1025
+ delegate :klass, :scope, :plural_name, :type, :join_primary_key, :join_foreign_key,
1026
+ :name, :scope_for, to: :@reflection
998
1027
 
999
1028
  def initialize(reflection, previous_reflection)
1000
1029
  @reflection = reflection
1001
1030
  @previous_reflection = previous_reflection
1002
1031
  end
1003
1032
 
1004
- def join_scopes(table, predicate_builder) # :nodoc:
1005
- scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
1006
- scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
1033
+ def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
1034
+ scopes = @previous_reflection.join_scopes(table, predicate_builder, klass, record) + super
1035
+ scopes << build_scope(table, predicate_builder, klass).instance_exec(record, &source_type_scope)
1007
1036
  end
1008
1037
 
1009
1038
  def constraints
@@ -1019,7 +1048,7 @@ module ActiveRecord
1019
1048
  end
1020
1049
 
1021
1050
  class RuntimeReflection < AbstractReflection # :nodoc:
1022
- delegate :scope, :type, :constraints, :get_join_keys, to: :@reflection
1051
+ delegate :scope, :type, :constraints, :join_foreign_key, to: :@reflection
1023
1052
 
1024
1053
  def initialize(reflection, association)
1025
1054
  @reflection = reflection
@@ -1031,7 +1060,11 @@ module ActiveRecord
1031
1060
  end
1032
1061
 
1033
1062
  def aliased_table
1034
- @aliased_table ||= Arel::Table.new(table_name, type_caster: klass.type_caster)
1063
+ klass.arel_table
1064
+ end
1065
+
1066
+ def join_primary_key(klass = self.klass)
1067
+ @reflection.join_primary_key(klass)
1035
1068
  end
1036
1069
 
1037
1070
  def all_includes; yield; end