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
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/enumerable"
4
+
3
5
  module ActiveRecord
4
6
  module Calculations
5
7
  # Count the records.
@@ -29,7 +31,7 @@ module ActiveRecord
29
31
  #
30
32
  # Article.group(:status, :category).count
31
33
  # # => {["draft", "business"]=>10, ["draft", "technology"]=>4,
32
- # ["published", "business"]=>0, ["published", "technology"]=>2}
34
+ # # ["published", "business"]=>0, ["published", "technology"]=>2}
33
35
  #
34
36
  # If #count is used with {Relation#select}[rdoc-ref:QueryMethods#select], it will count the selected columns:
35
37
  #
@@ -41,15 +43,13 @@ module ActiveRecord
41
43
  def count(column_name = nil)
42
44
  if block_given?
43
45
  unless column_name.nil?
44
- ActiveSupport::Deprecation.warn \
45
- "When `count' is called with a block, it ignores other arguments. " \
46
- "This behavior is now deprecated and will result in an ArgumentError in Rails 6.0."
46
+ raise ArgumentError, "Column name argument is not supported when a block is passed."
47
47
  end
48
48
 
49
- return super()
49
+ super()
50
+ else
51
+ calculate(:count, column_name)
50
52
  end
51
-
52
- calculate(:count, column_name)
53
53
  end
54
54
 
55
55
  # Calculates the average value on a given column. Returns +nil+ if there's
@@ -83,18 +83,25 @@ module ActiveRecord
83
83
  # #calculate for examples with options.
84
84
  #
85
85
  # Person.sum(:age) # => 4562
86
- def sum(column_name = nil)
86
+ def sum(identity_or_column = nil, &block)
87
87
  if block_given?
88
- unless column_name.nil?
89
- ActiveSupport::Deprecation.warn \
90
- "When `sum' is called with a block, it ignores other arguments. " \
91
- "This behavior is now deprecated and will result in an ArgumentError in Rails 6.0."
88
+ values = map(&block)
89
+ if identity_or_column.nil? && (values.first.is_a?(Numeric) || values.first(1) == [])
90
+ identity_or_column = 0
92
91
  end
93
92
 
94
- return super()
93
+ if identity_or_column.nil?
94
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
95
+ Rails 7.0 has deprecated Enumerable.sum in favor of Ruby's native implementation available since 2.4.
96
+ Sum of non-numeric elements requires an initial argument.
97
+ MSG
98
+ values.inject(:+) || 0
99
+ else
100
+ values.sum(identity_or_column)
101
+ end
102
+ else
103
+ calculate(:sum, identity_or_column)
95
104
  end
96
-
97
- calculate(:sum, column_name)
98
105
  end
99
106
 
100
107
  # This calculates aggregate values in the given column. Methods for #count, #sum, #average,
@@ -138,7 +145,7 @@ module ActiveRecord
138
145
  relation.select_values = [ klass.primary_key || table[Arel.star] ]
139
146
  end
140
147
  # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
141
- relation.order_values = []
148
+ relation.order_values = [] if group_values.empty?
142
149
  end
143
150
 
144
151
  relation.calculate(operation, column_name)
@@ -148,7 +155,7 @@ module ActiveRecord
148
155
  end
149
156
 
150
157
  # Use #pluck as a shortcut to select one or more attributes without
151
- # loading a bunch of records just to grab the attributes you want.
158
+ # loading an entire record object per row.
152
159
  #
153
160
  # Person.pluck(:name)
154
161
  #
@@ -176,14 +183,14 @@ module ActiveRecord
176
183
  # # SELECT people.id FROM people WHERE people.age = 21 LIMIT 5
177
184
  # # => [2, 3]
178
185
  #
179
- # Person.pluck('DATEDIFF(updated_at, created_at)')
186
+ # Person.pluck(Arel.sql('DATEDIFF(updated_at, created_at)'))
180
187
  # # SELECT DATEDIFF(updated_at, created_at) FROM people
181
188
  # # => ['0', '27761', '173']
182
189
  #
183
190
  # See also #ids.
184
191
  #
185
192
  def pluck(*column_names)
186
- if loaded? && (column_names.map(&:to_s) - @klass.attribute_names - @klass.attribute_aliases.keys).empty?
193
+ if loaded? && all_attributes?(column_names)
187
194
  return records.pluck(*column_names)
188
195
  end
189
196
 
@@ -191,12 +198,41 @@ module ActiveRecord
191
198
  relation = apply_join_dependency
192
199
  relation.pluck(*column_names)
193
200
  else
194
- klass.enforce_raw_sql_whitelist(column_names)
201
+ klass.disallow_raw_sql!(column_names)
202
+ columns = arel_columns(column_names)
195
203
  relation = spawn
196
- relation.select_values = column_names
197
- result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) }
198
- result.cast_values(klass.attribute_types)
204
+ relation.select_values = columns
205
+ result = skip_query_cache_if_necessary do
206
+ if where_clause.contradiction?
207
+ ActiveRecord::Result.empty
208
+ else
209
+ klass.connection.select_all(relation.arel, "#{klass.name} Pluck")
210
+ end
211
+ end
212
+ type_cast_pluck_values(result, columns)
213
+ end
214
+ end
215
+
216
+ # Pick the value(s) from the named column(s) in the current relation.
217
+ # This is short-hand for <tt>relation.limit(1).pluck(*column_names).first</tt>, and is primarily useful
218
+ # when you have a relation that's already narrowed down to a single row.
219
+ #
220
+ # Just like #pluck, #pick will only load the actual value, not the entire record object, so it's also
221
+ # more efficient. The value is, again like with pluck, typecast by the column type.
222
+ #
223
+ # Person.where(id: 1).pick(:name)
224
+ # # SELECT people.name FROM people WHERE id = 1 LIMIT 1
225
+ # # => 'David'
226
+ #
227
+ # Person.where(id: 1).pick(:name, :email_address)
228
+ # # SELECT people.name, people.email_address FROM people WHERE id = 1 LIMIT 1
229
+ # # => [ 'David', 'david@loudthinking.com' ]
230
+ def pick(*column_names)
231
+ if loaded? && all_attributes?(column_names)
232
+ return records.pick(*column_names)
199
233
  end
234
+
235
+ limit(1).pluck(*column_names).first
200
236
  end
201
237
 
202
238
  # Pluck all the ID's for the relation using the table's primary key
@@ -208,6 +244,10 @@ module ActiveRecord
208
244
  end
209
245
 
210
246
  private
247
+ def all_attributes?(column_names)
248
+ (column_names.map(&:to_s) - @klass.attribute_names - @klass.attribute_aliases.keys).empty?
249
+ end
250
+
211
251
  def has_include?(column_name)
212
252
  eager_loading? || (includes_values.present? && column_name && column_name != :all)
213
253
  end
@@ -246,20 +286,16 @@ module ActiveRecord
246
286
  def aggregate_column(column_name)
247
287
  return column_name if Arel::Expressions === column_name
248
288
 
249
- if @klass.has_attribute?(column_name) || @klass.attribute_alias?(column_name)
250
- @klass.arel_attribute(column_name)
251
- else
252
- Arel.sql(column_name == :all ? "*" : column_name.to_s)
289
+ arel_column(column_name.to_s) do |name|
290
+ Arel.sql(column_name == :all ? "*" : name)
253
291
  end
254
292
  end
255
293
 
256
294
  def operation_over_aggregate_column(column, operation, distinct)
257
- operation == "count" ? column.count(distinct) : column.send(operation)
295
+ operation == "count" ? column.count(distinct) : column.public_send(operation)
258
296
  end
259
297
 
260
- def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
261
- column_alias = column_name
262
-
298
+ def execute_simple_calculation(operation, column_name, distinct) # :nodoc:
263
299
  if operation == "count" && (column_name == :all && distinct || has_limit_or_offset?)
264
300
  # Shortcut when limit is zero.
265
301
  return 0 if limit_value == 0
@@ -270,59 +306,52 @@ module ActiveRecord
270
306
  relation = unscope(:order).distinct!(false)
271
307
 
272
308
  column = aggregate_column(column_name)
273
-
274
309
  select_value = operation_over_aggregate_column(column, operation, distinct)
275
- if operation == "sum" && distinct
276
- select_value.distinct = true
277
- end
310
+ select_value.distinct = true if operation == "sum" && distinct
278
311
 
279
- column_alias = select_value.alias
280
- column_alias ||= @klass.connection.column_name_for_operation(operation, select_value)
281
312
  relation.select_values = [select_value]
282
313
 
283
314
  query_builder = relation.arel
284
315
  end
285
316
 
286
- result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder, nil) }
287
- row = result.first
288
- value = row && row.values.first
289
- type = result.column_types.fetch(column_alias) do
290
- type_for(column_name)
317
+ result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder, "#{@klass.name} #{operation.capitalize}") }
318
+
319
+ if operation != "count"
320
+ type = column.try(:type_caster) ||
321
+ lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
322
+ type = type.subtype if Enum::EnumType === type
291
323
  end
292
324
 
293
- type_cast_calculated_value(value, type, operation)
325
+ type_cast_calculated_value(result.cast_values.first, operation, type)
294
326
  end
295
327
 
296
- def execute_grouped_calculation(operation, column_name, distinct) #:nodoc:
297
- group_attrs = group_values
328
+ def execute_grouped_calculation(operation, column_name, distinct) # :nodoc:
329
+ group_fields = group_values
330
+ group_fields = group_fields.uniq if group_fields.size > 1
298
331
 
299
- if group_attrs.first.respond_to?(:to_sym)
300
- association = @klass._reflect_on_association(group_attrs.first)
301
- associated = group_attrs.size == 1 && association && association.belongs_to? # only count belongs_to associations
302
- group_fields = Array(associated ? association.foreign_key : group_attrs)
303
- else
304
- group_fields = group_attrs
332
+ if group_fields.size == 1 && group_fields.first.respond_to?(:to_sym)
333
+ association = klass._reflect_on_association(group_fields.first)
334
+ associated = association && association.belongs_to? # only count belongs_to associations
335
+ group_fields = Array(association.foreign_key) if associated
305
336
  end
306
337
  group_fields = arel_columns(group_fields)
307
338
 
308
- group_aliases = group_fields.map { |field| column_alias_for(field) }
339
+ group_aliases = group_fields.map { |field|
340
+ field = connection.visitor.compile(field) if Arel.arel_node?(field)
341
+ column_alias_for(field.to_s.downcase)
342
+ }
309
343
  group_columns = group_aliases.zip(group_fields)
310
344
 
311
- if operation == "count" && column_name == :all
312
- aggregate_alias = "count_all"
313
- else
314
- aggregate_alias = column_alias_for([operation, column_name].join(" "))
315
- end
345
+ column = aggregate_column(column_name)
346
+ column_alias = column_alias_for("#{operation} #{column_name.to_s.downcase}")
347
+ select_value = operation_over_aggregate_column(column, operation, distinct)
348
+ select_value.as(connection.quote_column_name(column_alias))
316
349
 
317
- select_values = [
318
- operation_over_aggregate_column(
319
- aggregate_column(column_name),
320
- operation,
321
- distinct).as(aggregate_alias)
322
- ]
350
+ select_values = [select_value]
323
351
  select_values += self.select_values unless having_clause.empty?
324
352
 
325
353
  select_values.concat group_columns.map { |aliaz, field|
354
+ aliaz = connection.quote_column_name(aliaz)
326
355
  if field.respond_to?(:as)
327
356
  field.as(aliaz)
328
357
  else
@@ -334,48 +363,56 @@ module ActiveRecord
334
363
  relation.group_values = group_fields
335
364
  relation.select_values = select_values
336
365
 
337
- calculated_data = skip_query_cache_if_necessary { @klass.connection.select_all(relation.arel, nil) }
366
+ calculated_data = skip_query_cache_if_necessary { @klass.connection.select_all(relation.arel, "#{@klass.name} #{operation.capitalize}") }
338
367
 
339
368
  if association
340
369
  key_ids = calculated_data.collect { |row| row[group_aliases.first] }
341
370
  key_records = association.klass.base_class.where(association.klass.base_class.primary_key => key_ids)
342
- key_records = Hash[key_records.map { |r| [r.id, r] }]
371
+ key_records = key_records.index_by(&:id)
343
372
  end
344
373
 
345
- Hash[calculated_data.map do |row|
346
- key = group_columns.map { |aliaz, col_name|
347
- type = type_for(col_name) do
348
- calculated_data.column_types.fetch(aliaz, Type.default_value)
349
- end
350
- type_cast_calculated_value(row[aliaz], type)
351
- }
374
+ key_types = group_columns.each_with_object({}) do |(aliaz, col_name), types|
375
+ types[aliaz] = type_for(col_name) do
376
+ calculated_data.column_types.fetch(aliaz, Type.default_value)
377
+ end
378
+ end
379
+
380
+ hash_rows = calculated_data.cast_values(key_types).map! do |row|
381
+ calculated_data.columns.each_with_object({}).with_index do |(col_name, hash), i|
382
+ hash[col_name] = row[i]
383
+ end
384
+ end
385
+
386
+ if operation != "count"
387
+ type = column.try(:type_caster) ||
388
+ lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
389
+ type = type.subtype if Enum::EnumType === type
390
+ end
391
+
392
+ hash_rows.each_with_object({}) do |row, result|
393
+ key = group_aliases.map { |aliaz| row[aliaz] }
352
394
  key = key.first if key.size == 1
353
395
  key = key_records[key] if associated
354
396
 
355
- type = calculated_data.column_types.fetch(aggregate_alias) { type_for(column_name) }
356
- [key, type_cast_calculated_value(row[aggregate_alias], type, operation)]
357
- end]
397
+ result[key] = type_cast_calculated_value(row[column_alias], operation, type)
398
+ end
358
399
  end
359
400
 
360
- # Converts the given keys to the value that the database adapter returns as
401
+ # Converts the given field to the value that the database adapter returns as
361
402
  # a usable column name:
362
403
  #
363
404
  # column_alias_for("users.id") # => "users_id"
364
405
  # column_alias_for("sum(id)") # => "sum_id"
365
406
  # column_alias_for("count(distinct users.id)") # => "count_distinct_users_id"
366
407
  # column_alias_for("count(*)") # => "count_all"
367
- def column_alias_for(keys)
368
- if keys.respond_to? :name
369
- keys = "#{keys.relation.name}.#{keys.name}"
370
- end
371
-
372
- table_name = keys.to_s.downcase
373
- table_name.gsub!(/\*/, "all")
374
- table_name.gsub!(/\W+/, " ")
375
- table_name.strip!
376
- table_name.gsub!(/ +/, "_")
377
-
378
- @klass.connection.table_alias_for(table_name)
408
+ def column_alias_for(field)
409
+ column_alias = +field
410
+ column_alias.gsub!(/\*/, "all")
411
+ column_alias.gsub!(/\W+/, " ")
412
+ column_alias.strip!
413
+ column_alias.gsub!(/ +/, "_")
414
+
415
+ connection.table_alias_for(column_alias)
379
416
  end
380
417
 
381
418
  def type_for(field, &block)
@@ -383,12 +420,46 @@ module ActiveRecord
383
420
  @klass.type_for_attribute(field_name, &block)
384
421
  end
385
422
 
386
- def type_cast_calculated_value(value, type, operation = nil)
423
+ def lookup_cast_type_from_join_dependencies(name, join_dependencies = build_join_dependencies)
424
+ each_join_dependencies(join_dependencies) do |join|
425
+ type = join.base_klass.attribute_types.fetch(name, nil)
426
+ return type if type
427
+ end
428
+ nil
429
+ end
430
+
431
+ def type_cast_pluck_values(result, columns)
432
+ cast_types = if result.columns.size != columns.size
433
+ klass.attribute_types
434
+ else
435
+ join_dependencies = nil
436
+ columns.map.with_index do |column, i|
437
+ column.try(:type_caster) ||
438
+ klass.attribute_types.fetch(name = result.columns[i]) do
439
+ join_dependencies ||= build_join_dependencies
440
+ lookup_cast_type_from_join_dependencies(name, join_dependencies) ||
441
+ result.column_types[name] || Type.default_value
442
+ end
443
+ end
444
+ end
445
+ result.cast_values(cast_types)
446
+ end
447
+
448
+ def type_cast_calculated_value(value, operation, type)
387
449
  case operation
388
- when "count" then value.to_i
389
- when "sum" then type.deserialize(value || 0)
390
- when "average" then value && value.respond_to?(:to_d) ? value.to_d : value
391
- else type.deserialize(value)
450
+ when "count"
451
+ value.to_i
452
+ when "sum"
453
+ type.deserialize(value || 0)
454
+ when "average"
455
+ case type.type
456
+ when :integer, :decimal
457
+ value&.to_d
458
+ else
459
+ type.deserialize(value)
460
+ end
461
+ else # "minimum", "maximum"
462
+ type.deserialize(value)
392
463
  end
393
464
  end
394
465
 
@@ -403,16 +474,17 @@ module ActiveRecord
403
474
 
404
475
  def build_count_subquery(relation, column_name, distinct)
405
476
  if column_name == :all
477
+ column_alias = Arel.star
406
478
  relation.select_values = [ Arel.sql(FinderMethods::ONE_AS_ONE) ] unless distinct
407
479
  else
408
480
  column_alias = Arel.sql("count_column")
409
481
  relation.select_values = [ aggregate_column(column_name).as(column_alias) ]
410
482
  end
411
483
 
412
- subquery = relation.arel.as(Arel.sql("subquery_for_count"))
413
- select_value = operation_over_aggregate_column(column_alias || Arel.star, "count", false)
484
+ subquery_alias = Arel.sql("subquery_for_count")
485
+ select_value = operation_over_aggregate_column(column_alias, "count", false)
414
486
 
415
- Arel::SelectManager.new(subquery).project(select_value)
487
+ relation.build_subquery(subquery_alias, select_value)
416
488
  end
417
489
  end
418
490
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "mutex_m"
4
+ require "active_support/core_ext/module/delegation"
5
+
3
6
  module ActiveRecord
4
7
  module Delegation # :nodoc:
5
8
  module DelegateCache # :nodoc:
@@ -12,13 +15,14 @@ module ActiveRecord
12
15
  [
13
16
  ActiveRecord::Relation,
14
17
  ActiveRecord::Associations::CollectionProxy,
15
- ActiveRecord::AssociationRelation
18
+ ActiveRecord::AssociationRelation,
19
+ ActiveRecord::DisableJoinsAssociationRelation
16
20
  ].each do |klass|
17
21
  delegate = Class.new(klass) {
18
22
  include ClassSpecificRelation
19
23
  }
20
24
  include_relation_methods(delegate)
21
- mangled_name = klass.name.gsub("::".freeze, "_".freeze)
25
+ mangled_name = klass.name.gsub("::", "_")
22
26
  const_set mangled_name, delegate
23
27
  private_constant mangled_name
24
28
 
@@ -31,35 +35,48 @@ module ActiveRecord
31
35
  super
32
36
  end
33
37
 
38
+ def generate_relation_method(method)
39
+ generated_relation_methods.generate_method(method)
40
+ end
41
+
34
42
  protected
35
43
  def include_relation_methods(delegate)
36
- superclass.include_relation_methods(delegate) unless base_class == self
44
+ superclass.include_relation_methods(delegate) unless base_class?
37
45
  delegate.include generated_relation_methods
38
46
  end
39
47
 
40
48
  private
41
49
  def generated_relation_methods
42
- @generated_relation_methods ||= Module.new.tap do |mod|
43
- mod_name = "GeneratedRelationMethods"
44
- const_set mod_name, mod
45
- private_constant mod_name
50
+ @generated_relation_methods ||= GeneratedRelationMethods.new.tap do |mod|
51
+ const_set(:GeneratedRelationMethods, mod)
52
+ private_constant :GeneratedRelationMethods
46
53
  end
47
54
  end
55
+ end
48
56
 
49
- def generate_relation_method(method)
50
- if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method)
51
- generated_relation_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
52
- def #{method}(*args, &block)
53
- scoping { klass.#{method}(*args, &block) }
57
+ class GeneratedRelationMethods < Module # :nodoc:
58
+ include Mutex_m
59
+
60
+ def generate_method(method)
61
+ synchronize do
62
+ return if method_defined?(method)
63
+
64
+ if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method) && !DELEGATION_RESERVED_METHOD_NAMES.include?(method.to_s)
65
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
66
+ def #{method}(...)
67
+ scoping { klass.#{method}(...) }
54
68
  end
55
69
  RUBY
56
70
  else
57
- generated_relation_methods.send(:define_method, method) do |*args, &block|
71
+ define_method(method) do |*args, &block|
58
72
  scoping { klass.public_send(method, *args, &block) }
59
73
  end
74
+ ruby2_keywords(method)
60
75
  end
61
76
  end
77
+ end
62
78
  end
79
+ private_constant :GeneratedRelationMethods
63
80
 
64
81
  extend ActiveSupport::Concern
65
82
 
@@ -68,9 +85,9 @@ module ActiveRecord
68
85
  # may vary depending on the klass of a relation, so we create a subclass of Relation
69
86
  # for each different klass, and the delegations are compiled into that subclass only.
70
87
 
71
- delegate :to_xml, :encode_with, :length, :each, :uniq, :join,
88
+ delegate :to_xml, :encode_with, :length, :each, :join,
72
89
  :[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
73
- :to_sentence, :to_formatted_s, :as_json,
90
+ :to_sentence, :to_fs, :to_formatted_s, :as_json,
74
91
  :shuffle, :split, :slice, :index, :rindex, to: :records
75
92
 
76
93
  delegate :primary_key, :connection, to: :klass
@@ -78,62 +95,30 @@ module ActiveRecord
78
95
  module ClassSpecificRelation # :nodoc:
79
96
  extend ActiveSupport::Concern
80
97
 
81
- included do
82
- @delegation_mutex = Mutex.new
83
- end
84
-
85
98
  module ClassMethods # :nodoc:
86
99
  def name
87
100
  superclass.name
88
101
  end
89
-
90
- def delegate_to_scoped_klass(method)
91
- @delegation_mutex.synchronize do
92
- return if method_defined?(method)
93
-
94
- if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method)
95
- module_eval <<-RUBY, __FILE__, __LINE__ + 1
96
- def #{method}(*args, &block)
97
- scoping { @klass.#{method}(*args, &block) }
98
- end
99
- RUBY
100
- else
101
- define_method method do |*args, &block|
102
- scoping { @klass.public_send(method, *args, &block) }
103
- end
104
- end
105
- end
106
- end
107
102
  end
108
103
 
109
104
  private
110
-
111
105
  def method_missing(method, *args, &block)
112
106
  if @klass.respond_to?(method)
113
- self.class.delegate_to_scoped_klass(method)
107
+ @klass.generate_relation_method(method)
114
108
  scoping { @klass.public_send(method, *args, &block) }
115
- elsif @delegate_to_klass && @klass.respond_to?(method, true)
116
- ActiveSupport::Deprecation.warn \
117
- "Delegating missing #{method} method to #{@klass}. " \
118
- "Accessibility of private/protected class methods in :scope is deprecated and will be removed in Rails 6.0."
119
- @klass.send(method, *args, &block)
120
- elsif arel.respond_to?(method)
121
- ActiveSupport::Deprecation.warn \
122
- "Delegating #{method} to arel is deprecated and will be removed in Rails 6.0."
123
- arel.public_send(method, *args, &block)
124
109
  else
125
110
  super
126
111
  end
127
112
  end
113
+ ruby2_keywords(:method_missing)
128
114
  end
129
115
 
130
116
  module ClassMethods # :nodoc:
131
- def create(klass, *args)
132
- relation_class_for(klass).new(klass, *args)
117
+ def create(klass, *args, **kwargs)
118
+ relation_class_for(klass).new(klass, *args, **kwargs)
133
119
  end
134
120
 
135
121
  private
136
-
137
122
  def relation_class_for(klass)
138
123
  klass.relation_delegate_class(self)
139
124
  end
@@ -141,7 +126,7 @@ module ActiveRecord
141
126
 
142
127
  private
143
128
  def respond_to_missing?(method, _)
144
- super || @klass.respond_to?(method) || arel.respond_to?(method)
129
+ super || @klass.respond_to?(method)
145
130
  end
146
131
  end
147
132
  end