activerecord 5.0.6 → 6.0.1

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

Potentially problematic release.


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

Files changed (358) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +638 -2023
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +8 -6
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record/aggregations.rb +249 -246
  8. data/lib/active_record/association_relation.rb +24 -13
  9. data/lib/active_record/associations/alias_tracker.rb +24 -33
  10. data/lib/active_record/associations/association.rb +119 -56
  11. data/lib/active_record/associations/association_scope.rb +94 -94
  12. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  14. data/lib/active_record/associations/builder/association.rb +18 -25
  15. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  16. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -61
  18. data/lib/active_record/associations/builder/has_many.rb +4 -0
  19. data/lib/active_record/associations/builder/has_one.rb +37 -1
  20. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  21. data/lib/active_record/associations/collection_association.rb +80 -252
  22. data/lib/active_record/associations/collection_proxy.rb +158 -121
  23. data/lib/active_record/associations/foreign_association.rb +9 -0
  24. data/lib/active_record/associations/has_many_association.rb +23 -29
  25. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  26. data/lib/active_record/associations/has_one_association.rb +59 -54
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +38 -90
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +134 -176
  32. data/lib/active_record/associations/preloader/association.rb +84 -125
  33. data/lib/active_record/associations/preloader/through_association.rb +82 -75
  34. data/lib/active_record/associations/preloader.rb +90 -102
  35. data/lib/active_record/associations/singular_association.rb +12 -45
  36. data/lib/active_record/associations/through_association.rb +26 -14
  37. data/lib/active_record/associations.rb +1603 -1592
  38. data/lib/active_record/attribute_assignment.rb +54 -60
  39. data/lib/active_record/attribute_decorators.rb +38 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -7
  41. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -91
  43. data/lib/active_record/attribute_methods/query.rb +4 -3
  44. data/lib/active_record/attribute_methods/read.rb +21 -49
  45. data/lib/active_record/attribute_methods/serialization.rb +30 -7
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -64
  47. data/lib/active_record/attribute_methods/write.rb +35 -33
  48. data/lib/active_record/attribute_methods.rb +66 -106
  49. data/lib/active_record/attributes.rb +38 -24
  50. data/lib/active_record/autosave_association.rb +53 -32
  51. data/lib/active_record/base.rb +27 -24
  52. data/lib/active_record/callbacks.rb +63 -33
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +11 -11
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +553 -321
  56. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  57. data/lib/active_record/connection_adapters/abstract/database_statements.rb +213 -94
  58. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -28
  59. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
  60. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -27
  62. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -126
  63. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  64. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +369 -199
  65. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
  66. data/lib/active_record/connection_adapters/abstract_adapter.rb +363 -202
  67. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -551
  68. data/lib/active_record/connection_adapters/column.rb +41 -13
  69. data/lib/active_record/connection_adapters/connection_specification.rb +172 -138
  70. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  71. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +143 -49
  73. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -22
  74. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  75. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +50 -45
  76. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  77. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  78. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  79. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +49 -30
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +22 -7
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +60 -54
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -10
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -17
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  98. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +31 -9
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -30
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -4
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +35 -32
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +380 -300
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +10 -6
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +382 -275
  116. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +74 -19
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +254 -262
  126. data/lib/active_record/connection_adapters/statement_pool.rb +9 -7
  127. data/lib/active_record/connection_handling.rb +159 -40
  128. data/lib/active_record/core.rb +202 -162
  129. data/lib/active_record/counter_cache.rb +57 -28
  130. data/lib/active_record/database_configurations/database_config.rb +37 -0
  131. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  132. data/lib/active_record/database_configurations/url_config.rb +79 -0
  133. data/lib/active_record/database_configurations.rb +233 -0
  134. data/lib/active_record/define_callbacks.rb +22 -0
  135. data/lib/active_record/dynamic_matchers.rb +87 -86
  136. data/lib/active_record/enum.rb +60 -23
  137. data/lib/active_record/errors.rb +114 -18
  138. data/lib/active_record/explain.rb +4 -3
  139. data/lib/active_record/explain_registry.rb +3 -1
  140. data/lib/active_record/explain_subscriber.rb +9 -4
  141. data/lib/active_record/fixture_set/file.rb +13 -8
  142. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  143. data/lib/active_record/fixture_set/render_context.rb +17 -0
  144. data/lib/active_record/fixture_set/table_row.rb +153 -0
  145. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  146. data/lib/active_record/fixtures.rb +195 -502
  147. data/lib/active_record/gem_version.rb +4 -2
  148. data/lib/active_record/inheritance.rb +151 -97
  149. data/lib/active_record/insert_all.rb +179 -0
  150. data/lib/active_record/integration.rb +116 -25
  151. data/lib/active_record/internal_metadata.rb +15 -18
  152. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  153. data/lib/active_record/locking/optimistic.rb +78 -87
  154. data/lib/active_record/locking/pessimistic.rb +18 -6
  155. data/lib/active_record/log_subscriber.rb +48 -29
  156. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  157. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/migration/command_recorder.rb +143 -97
  160. data/lib/active_record/migration/compatibility.rb +174 -56
  161. data/lib/active_record/migration/join_table.rb +8 -6
  162. data/lib/active_record/migration.rb +367 -300
  163. data/lib/active_record/model_schema.rb +145 -139
  164. data/lib/active_record/nested_attributes.rb +214 -201
  165. data/lib/active_record/no_touching.rb +10 -1
  166. data/lib/active_record/null_relation.rb +13 -34
  167. data/lib/active_record/persistence.rb +442 -72
  168. data/lib/active_record/query_cache.rb +15 -14
  169. data/lib/active_record/querying.rb +36 -23
  170. data/lib/active_record/railtie.rb +128 -36
  171. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  172. data/lib/active_record/railties/console_sandbox.rb +2 -0
  173. data/lib/active_record/railties/controller_runtime.rb +34 -33
  174. data/lib/active_record/railties/databases.rake +309 -177
  175. data/lib/active_record/readonly_attributes.rb +5 -4
  176. data/lib/active_record/reflection.rb +211 -249
  177. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  178. data/lib/active_record/relation/batches.rb +99 -52
  179. data/lib/active_record/relation/calculations.rb +211 -172
  180. data/lib/active_record/relation/delegation.rb +67 -65
  181. data/lib/active_record/relation/finder_methods.rb +208 -247
  182. data/lib/active_record/relation/from_clause.rb +2 -8
  183. data/lib/active_record/relation/merger.rb +78 -61
  184. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  185. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  186. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  187. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  188. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  189. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  190. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  191. data/lib/active_record/relation/predicate_builder.rb +86 -104
  192. data/lib/active_record/relation/query_attribute.rb +33 -2
  193. data/lib/active_record/relation/query_methods.rb +458 -329
  194. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  195. data/lib/active_record/relation/spawn_methods.rb +8 -7
  196. data/lib/active_record/relation/where_clause.rb +111 -95
  197. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  198. data/lib/active_record/relation.rb +429 -318
  199. data/lib/active_record/result.rb +69 -39
  200. data/lib/active_record/runtime_registry.rb +5 -3
  201. data/lib/active_record/sanitization.rb +83 -99
  202. data/lib/active_record/schema.rb +7 -14
  203. data/lib/active_record/schema_dumper.rb +71 -69
  204. data/lib/active_record/schema_migration.rb +15 -5
  205. data/lib/active_record/scoping/default.rb +93 -95
  206. data/lib/active_record/scoping/named.rb +45 -25
  207. data/lib/active_record/scoping.rb +20 -19
  208. data/lib/active_record/secure_token.rb +4 -2
  209. data/lib/active_record/serialization.rb +2 -0
  210. data/lib/active_record/statement_cache.rb +63 -28
  211. data/lib/active_record/store.rb +121 -41
  212. data/lib/active_record/suppressor.rb +4 -1
  213. data/lib/active_record/table_metadata.rb +26 -20
  214. data/lib/active_record/tasks/database_tasks.rb +276 -85
  215. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -90
  216. data/lib/active_record/tasks/postgresql_database_tasks.rb +78 -47
  217. data/lib/active_record/tasks/sqlite_database_tasks.rb +34 -16
  218. data/lib/active_record/test_databases.rb +23 -0
  219. data/lib/active_record/test_fixtures.rb +224 -0
  220. data/lib/active_record/timestamp.rb +70 -35
  221. data/lib/active_record/touch_later.rb +7 -4
  222. data/lib/active_record/transactions.rb +133 -149
  223. data/lib/active_record/translation.rb +3 -1
  224. data/lib/active_record/type/adapter_specific_registry.rb +44 -45
  225. data/lib/active_record/type/date.rb +2 -0
  226. data/lib/active_record/type/date_time.rb +2 -0
  227. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  228. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  229. data/lib/active_record/type/internal/timezone.rb +2 -0
  230. data/lib/active_record/type/json.rb +30 -0
  231. data/lib/active_record/type/serialized.rb +16 -8
  232. data/lib/active_record/type/text.rb +11 -0
  233. data/lib/active_record/type/time.rb +2 -1
  234. data/lib/active_record/type/type_map.rb +13 -15
  235. data/lib/active_record/type/unsigned_integer.rb +17 -0
  236. data/lib/active_record/type.rb +23 -17
  237. data/lib/active_record/type_caster/connection.rb +17 -12
  238. data/lib/active_record/type_caster/map.rb +5 -4
  239. data/lib/active_record/type_caster.rb +4 -2
  240. data/lib/active_record/validations/absence.rb +2 -0
  241. data/lib/active_record/validations/associated.rb +3 -1
  242. data/lib/active_record/validations/length.rb +2 -0
  243. data/lib/active_record/validations/presence.rb +4 -2
  244. data/lib/active_record/validations/uniqueness.rb +29 -42
  245. data/lib/active_record/validations.rb +7 -4
  246. data/lib/active_record/version.rb +3 -1
  247. data/lib/active_record.rb +36 -22
  248. data/lib/arel/alias_predication.rb +9 -0
  249. data/lib/arel/attributes/attribute.rb +37 -0
  250. data/lib/arel/attributes.rb +22 -0
  251. data/lib/arel/collectors/bind.rb +24 -0
  252. data/lib/arel/collectors/composite.rb +31 -0
  253. data/lib/arel/collectors/plain_string.rb +20 -0
  254. data/lib/arel/collectors/sql_string.rb +20 -0
  255. data/lib/arel/collectors/substitute_binds.rb +28 -0
  256. data/lib/arel/crud.rb +42 -0
  257. data/lib/arel/delete_manager.rb +18 -0
  258. data/lib/arel/errors.rb +9 -0
  259. data/lib/arel/expressions.rb +29 -0
  260. data/lib/arel/factory_methods.rb +49 -0
  261. data/lib/arel/insert_manager.rb +49 -0
  262. data/lib/arel/math.rb +45 -0
  263. data/lib/arel/nodes/and.rb +32 -0
  264. data/lib/arel/nodes/ascending.rb +23 -0
  265. data/lib/arel/nodes/binary.rb +52 -0
  266. data/lib/arel/nodes/bind_param.rb +36 -0
  267. data/lib/arel/nodes/case.rb +55 -0
  268. data/lib/arel/nodes/casted.rb +50 -0
  269. data/lib/arel/nodes/comment.rb +29 -0
  270. data/lib/arel/nodes/count.rb +12 -0
  271. data/lib/arel/nodes/delete_statement.rb +45 -0
  272. data/lib/arel/nodes/descending.rb +23 -0
  273. data/lib/arel/nodes/equality.rb +18 -0
  274. data/lib/arel/nodes/extract.rb +24 -0
  275. data/lib/arel/nodes/false.rb +16 -0
  276. data/lib/arel/nodes/full_outer_join.rb +8 -0
  277. data/lib/arel/nodes/function.rb +44 -0
  278. data/lib/arel/nodes/grouping.rb +8 -0
  279. data/lib/arel/nodes/in.rb +8 -0
  280. data/lib/arel/nodes/infix_operation.rb +80 -0
  281. data/lib/arel/nodes/inner_join.rb +8 -0
  282. data/lib/arel/nodes/insert_statement.rb +37 -0
  283. data/lib/arel/nodes/join_source.rb +20 -0
  284. data/lib/arel/nodes/matches.rb +18 -0
  285. data/lib/arel/nodes/named_function.rb +23 -0
  286. data/lib/arel/nodes/node.rb +50 -0
  287. data/lib/arel/nodes/node_expression.rb +13 -0
  288. data/lib/arel/nodes/outer_join.rb +8 -0
  289. data/lib/arel/nodes/over.rb +15 -0
  290. data/lib/arel/nodes/regexp.rb +16 -0
  291. data/lib/arel/nodes/right_outer_join.rb +8 -0
  292. data/lib/arel/nodes/select_core.rb +67 -0
  293. data/lib/arel/nodes/select_statement.rb +41 -0
  294. data/lib/arel/nodes/sql_literal.rb +16 -0
  295. data/lib/arel/nodes/string_join.rb +11 -0
  296. data/lib/arel/nodes/table_alias.rb +27 -0
  297. data/lib/arel/nodes/terminal.rb +16 -0
  298. data/lib/arel/nodes/true.rb +16 -0
  299. data/lib/arel/nodes/unary.rb +45 -0
  300. data/lib/arel/nodes/unary_operation.rb +20 -0
  301. data/lib/arel/nodes/unqualified_column.rb +22 -0
  302. data/lib/arel/nodes/update_statement.rb +41 -0
  303. data/lib/arel/nodes/values_list.rb +9 -0
  304. data/lib/arel/nodes/window.rb +126 -0
  305. data/lib/arel/nodes/with.rb +11 -0
  306. data/lib/arel/nodes.rb +68 -0
  307. data/lib/arel/order_predications.rb +13 -0
  308. data/lib/arel/predications.rb +257 -0
  309. data/lib/arel/select_manager.rb +271 -0
  310. data/lib/arel/table.rb +110 -0
  311. data/lib/arel/tree_manager.rb +72 -0
  312. data/lib/arel/update_manager.rb +34 -0
  313. data/lib/arel/visitors/depth_first.rb +204 -0
  314. data/lib/arel/visitors/dot.rb +297 -0
  315. data/lib/arel/visitors/ibm_db.rb +34 -0
  316. data/lib/arel/visitors/informix.rb +62 -0
  317. data/lib/arel/visitors/mssql.rb +157 -0
  318. data/lib/arel/visitors/mysql.rb +83 -0
  319. data/lib/arel/visitors/oracle.rb +159 -0
  320. data/lib/arel/visitors/oracle12.rb +66 -0
  321. data/lib/arel/visitors/postgresql.rb +110 -0
  322. data/lib/arel/visitors/sqlite.rb +39 -0
  323. data/lib/arel/visitors/to_sql.rb +889 -0
  324. data/lib/arel/visitors/visitor.rb +46 -0
  325. data/lib/arel/visitors/where_sql.rb +23 -0
  326. data/lib/arel/visitors.rb +20 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +58 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  330. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  332. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  334. data/lib/rails/generators/active_record/migration.rb +17 -2
  335. data/lib/rails/generators/active_record/model/model_generator.rb +9 -29
  336. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  337. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +133 -50
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  347. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  348. data/lib/active_record/attribute.rb +0 -213
  349. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  350. data/lib/active_record/attribute_set/builder.rb +0 -130
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/collection_cache_key.rb +0 -50
  353. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  354. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  355. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  356. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  357. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  358. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Calculations
3
5
  # Count the records.
@@ -37,7 +39,15 @@ module ActiveRecord
37
39
  # Note: not all valid {Relation#select}[rdoc-ref:QueryMethods#select] expressions are valid #count expressions. The specifics differ
38
40
  # between databases. In invalid cases, an error from the database is thrown.
39
41
  def count(column_name = nil)
40
- calculate(:count, column_name)
42
+ if block_given?
43
+ unless column_name.nil?
44
+ raise ArgumentError, "Column name argument is not supported when a block is passed."
45
+ end
46
+
47
+ super()
48
+ else
49
+ calculate(:count, column_name)
50
+ end
41
51
  end
42
52
 
43
53
  # Calculates the average value on a given column. Returns +nil+ if there's
@@ -71,9 +81,16 @@ module ActiveRecord
71
81
  # #calculate for examples with options.
72
82
  #
73
83
  # Person.sum(:age) # => 4562
74
- def sum(column_name = nil, &block)
75
- return super(&block) if block_given?
76
- calculate(:sum, column_name)
84
+ def sum(column_name = nil)
85
+ if block_given?
86
+ unless column_name.nil?
87
+ raise ArgumentError, "Column name argument is not supported when a block is passed."
88
+ end
89
+
90
+ super()
91
+ else
92
+ calculate(:sum, column_name)
93
+ end
77
94
  end
78
95
 
79
96
  # This calculates aggregate values in the given column. Methods for #count, #sum, #average,
@@ -108,13 +125,17 @@ module ActiveRecord
108
125
  # ...
109
126
  # end
110
127
  def calculate(operation, column_name)
111
- if column_name.is_a?(Symbol) && attribute_alias?(column_name)
112
- column_name = attribute_alias(column_name)
113
- end
114
-
115
128
  if has_include?(column_name)
116
- relation = construct_relation_for_association_calculations
117
- relation = relation.distinct if operation.to_s.downcase == "count"
129
+ relation = apply_join_dependency
130
+
131
+ if operation.to_s.downcase == "count"
132
+ unless distinct_value || distinct_select?(column_name || select_for_count)
133
+ relation.distinct!
134
+ relation.select_values = [ klass.primary_key || table[Arel.star] ]
135
+ end
136
+ # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
137
+ relation.order_values = []
138
+ end
118
139
 
119
140
  relation.calculate(operation, column_name)
120
141
  else
@@ -163,17 +184,35 @@ module ActiveRecord
163
184
  end
164
185
 
165
186
  if has_include?(column_names.first)
166
- construct_relation_for_association_calculations.pluck(*column_names)
187
+ relation = apply_join_dependency
188
+ relation.pluck(*column_names)
167
189
  else
190
+ klass.disallow_raw_sql!(column_names)
168
191
  relation = spawn
169
- relation.select_values = column_names.map { |cn|
170
- @klass.has_attribute?(cn) || @klass.attribute_alias?(cn) ? arel_attribute(cn) : cn
171
- }
172
- result = klass.connection.select_all(relation.arel, nil, bound_attributes)
192
+ relation.select_values = column_names
193
+ result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) }
173
194
  result.cast_values(klass.attribute_types)
174
195
  end
175
196
  end
176
197
 
198
+ # Pick the value(s) from the named column(s) in the current relation.
199
+ # This is short-hand for <tt>relation.limit(1).pluck(*column_names).first</tt>, and is primarily useful
200
+ # when you have a relation that's already narrowed down to a single row.
201
+ #
202
+ # Just like #pluck, #pick will only load the actual value, not the entire record object, so it's also
203
+ # more efficient. The value is, again like with pluck, typecast by the column type.
204
+ #
205
+ # Person.where(id: 1).pick(:name)
206
+ # # SELECT people.name FROM people WHERE id = 1 LIMIT 1
207
+ # # => 'David'
208
+ #
209
+ # Person.where(id: 1).pick(:name, :email_address)
210
+ # # SELECT people.name, people.email_address FROM people WHERE id = 1 LIMIT 1
211
+ # # => [ 'David', 'david@loudthinking.com' ]
212
+ def pick(*column_names)
213
+ limit(1).pluck(*column_names).first
214
+ end
215
+
177
216
  # Pluck all the ID's for the relation using the table's primary key
178
217
  #
179
218
  # Person.ids # SELECT people.id FROM people
@@ -183,203 +222,203 @@ module ActiveRecord
183
222
  end
184
223
 
185
224
  private
225
+ def has_include?(column_name)
226
+ eager_loading? || (includes_values.present? && column_name && column_name != :all)
227
+ end
186
228
 
187
- def has_include?(column_name)
188
- eager_loading? || (includes_values.present? && column_name && column_name != :all)
189
- end
229
+ def perform_calculation(operation, column_name)
230
+ operation = operation.to_s.downcase
190
231
 
191
- def perform_calculation(operation, column_name)
192
- operation = operation.to_s.downcase
232
+ # If #count is used with #distinct (i.e. `relation.distinct.count`) it is
233
+ # considered distinct.
234
+ distinct = distinct_value
193
235
 
194
- # If #count is used with #distinct (i.e. `relation.distinct.count`) it is
195
- # considered distinct.
196
- distinct = self.distinct_value
236
+ if operation == "count"
237
+ column_name ||= select_for_count
238
+ if column_name == :all
239
+ if !distinct
240
+ distinct = distinct_select?(select_for_count) if group_values.empty?
241
+ elsif group_values.any? || select_values.empty? && order_values.empty?
242
+ column_name = primary_key
243
+ end
244
+ elsif distinct_select?(column_name)
245
+ distinct = nil
246
+ end
247
+ end
197
248
 
198
- if operation == "count"
199
- column_name ||= select_for_count
200
- column_name = primary_key if column_name == :all && distinct
201
- distinct = nil if column_name =~ /\s*DISTINCT[\s(]+/i
249
+ if group_values.any?
250
+ execute_grouped_calculation(operation, column_name, distinct)
251
+ else
252
+ execute_simple_calculation(operation, column_name, distinct)
253
+ end
202
254
  end
203
255
 
204
- if group_values.any?
205
- execute_grouped_calculation(operation, column_name, distinct)
206
- else
207
- execute_simple_calculation(operation, column_name, distinct)
256
+ def distinct_select?(column_name)
257
+ column_name.is_a?(::String) && /\bDISTINCT[\s(]/i.match?(column_name)
208
258
  end
209
- end
210
259
 
211
- def aggregate_column(column_name)
212
- return column_name if Arel::Expressions === column_name
260
+ def aggregate_column(column_name)
261
+ return column_name if Arel::Expressions === column_name
213
262
 
214
- if @klass.column_names.include?(column_name.to_s)
215
- Arel::Attribute.new(@klass.unscoped.table, column_name)
216
- else
217
- Arel.sql(column_name == :all ? "*" : column_name.to_s)
263
+ arel_column(column_name.to_s) do |name|
264
+ Arel.sql(column_name == :all ? "*" : name)
265
+ end
218
266
  end
219
- end
220
267
 
221
- def operation_over_aggregate_column(column, operation, distinct)
222
- operation == 'count' ? column.count(distinct) : column.send(operation)
223
- end
268
+ def operation_over_aggregate_column(column, operation, distinct)
269
+ operation == "count" ? column.count(distinct) : column.send(operation)
270
+ end
224
271
 
225
- def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
226
- # PostgreSQL doesn't like ORDER BY when there are no GROUP BY
227
- relation = unscope(:order)
272
+ def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
273
+ column_alias = column_name
228
274
 
229
- column_alias = column_name
275
+ if operation == "count" && (column_name == :all && distinct || has_limit_or_offset?)
276
+ # Shortcut when limit is zero.
277
+ return 0 if limit_value == 0
230
278
 
231
- if operation == "count" && (relation.limit_value || relation.offset_value)
232
- # Shortcut when limit is zero.
233
- return 0 if relation.limit_value == 0
279
+ query_builder = build_count_subquery(spawn, column_name, distinct)
280
+ else
281
+ # PostgreSQL doesn't like ORDER BY when there are no GROUP BY
282
+ relation = unscope(:order).distinct!(false)
234
283
 
235
- query_builder = build_count_subquery(relation, column_name, distinct)
236
- else
237
- column = aggregate_column(column_name)
284
+ column = aggregate_column(column_name)
238
285
 
239
- select_value = operation_over_aggregate_column(column, operation, distinct)
286
+ select_value = operation_over_aggregate_column(column, operation, distinct)
287
+ if operation == "sum" && distinct
288
+ select_value.distinct = true
289
+ end
240
290
 
241
- if operation == "sum" && distinct
242
- select_value.distinct = true
243
- end
291
+ column_alias = select_value.alias
292
+ column_alias ||= @klass.connection.column_name_for_operation(operation, select_value)
293
+ relation.select_values = [select_value]
244
294
 
245
- column_alias = select_value.alias
246
- column_alias ||= @klass.connection.column_name_for_operation(operation, select_value)
247
- relation.select_values = [select_value]
295
+ query_builder = relation.arel
296
+ end
248
297
 
249
- query_builder = relation.arel
250
- end
298
+ result = skip_query_cache_if_necessary { @klass.connection.select_all(query_builder, nil) }
299
+ row = result.first
300
+ value = row && row.values.first
301
+ type = result.column_types.fetch(column_alias) do
302
+ type_for(column_name)
303
+ end
251
304
 
252
- result = @klass.connection.select_all(query_builder, nil, bound_attributes)
253
- row = result.first
254
- value = row && row.values.first
255
- column = result.column_types.fetch(column_alias) do
256
- type_for(column_name)
305
+ type_cast_calculated_value(value, type, operation)
257
306
  end
258
307
 
259
- type_cast_calculated_value(value, column, operation)
260
- end
308
+ def execute_grouped_calculation(operation, column_name, distinct) #:nodoc:
309
+ group_fields = group_values
261
310
 
262
- def execute_grouped_calculation(operation, column_name, distinct) #:nodoc:
263
- group_attrs = group_values
311
+ if group_fields.size == 1 && group_fields.first.respond_to?(:to_sym)
312
+ association = klass._reflect_on_association(group_fields.first)
313
+ associated = association && association.belongs_to? # only count belongs_to associations
314
+ group_fields = Array(association.foreign_key) if associated
315
+ end
316
+ group_fields = arel_columns(group_fields)
264
317
 
265
- if group_attrs.first.respond_to?(:to_sym)
266
- association = @klass._reflect_on_association(group_attrs.first)
267
- associated = group_attrs.size == 1 && association && association.belongs_to? # only count belongs_to associations
268
- group_fields = Array(associated ? association.foreign_key : group_attrs)
269
- else
270
- group_fields = group_attrs
271
- end
272
- group_fields = arel_columns(group_fields)
318
+ group_aliases = group_fields.map { |field|
319
+ field = connection.visitor.compile(field) if Arel.arel_node?(field)
320
+ column_alias_for(field.to_s.downcase)
321
+ }
322
+ group_columns = group_aliases.zip(group_fields)
323
+
324
+ aggregate_alias = column_alias_for("#{operation} #{column_name.to_s.downcase}")
325
+
326
+ select_values = [
327
+ operation_over_aggregate_column(
328
+ aggregate_column(column_name),
329
+ operation,
330
+ distinct).as(aggregate_alias)
331
+ ]
332
+ select_values += self.select_values unless having_clause.empty?
333
+
334
+ select_values.concat group_columns.map { |aliaz, field|
335
+ if field.respond_to?(:as)
336
+ field.as(aliaz)
337
+ else
338
+ "#{field} AS #{aliaz}"
339
+ end
340
+ }
273
341
 
274
- group_aliases = group_fields.map { |field| column_alias_for(field) }
275
- group_columns = group_aliases.zip(group_fields)
342
+ relation = except(:group).distinct!(false)
343
+ relation.group_values = group_fields
344
+ relation.select_values = select_values
276
345
 
277
- if operation == 'count' && column_name == :all
278
- aggregate_alias = 'count_all'
279
- else
280
- aggregate_alias = column_alias_for([operation, column_name].join(' '))
281
- end
346
+ calculated_data = skip_query_cache_if_necessary { @klass.connection.select_all(relation.arel, nil) }
282
347
 
283
- select_values = [
284
- operation_over_aggregate_column(
285
- aggregate_column(column_name),
286
- operation,
287
- distinct).as(aggregate_alias)
288
- ]
289
- select_values += self.select_values unless having_clause.empty?
290
-
291
- select_values.concat group_columns.map { |aliaz, field|
292
- if field.respond_to?(:as)
293
- field.as(aliaz)
294
- else
295
- "#{field} AS #{aliaz}"
348
+ if association
349
+ key_ids = calculated_data.collect { |row| row[group_aliases.first] }
350
+ key_records = association.klass.base_class.where(association.klass.base_class.primary_key => key_ids)
351
+ key_records = Hash[key_records.map { |r| [r.id, r] }]
296
352
  end
297
- }
298
-
299
- relation = except(:group)
300
- relation.group_values = group_fields
301
- relation.select_values = select_values
302
-
303
- calculated_data = @klass.connection.select_all(relation, nil, relation.bound_attributes)
304
353
 
305
- if association
306
- key_ids = calculated_data.collect { |row| row[group_aliases.first] }
307
- key_records = association.klass.base_class.where(association.klass.base_class.primary_key => key_ids)
308
- key_records = Hash[key_records.map { |r| [r.id, r] }]
309
- end
310
-
311
- Hash[calculated_data.map do |row|
312
- key = group_columns.map { |aliaz, col_name|
313
- column = type_for(col_name) do
314
- calculated_data.column_types.fetch(aliaz) do
315
- Type::Value.new
354
+ Hash[calculated_data.map do |row|
355
+ key = group_columns.map { |aliaz, col_name|
356
+ type = type_for(col_name) do
357
+ calculated_data.column_types.fetch(aliaz, Type.default_value)
316
358
  end
317
- end
318
- type_cast_calculated_value(row[aliaz], column)
319
- }
320
- key = key.first if key.size == 1
321
- key = key_records[key] if associated
322
-
323
- column_type = calculated_data.column_types.fetch(aggregate_alias) { type_for(column_name) }
324
- [key, type_cast_calculated_value(row[aggregate_alias], column_type, operation)]
325
- end]
326
- end
327
-
328
- # Converts the given keys to the value that the database adapter returns as
329
- # a usable column name:
330
- #
331
- # column_alias_for("users.id") # => "users_id"
332
- # column_alias_for("sum(id)") # => "sum_id"
333
- # column_alias_for("count(distinct users.id)") # => "count_distinct_users_id"
334
- # column_alias_for("count(*)") # => "count_all"
335
- def column_alias_for(keys)
336
- if keys.respond_to? :name
337
- keys = "#{keys.relation.name}.#{keys.name}"
359
+ type_cast_calculated_value(row[aliaz], type)
360
+ }
361
+ key = key.first if key.size == 1
362
+ key = key_records[key] if associated
363
+
364
+ type = calculated_data.column_types.fetch(aggregate_alias) { type_for(column_name) }
365
+ [key, type_cast_calculated_value(row[aggregate_alias], type, operation)]
366
+ end]
338
367
  end
339
368
 
340
- table_name = keys.to_s.downcase
341
- table_name.gsub!(/\*/, 'all')
342
- table_name.gsub!(/\W+/, ' ')
343
- table_name.strip!
344
- table_name.gsub!(/ +/, '_')
345
-
346
- @klass.connection.table_alias_for(table_name)
347
- end
369
+ # Converts the given field to the value that the database adapter returns as
370
+ # a usable column name:
371
+ #
372
+ # column_alias_for("users.id") # => "users_id"
373
+ # column_alias_for("sum(id)") # => "sum_id"
374
+ # column_alias_for("count(distinct users.id)") # => "count_distinct_users_id"
375
+ # column_alias_for("count(*)") # => "count_all"
376
+ def column_alias_for(field)
377
+ column_alias = +field
378
+ column_alias.gsub!(/\*/, "all")
379
+ column_alias.gsub!(/\W+/, " ")
380
+ column_alias.strip!
381
+ column_alias.gsub!(/ +/, "_")
382
+
383
+ connection.table_alias_for(column_alias)
384
+ end
348
385
 
349
- def type_for(field, &block)
350
- field_name = field.respond_to?(:name) ? field.name.to_s : field.to_s.split('.').last
351
- @klass.type_for_attribute(field_name, &block)
352
- end
386
+ def type_for(field, &block)
387
+ field_name = field.respond_to?(:name) ? field.name.to_s : field.to_s.split(".").last
388
+ @klass.type_for_attribute(field_name, &block)
389
+ end
353
390
 
354
- def type_cast_calculated_value(value, type, operation = nil)
355
- case operation
356
- when 'count' then value.to_i
357
- when 'sum' then type.deserialize(value || 0)
358
- when 'average' then value.respond_to?(:to_d) ? value.to_d : value
391
+ def type_cast_calculated_value(value, type, operation = nil)
392
+ case operation
393
+ when "count" then value.to_i
394
+ when "sum" then type.deserialize(value || 0)
395
+ when "average" then value&.respond_to?(:to_d) ? value.to_d : value
359
396
  else type.deserialize(value)
397
+ end
360
398
  end
361
- end
362
399
 
363
- def select_for_count
364
- if select_values.present?
365
- return select_values.first if select_values.one?
366
- select_values.join(", ")
367
- else
368
- :all
400
+ def select_for_count
401
+ if select_values.present?
402
+ return select_values.first if select_values.one?
403
+ select_values.join(", ")
404
+ else
405
+ :all
406
+ end
369
407
  end
370
- end
371
408
 
372
- def build_count_subquery(relation, column_name, distinct)
373
- column_alias = Arel.sql('count_column')
374
- subquery_alias = Arel.sql('subquery_for_count')
409
+ def build_count_subquery(relation, column_name, distinct)
410
+ if column_name == :all
411
+ column_alias = Arel.star
412
+ relation.select_values = [ Arel.sql(FinderMethods::ONE_AS_ONE) ] unless distinct
413
+ else
414
+ column_alias = Arel.sql("count_column")
415
+ relation.select_values = [ aggregate_column(column_name).as(column_alias) ]
416
+ end
375
417
 
376
- aliased_column = aggregate_column(column_name == :all ? 1 : column_name).as(column_alias)
377
- relation.select_values = [aliased_column]
378
- subquery = relation.arel.as(subquery_alias)
418
+ subquery_alias = Arel.sql("subquery_for_count")
419
+ select_value = operation_over_aggregate_column(column_alias, "count", false)
379
420
 
380
- sm = Arel::SelectManager.new relation.engine
381
- select_value = operation_over_aggregate_column(column_alias, 'count', distinct)
382
- sm.project(select_value).from(subquery)
383
- end
421
+ relation.build_subquery(subquery_alias, select_value)
422
+ end
384
423
  end
385
424
  end
@@ -1,4 +1,6 @@
1
- require 'active_support/concern'
1
+ # frozen_string_literal: true
2
+
3
+ require "mutex_m"
2
4
 
3
5
  module ActiveRecord
4
6
  module Delegation # :nodoc:
@@ -17,7 +19,11 @@ module ActiveRecord
17
19
  delegate = Class.new(klass) {
18
20
  include ClassSpecificRelation
19
21
  }
20
- const_set klass.name.gsub('::'.freeze, '_'.freeze), delegate
22
+ include_relation_methods(delegate)
23
+ mangled_name = klass.name.gsub("::", "_")
24
+ const_set mangled_name, delegate
25
+ private_constant mangled_name
26
+
21
27
  cache[klass] = delegate
22
28
  end
23
29
  end
@@ -26,8 +32,49 @@ module ActiveRecord
26
32
  child_class.initialize_relation_delegate_cache
27
33
  super
28
34
  end
35
+
36
+ def generate_relation_method(method)
37
+ generated_relation_methods.generate_method(method)
38
+ end
39
+
40
+ protected
41
+ def include_relation_methods(delegate)
42
+ superclass.include_relation_methods(delegate) unless base_class?
43
+ delegate.include generated_relation_methods
44
+ end
45
+
46
+ private
47
+ def generated_relation_methods
48
+ @generated_relation_methods ||= GeneratedRelationMethods.new.tap do |mod|
49
+ const_set(:GeneratedRelationMethods, mod)
50
+ private_constant :GeneratedRelationMethods
51
+ end
52
+ end
29
53
  end
30
54
 
55
+ class GeneratedRelationMethods < Module # :nodoc:
56
+ include Mutex_m
57
+
58
+ def generate_method(method)
59
+ synchronize do
60
+ return if method_defined?(method)
61
+
62
+ if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method)
63
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
64
+ def #{method}(*args, &block)
65
+ scoping { klass.#{method}(*args, &block) }
66
+ end
67
+ RUBY
68
+ else
69
+ define_method(method) do |*args, &block|
70
+ scoping { klass.public_send(method, *args, &block) }
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ private_constant :GeneratedRelationMethods
77
+
31
78
  extend ActiveSupport::Concern
32
79
 
33
80
  # This module creates compiled delegation methods dynamically at runtime, which makes
@@ -35,65 +82,32 @@ module ActiveRecord
35
82
  # may vary depending on the klass of a relation, so we create a subclass of Relation
36
83
  # for each different klass, and the delegations are compiled into that subclass only.
37
84
 
38
- delegate :to_xml, :encode_with, :length, :collect, :map, :each, :all?, :include?, :to_ary, :join,
39
- :[], :&, :|, :+, :-, :sample, :reverse, :compact, :in_groups, :in_groups_of,
40
- :to_sentence, :to_formatted_s,
41
- :shuffle, :split, :index, to: :records
85
+ delegate :to_xml, :encode_with, :length, :each, :join,
86
+ :[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
87
+ :to_sentence, :to_formatted_s, :as_json,
88
+ :shuffle, :split, :slice, :index, :rindex, to: :records
42
89
 
43
- delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key,
44
- :connection, :columns_hash, :to => :klass
90
+ delegate :primary_key, :connection, to: :klass
45
91
 
46
92
  module ClassSpecificRelation # :nodoc:
47
93
  extend ActiveSupport::Concern
48
94
 
49
- included do
50
- @delegation_mutex = Mutex.new
51
- end
52
-
53
95
  module ClassMethods # :nodoc:
54
96
  def name
55
97
  superclass.name
56
98
  end
99
+ end
57
100
 
58
- def delegate_to_scoped_klass(method)
59
- @delegation_mutex.synchronize do
60
- return if method_defined?(method)
61
-
62
- if method.to_s =~ /\A[a-zA-Z_]\w*[!?]?\z/
63
- module_eval <<-RUBY, __FILE__, __LINE__ + 1
64
- def #{method}(*args, &block)
65
- scoping { @klass.#{method}(*args, &block) }
66
- end
67
- RUBY
68
- else
69
- define_method method do |*args, &block|
70
- scoping { @klass.public_send(method, *args, &block) }
71
- end
72
- end
73
- end
74
- end
101
+ private
75
102
 
76
- def delegate(method, opts = {})
77
- @delegation_mutex.synchronize do
78
- return if method_defined?(method)
103
+ def method_missing(method, *args, &block)
104
+ if @klass.respond_to?(method)
105
+ @klass.generate_relation_method(method)
106
+ scoping { @klass.public_send(method, *args, &block) }
107
+ else
79
108
  super
80
109
  end
81
110
  end
82
- end
83
-
84
- protected
85
-
86
- def method_missing(method, *args, &block)
87
- if @klass.respond_to?(method)
88
- self.class.delegate_to_scoped_klass(method)
89
- scoping { @klass.public_send(method, *args, &block) }
90
- elsif arel.respond_to?(method)
91
- self.class.delegate method, :to => :arel
92
- arel.public_send(method, *args, &block)
93
- else
94
- super
95
- end
96
- end
97
111
  end
98
112
 
99
113
  module ClassMethods # :nodoc:
@@ -103,26 +117,14 @@ module ActiveRecord
103
117
 
104
118
  private
105
119
 
106
- def relation_class_for(klass)
107
- klass.relation_delegate_class(self)
108
- end
109
- end
110
-
111
- def respond_to?(method, include_private = false)
112
- super || @klass.respond_to?(method, include_private) ||
113
- arel.respond_to?(method, include_private)
120
+ def relation_class_for(klass)
121
+ klass.relation_delegate_class(self)
122
+ end
114
123
  end
115
124
 
116
- protected
117
-
118
- def method_missing(method, *args, &block)
119
- if @klass.respond_to?(method)
120
- scoping { @klass.public_send(method, *args, &block) }
121
- elsif arel.respond_to?(method)
122
- arel.public_send(method, *args, &block)
123
- else
124
- super
125
+ private
126
+ def respond_to_missing?(method, _)
127
+ super || @klass.respond_to?(method)
125
128
  end
126
- end
127
129
  end
128
130
  end