activerecord 3.2.6 → 6.0.0

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 (371) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +611 -6417
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +44 -47
  5. data/examples/performance.rb +79 -71
  6. data/examples/simple.rb +6 -5
  7. data/lib/active_record/aggregations.rb +268 -238
  8. data/lib/active_record/association_relation.rb +40 -0
  9. data/lib/active_record/associations/alias_tracker.rb +47 -42
  10. data/lib/active_record/associations/association.rb +173 -81
  11. data/lib/active_record/associations/association_scope.rb +124 -92
  12. data/lib/active_record/associations/belongs_to_association.rb +83 -38
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +11 -9
  14. data/lib/active_record/associations/builder/association.rb +113 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +105 -60
  16. data/lib/active_record/associations/builder/collection_association.rb +53 -56
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +98 -41
  18. data/lib/active_record/associations/builder/has_many.rb +11 -63
  19. data/lib/active_record/associations/builder/has_one.rb +47 -45
  20. data/lib/active_record/associations/builder/singular_association.rb +30 -18
  21. data/lib/active_record/associations/collection_association.rb +217 -295
  22. data/lib/active_record/associations/collection_proxy.rb +1074 -77
  23. data/lib/active_record/associations/foreign_association.rb +20 -0
  24. data/lib/active_record/associations/has_many_association.rb +78 -50
  25. data/lib/active_record/associations/has_many_through_association.rb +99 -61
  26. data/lib/active_record/associations/has_one_association.rb +75 -30
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +45 -119
  29. data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
  30. data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
  31. data/lib/active_record/associations/join_dependency.rb +208 -164
  32. data/lib/active_record/associations/preloader/association.rb +93 -87
  33. data/lib/active_record/associations/preloader/through_association.rb +87 -38
  34. data/lib/active_record/associations/preloader.rb +134 -110
  35. data/lib/active_record/associations/singular_association.rb +19 -24
  36. data/lib/active_record/associations/through_association.rb +61 -27
  37. data/lib/active_record/associations.rb +1766 -1505
  38. data/lib/active_record/attribute_assignment.rb +57 -193
  39. data/lib/active_record/attribute_decorators.rb +90 -0
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +58 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +187 -67
  42. data/lib/active_record/attribute_methods/primary_key.rb +100 -78
  43. data/lib/active_record/attribute_methods/query.rb +10 -8
  44. data/lib/active_record/attribute_methods/read.rb +29 -118
  45. data/lib/active_record/attribute_methods/serialization.rb +60 -72
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -42
  47. data/lib/active_record/attribute_methods/write.rb +36 -44
  48. data/lib/active_record/attribute_methods.rb +306 -161
  49. data/lib/active_record/attributes.rb +279 -0
  50. data/lib/active_record/autosave_association.rb +324 -238
  51. data/lib/active_record/base.rb +114 -507
  52. data/lib/active_record/callbacks.rb +147 -83
  53. data/lib/active_record/coders/json.rb +15 -0
  54. data/lib/active_record/coders/yaml_column.rb +32 -23
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +962 -279
  56. data/lib/active_record/connection_adapters/abstract/database_limits.rb +32 -5
  57. data/lib/active_record/connection_adapters/abstract/database_statements.rb +331 -209
  58. data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -23
  59. data/lib/active_record/connection_adapters/abstract/quoting.rb +201 -65
  60. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +510 -289
  63. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1182 -313
  65. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  66. data/lib/active_record/connection_adapters/abstract_adapter.rb +585 -120
  67. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +610 -463
  68. data/lib/active_record/connection_adapters/column.rb +58 -233
  69. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  70. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  71. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
  73. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  74. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  79. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +75 -207
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  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 +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  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 +41 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +695 -1052
  116. data/lib/active_record/connection_adapters/schema_cache.rb +115 -24
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  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 +528 -26
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +267 -0
  128. data/lib/active_record/core.rb +599 -0
  129. data/lib/active_record/counter_cache.rb +177 -103
  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 +107 -64
  136. data/lib/active_record/enum.rb +274 -0
  137. data/lib/active_record/errors.rb +254 -61
  138. data/lib/active_record/explain.rb +35 -70
  139. data/lib/active_record/explain_registry.rb +32 -0
  140. data/lib/active_record/explain_subscriber.rb +18 -8
  141. data/lib/active_record/fixture_set/file.rb +82 -0
  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 +291 -475
  147. data/lib/active_record/gem_version.rb +17 -0
  148. data/lib/active_record/inheritance.rb +219 -100
  149. data/lib/active_record/insert_all.rb +179 -0
  150. data/lib/active_record/integration.rb +175 -17
  151. data/lib/active_record/internal_metadata.rb +53 -0
  152. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  153. data/lib/active_record/locale/en.yml +9 -1
  154. data/lib/active_record/locking/optimistic.rb +106 -92
  155. data/lib/active_record/locking/pessimistic.rb +23 -11
  156. data/lib/active_record/log_subscriber.rb +80 -30
  157. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  158. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  159. data/lib/active_record/middleware/database_selector.rb +75 -0
  160. data/lib/active_record/migration/command_recorder.rb +235 -56
  161. data/lib/active_record/migration/compatibility.rb +244 -0
  162. data/lib/active_record/migration/join_table.rb +17 -0
  163. data/lib/active_record/migration.rb +917 -301
  164. data/lib/active_record/model_schema.rb +351 -175
  165. data/lib/active_record/nested_attributes.rb +366 -235
  166. data/lib/active_record/no_touching.rb +65 -0
  167. data/lib/active_record/null_relation.rb +68 -0
  168. data/lib/active_record/persistence.rb +761 -166
  169. data/lib/active_record/query_cache.rb +22 -44
  170. data/lib/active_record/querying.rb +55 -31
  171. data/lib/active_record/railtie.rb +185 -47
  172. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  173. data/lib/active_record/railties/console_sandbox.rb +5 -4
  174. data/lib/active_record/railties/controller_runtime.rb +35 -33
  175. data/lib/active_record/railties/databases.rake +366 -463
  176. data/lib/active_record/readonly_attributes.rb +4 -6
  177. data/lib/active_record/reflection.rb +736 -228
  178. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  179. data/lib/active_record/relation/batches.rb +252 -52
  180. data/lib/active_record/relation/calculations.rb +340 -270
  181. data/lib/active_record/relation/delegation.rb +117 -36
  182. data/lib/active_record/relation/finder_methods.rb +439 -286
  183. data/lib/active_record/relation/from_clause.rb +26 -0
  184. data/lib/active_record/relation/merger.rb +184 -0
  185. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  186. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  187. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  188. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  189. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  190. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  191. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder.rb +131 -39
  193. data/lib/active_record/relation/query_attribute.rb +50 -0
  194. data/lib/active_record/relation/query_methods.rb +1163 -221
  195. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  196. data/lib/active_record/relation/spawn_methods.rb +49 -120
  197. data/lib/active_record/relation/where_clause.rb +190 -0
  198. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  199. data/lib/active_record/relation.rb +671 -349
  200. data/lib/active_record/result.rb +149 -15
  201. data/lib/active_record/runtime_registry.rb +24 -0
  202. data/lib/active_record/sanitization.rb +153 -133
  203. data/lib/active_record/schema.rb +22 -19
  204. data/lib/active_record/schema_dumper.rb +178 -112
  205. data/lib/active_record/schema_migration.rb +60 -0
  206. data/lib/active_record/scoping/default.rb +107 -98
  207. data/lib/active_record/scoping/named.rb +130 -115
  208. data/lib/active_record/scoping.rb +77 -123
  209. data/lib/active_record/secure_token.rb +40 -0
  210. data/lib/active_record/serialization.rb +10 -6
  211. data/lib/active_record/statement_cache.rb +148 -0
  212. data/lib/active_record/store.rb +256 -16
  213. data/lib/active_record/suppressor.rb +61 -0
  214. data/lib/active_record/table_metadata.rb +75 -0
  215. data/lib/active_record/tasks/database_tasks.rb +506 -0
  216. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  217. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  218. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  219. data/lib/active_record/test_databases.rb +23 -0
  220. data/lib/active_record/test_fixtures.rb +224 -0
  221. data/lib/active_record/timestamp.rb +93 -39
  222. data/lib/active_record/touch_later.rb +66 -0
  223. data/lib/active_record/transactions.rb +260 -129
  224. data/lib/active_record/translation.rb +3 -1
  225. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  226. data/lib/active_record/type/date.rb +9 -0
  227. data/lib/active_record/type/date_time.rb +9 -0
  228. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  229. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  230. data/lib/active_record/type/internal/timezone.rb +17 -0
  231. data/lib/active_record/type/json.rb +30 -0
  232. data/lib/active_record/type/serialized.rb +71 -0
  233. data/lib/active_record/type/text.rb +11 -0
  234. data/lib/active_record/type/time.rb +21 -0
  235. data/lib/active_record/type/type_map.rb +62 -0
  236. data/lib/active_record/type/unsigned_integer.rb +17 -0
  237. data/lib/active_record/type.rb +78 -0
  238. data/lib/active_record/type_caster/connection.rb +34 -0
  239. data/lib/active_record/type_caster/map.rb +20 -0
  240. data/lib/active_record/type_caster.rb +9 -0
  241. data/lib/active_record/validations/absence.rb +25 -0
  242. data/lib/active_record/validations/associated.rb +35 -18
  243. data/lib/active_record/validations/length.rb +26 -0
  244. data/lib/active_record/validations/presence.rb +68 -0
  245. data/lib/active_record/validations/uniqueness.rb +123 -77
  246. data/lib/active_record/validations.rb +54 -43
  247. data/lib/active_record/version.rb +7 -7
  248. data/lib/active_record.rb +97 -49
  249. data/lib/arel/alias_predication.rb +9 -0
  250. data/lib/arel/attributes/attribute.rb +37 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/collectors/bind.rb +24 -0
  253. data/lib/arel/collectors/composite.rb +31 -0
  254. data/lib/arel/collectors/plain_string.rb +20 -0
  255. data/lib/arel/collectors/sql_string.rb +20 -0
  256. data/lib/arel/collectors/substitute_binds.rb +28 -0
  257. data/lib/arel/crud.rb +42 -0
  258. data/lib/arel/delete_manager.rb +18 -0
  259. data/lib/arel/errors.rb +9 -0
  260. data/lib/arel/expressions.rb +29 -0
  261. data/lib/arel/factory_methods.rb +49 -0
  262. data/lib/arel/insert_manager.rb +49 -0
  263. data/lib/arel/math.rb +45 -0
  264. data/lib/arel/nodes/and.rb +32 -0
  265. data/lib/arel/nodes/ascending.rb +23 -0
  266. data/lib/arel/nodes/binary.rb +52 -0
  267. data/lib/arel/nodes/bind_param.rb +36 -0
  268. data/lib/arel/nodes/case.rb +55 -0
  269. data/lib/arel/nodes/casted.rb +50 -0
  270. data/lib/arel/nodes/comment.rb +29 -0
  271. data/lib/arel/nodes/count.rb +12 -0
  272. data/lib/arel/nodes/delete_statement.rb +45 -0
  273. data/lib/arel/nodes/descending.rb +23 -0
  274. data/lib/arel/nodes/equality.rb +18 -0
  275. data/lib/arel/nodes/extract.rb +24 -0
  276. data/lib/arel/nodes/false.rb +16 -0
  277. data/lib/arel/nodes/full_outer_join.rb +8 -0
  278. data/lib/arel/nodes/function.rb +44 -0
  279. data/lib/arel/nodes/grouping.rb +8 -0
  280. data/lib/arel/nodes/in.rb +8 -0
  281. data/lib/arel/nodes/infix_operation.rb +80 -0
  282. data/lib/arel/nodes/inner_join.rb +8 -0
  283. data/lib/arel/nodes/insert_statement.rb +37 -0
  284. data/lib/arel/nodes/join_source.rb +20 -0
  285. data/lib/arel/nodes/matches.rb +18 -0
  286. data/lib/arel/nodes/named_function.rb +23 -0
  287. data/lib/arel/nodes/node.rb +50 -0
  288. data/lib/arel/nodes/node_expression.rb +13 -0
  289. data/lib/arel/nodes/outer_join.rb +8 -0
  290. data/lib/arel/nodes/over.rb +15 -0
  291. data/lib/arel/nodes/regexp.rb +16 -0
  292. data/lib/arel/nodes/right_outer_join.rb +8 -0
  293. data/lib/arel/nodes/select_core.rb +67 -0
  294. data/lib/arel/nodes/select_statement.rb +41 -0
  295. data/lib/arel/nodes/sql_literal.rb +16 -0
  296. data/lib/arel/nodes/string_join.rb +11 -0
  297. data/lib/arel/nodes/table_alias.rb +27 -0
  298. data/lib/arel/nodes/terminal.rb +16 -0
  299. data/lib/arel/nodes/true.rb +16 -0
  300. data/lib/arel/nodes/unary.rb +45 -0
  301. data/lib/arel/nodes/unary_operation.rb +20 -0
  302. data/lib/arel/nodes/unqualified_column.rb +22 -0
  303. data/lib/arel/nodes/update_statement.rb +41 -0
  304. data/lib/arel/nodes/values_list.rb +9 -0
  305. data/lib/arel/nodes/window.rb +126 -0
  306. data/lib/arel/nodes/with.rb +11 -0
  307. data/lib/arel/nodes.rb +68 -0
  308. data/lib/arel/order_predications.rb +13 -0
  309. data/lib/arel/predications.rb +257 -0
  310. data/lib/arel/select_manager.rb +271 -0
  311. data/lib/arel/table.rb +110 -0
  312. data/lib/arel/tree_manager.rb +72 -0
  313. data/lib/arel/update_manager.rb +34 -0
  314. data/lib/arel/visitors/depth_first.rb +204 -0
  315. data/lib/arel/visitors/dot.rb +297 -0
  316. data/lib/arel/visitors/ibm_db.rb +34 -0
  317. data/lib/arel/visitors/informix.rb +62 -0
  318. data/lib/arel/visitors/mssql.rb +157 -0
  319. data/lib/arel/visitors/mysql.rb +83 -0
  320. data/lib/arel/visitors/oracle.rb +159 -0
  321. data/lib/arel/visitors/oracle12.rb +66 -0
  322. data/lib/arel/visitors/postgresql.rb +110 -0
  323. data/lib/arel/visitors/sqlite.rb +39 -0
  324. data/lib/arel/visitors/to_sql.rb +889 -0
  325. data/lib/arel/visitors/visitor.rb +46 -0
  326. data/lib/arel/visitors/where_sql.rb +23 -0
  327. data/lib/arel/visitors.rb +20 -0
  328. data/lib/arel/window_predications.rb +9 -0
  329. data/lib/arel.rb +51 -0
  330. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  331. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  332. data/lib/rails/generators/active_record/migration/migration_generator.rb +59 -9
  333. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  334. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  335. data/lib/rails/generators/active_record/migration.rb +41 -8
  336. data/lib/rails/generators/active_record/model/model_generator.rb +24 -22
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
  339. data/lib/rails/generators/active_record.rb +10 -16
  340. metadata +285 -149
  341. data/examples/associations.png +0 -0
  342. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  343. data/lib/active_record/associations/join_helper.rb +0 -55
  344. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  345. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  346. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  347. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  348. data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
  349. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  350. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  351. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  352. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  353. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -188
  354. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -426
  355. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -579
  356. data/lib/active_record/dynamic_finder_match.rb +0 -68
  357. data/lib/active_record/dynamic_scope_match.rb +0 -23
  358. data/lib/active_record/fixtures/file.rb +0 -65
  359. data/lib/active_record/identity_map.rb +0 -162
  360. data/lib/active_record/observer.rb +0 -121
  361. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  362. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  363. data/lib/active_record/session_store.rb +0 -358
  364. data/lib/active_record/test_case.rb +0 -73
  365. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
  366. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  367. data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
  368. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  369. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  370. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  371. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,4 +1,4 @@
1
- require 'active_support/concern'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
4
  module Scoping
@@ -6,136 +6,145 @@ module ActiveRecord
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
- # Stores the default scope for the class
10
- class_attribute :default_scopes, :instance_writer => false
11
- self.default_scopes = []
9
+ # Stores the default scope for the class.
10
+ class_attribute :default_scopes, instance_writer: false, instance_predicate: false, default: []
11
+ class_attribute :default_scope_override, instance_writer: false, instance_predicate: false, default: nil
12
12
  end
13
13
 
14
14
  module ClassMethods
15
- # Returns a scope for the model without the default_scope.
15
+ # Returns a scope for the model without the previously set scopes.
16
16
  #
17
17
  # class Post < ActiveRecord::Base
18
18
  # def self.default_scope
19
- # where :published => true
19
+ # where(published: true)
20
20
  # end
21
21
  # end
22
22
  #
23
- # Post.all # Fires "SELECT * FROM posts WHERE published = true"
24
- # Post.unscoped.all # Fires "SELECT * FROM posts"
23
+ # Post.all # Fires "SELECT * FROM posts WHERE published = true"
24
+ # Post.unscoped.all # Fires "SELECT * FROM posts"
25
+ # Post.where(published: false).unscoped.all # Fires "SELECT * FROM posts"
25
26
  #
26
27
  # This method also accepts a block. All queries inside the block will
27
- # not use the default_scope:
28
+ # not use the previously set scopes.
28
29
  #
29
30
  # Post.unscoped {
30
31
  # Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
31
32
  # }
32
- #
33
- # It is recommended to use the block form of unscoped because chaining
34
- # unscoped with <tt>scope</tt> does not work. Assuming that
35
- # <tt>published</tt> is a <tt>scope</tt>, the following two statements
36
- # are equal: the default_scope is applied on both.
37
- #
38
- # Post.unscoped.published
39
- # Post.published
40
- def unscoped #:nodoc:
33
+ def unscoped
41
34
  block_given? ? relation.scoping { yield } : relation
42
35
  end
43
36
 
37
+ # Are there attributes associated with this scope?
38
+ def scope_attributes? # :nodoc:
39
+ super || default_scopes.any? || respond_to?(:default_scope)
40
+ end
41
+
44
42
  def before_remove_const #:nodoc:
45
43
  self.current_scope = nil
46
44
  end
47
45
 
48
- protected
46
+ private
49
47
 
50
- # Use this macro in your model to set a default scope for all operations on
51
- # the model.
52
- #
53
- # class Article < ActiveRecord::Base
54
- # default_scope where(:published => true)
55
- # end
56
- #
57
- # Article.all # => SELECT * FROM articles WHERE published = true
58
- #
59
- # The <tt>default_scope</tt> is also applied while creating/building a record. It is not
60
- # applied while updating a record.
61
- #
62
- # Article.new.published # => true
63
- # Article.create.published # => true
64
- #
65
- # You can also use <tt>default_scope</tt> with a block, in order to have it lazily evaluated:
66
- #
67
- # class Article < ActiveRecord::Base
68
- # default_scope { where(:published_at => Time.now - 1.week) }
69
- # end
70
- #
71
- # (You can also pass any object which responds to <tt>call</tt> to the <tt>default_scope</tt>
72
- # macro, and it will be called when building the default scope.)
73
- #
74
- # If you use multiple <tt>default_scope</tt> declarations in your model then they will
75
- # be merged together:
76
- #
77
- # class Article < ActiveRecord::Base
78
- # default_scope where(:published => true)
79
- # default_scope where(:rating => 'G')
80
- # end
81
- #
82
- # Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
83
- #
84
- # This is also the case with inheritance and module includes where the parent or module
85
- # defines a <tt>default_scope</tt> and the child or including class defines a second one.
86
- #
87
- # If you need to do more complex things with a default scope, you can alternatively
88
- # define it as a class method:
89
- #
90
- # class Article < ActiveRecord::Base
91
- # def self.default_scope
92
- # # Should return a scope, you can call 'super' here etc.
93
- # end
94
- # end
95
- def default_scope(scope = {})
96
- scope = Proc.new if block_given?
97
- self.default_scopes = default_scopes + [scope]
98
- end
48
+ # Use this macro in your model to set a default scope for all operations on
49
+ # the model.
50
+ #
51
+ # class Article < ActiveRecord::Base
52
+ # default_scope { where(published: true) }
53
+ # end
54
+ #
55
+ # Article.all # => SELECT * FROM articles WHERE published = true
56
+ #
57
+ # The #default_scope is also applied while creating/building a record.
58
+ # It is not applied while updating a record.
59
+ #
60
+ # Article.new.published # => true
61
+ # Article.create.published # => true
62
+ #
63
+ # (You can also pass any object which responds to +call+ to the
64
+ # +default_scope+ macro, and it will be called when building the
65
+ # default scope.)
66
+ #
67
+ # If you use multiple #default_scope declarations in your model then
68
+ # they will be merged together:
69
+ #
70
+ # class Article < ActiveRecord::Base
71
+ # default_scope { where(published: true) }
72
+ # default_scope { where(rating: 'G') }
73
+ # end
74
+ #
75
+ # Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
76
+ #
77
+ # This is also the case with inheritance and module includes where the
78
+ # parent or module defines a #default_scope and the child or including
79
+ # class defines a second one.
80
+ #
81
+ # If you need to do more complex things with a default scope, you can
82
+ # alternatively define it as a class method:
83
+ #
84
+ # class Article < ActiveRecord::Base
85
+ # def self.default_scope
86
+ # # Should return a scope, you can call 'super' here etc.
87
+ # end
88
+ # end
89
+ def default_scope(scope = nil, &block) # :doc:
90
+ scope = block if block_given?
91
+
92
+ if scope.is_a?(Relation) || !scope.respond_to?(:call)
93
+ raise ArgumentError,
94
+ "Support for calling #default_scope without a block is removed. For example instead " \
95
+ "of `default_scope where(color: 'red')`, please use " \
96
+ "`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
97
+ "self.default_scope.)"
98
+ end
99
+
100
+ self.default_scopes += [scope]
101
+ end
102
+
103
+ def build_default_scope(relation = relation())
104
+ return if abstract_class?
105
+
106
+ if default_scope_override.nil?
107
+ self.default_scope_override = !Base.is_a?(method(:default_scope).owner)
108
+ end
99
109
 
100
- def build_default_scope #:nodoc:
101
- if method(:default_scope).owner != ActiveRecord::Scoping::Default::ClassMethods
102
- evaluate_default_scope { default_scope }
103
- elsif default_scopes.any?
104
- evaluate_default_scope do
105
- default_scopes.inject(relation) do |default_scope, scope|
106
- if scope.is_a?(Hash)
107
- default_scope.apply_finder_options(scope)
108
- elsif !scope.is_a?(Relation) && scope.respond_to?(:call)
109
- default_scope.merge(scope.call)
110
- else
111
- default_scope.merge(scope)
110
+ if default_scope_override
111
+ # The user has defined their own default scope method, so call that
112
+ evaluate_default_scope do
113
+ if scope = default_scope
114
+ relation.merge!(scope)
115
+ end
116
+ end
117
+ elsif default_scopes.any?
118
+ evaluate_default_scope do
119
+ default_scopes.inject(relation) do |default_scope, scope|
120
+ scope = scope.respond_to?(:to_proc) ? scope : scope.method(:call)
121
+ default_scope.instance_exec(&scope) || default_scope
112
122
  end
113
123
  end
114
124
  end
115
125
  end
116
- end
117
126
 
118
- def ignore_default_scope? #:nodoc:
119
- Thread.current["#{self}_ignore_default_scope"]
120
- end
127
+ def ignore_default_scope?
128
+ ScopeRegistry.value_for(:ignore_default_scope, base_class)
129
+ end
121
130
 
122
- def ignore_default_scope=(ignore) #:nodoc:
123
- Thread.current["#{self}_ignore_default_scope"] = ignore
124
- end
131
+ def ignore_default_scope=(ignore)
132
+ ScopeRegistry.set_value_for(:ignore_default_scope, base_class, ignore)
133
+ end
125
134
 
126
- # The ignore_default_scope flag is used to prevent an infinite recursion situation where
127
- # a default scope references a scope which has a default scope which references a scope...
128
- def evaluate_default_scope
129
- return if ignore_default_scope?
135
+ # The ignore_default_scope flag is used to prevent an infinite recursion
136
+ # situation where a default scope references a scope which has a default
137
+ # scope which references a scope...
138
+ def evaluate_default_scope
139
+ return if ignore_default_scope?
130
140
 
131
- begin
132
- self.ignore_default_scope = true
133
- yield
134
- ensure
135
- self.ignore_default_scope = false
141
+ begin
142
+ self.ignore_default_scope = true
143
+ yield
144
+ ensure
145
+ self.ignore_default_scope = false
146
+ end
136
147
  end
137
- end
138
-
139
148
  end
140
149
  end
141
150
  end
@@ -1,139 +1,136 @@
1
- require 'active_support/core_ext/array'
2
- require 'active_support/core_ext/hash/except'
3
- require 'active_support/core_ext/kernel/singleton_class'
4
- require 'active_support/core_ext/object/blank'
5
- require 'active_support/core_ext/class/attribute'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array"
4
+ require "active_support/core_ext/hash/except"
5
+ require "active_support/core_ext/kernel/singleton_class"
6
6
 
7
7
  module ActiveRecord
8
- # = Active Record Named \Scopes
8
+ # = Active Record \Named \Scopes
9
9
  module Scoping
10
10
  module Named
11
11
  extend ActiveSupport::Concern
12
12
 
13
13
  module ClassMethods
14
- # Returns an anonymous \scope.
14
+ # Returns an ActiveRecord::Relation scope object.
15
15
  #
16
- # posts = Post.scoped
16
+ # posts = Post.all
17
17
  # posts.size # Fires "select count(*) from posts" and returns the count
18
18
  # posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
19
19
  #
20
- # fruits = Fruit.scoped
21
- # fruits = fruits.where(:color => 'red') if options[:red_only]
20
+ # fruits = Fruit.all
21
+ # fruits = fruits.where(color: 'red') if options[:red_only]
22
22
  # fruits = fruits.limit(10) if limited?
23
23
  #
24
- # Anonymous \scopes tend to be useful when procedurally generating complex
25
- # queries, where passing intermediate values (\scopes) around as first-class
26
- # objects is convenient.
27
- #
28
- # You can define a \scope that applies to all finders using
29
- # ActiveRecord::Base.default_scope.
30
- def scoped(options = nil)
31
- if options
32
- scoped.apply_finder_options(options)
33
- else
34
- if current_scope
35
- current_scope.clone
24
+ # You can define a scope that applies to all finders using
25
+ # {default_scope}[rdoc-ref:Scoping::Default::ClassMethods#default_scope].
26
+ def all
27
+ scope = current_scope
28
+
29
+ if scope
30
+ if scope._deprecated_scope_source
31
+ ActiveSupport::Deprecation.warn(<<~MSG.squish)
32
+ Class level methods will no longer inherit scoping from `#{scope._deprecated_scope_source}`
33
+ in Rails 6.1. To continue using the scoped relation, pass it into the block directly.
34
+ To instead access the full set of models, as Rails 6.1 will, use `#{name}.unscoped`.
35
+ MSG
36
+ end
37
+
38
+ if self == scope.klass
39
+ scope.clone
36
40
  else
37
- scope = relation.clone
38
- scope.default_scoped = true
39
- scope
41
+ relation.merge!(scope)
40
42
  end
43
+ else
44
+ default_scoped
41
45
  end
42
46
  end
43
47
 
44
- ##
45
- # Collects attributes from scopes that should be applied when creating
46
- # an AR instance for the particular class this is called on.
47
- def scope_attributes # :nodoc:
48
- if current_scope
49
- current_scope.scope_for_create
48
+ def scope_for_association(scope = relation) # :nodoc:
49
+ if current_scope&.empty_scope?
50
+ scope
50
51
  else
51
- scope = relation.clone
52
- scope.default_scoped = true
53
- scope.scope_for_create
52
+ default_scoped(scope)
54
53
  end
55
54
  end
56
55
 
57
- ##
58
- # Are there default attributes associated with this scope?
59
- def scope_attributes? # :nodoc:
60
- current_scope || default_scopes.any?
56
+ def default_scoped(scope = relation) # :nodoc:
57
+ build_default_scope(scope) || scope
61
58
  end
62
59
 
63
- # Adds a class method for retrieving and querying objects. A \scope represents a narrowing of a database query,
64
- # such as <tt>where(:color => :red).select('shirts.*').includes(:washing_instructions)</tt>.
60
+ def default_extensions # :nodoc:
61
+ if scope = scope_for_association || build_default_scope
62
+ scope.extensions
63
+ else
64
+ []
65
+ end
66
+ end
67
+
68
+ # Adds a class method for retrieving and querying objects.
69
+ # The method is intended to return an ActiveRecord::Relation
70
+ # object, which is composable with other scopes.
71
+ # If it returns +nil+ or +false+, an
72
+ # {all}[rdoc-ref:Scoping::Named::ClassMethods#all] scope is returned instead.
73
+ #
74
+ # A \scope represents a narrowing of a database query, such as
75
+ # <tt>where(color: :red).select('shirts.*').includes(:washing_instructions)</tt>.
65
76
  #
66
77
  # class Shirt < ActiveRecord::Base
67
- # scope :red, where(:color => 'red')
68
- # scope :dry_clean_only, joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true)
78
+ # scope :red, -> { where(color: 'red') }
79
+ # scope :dry_clean_only, -> { joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true) }
69
80
  # end
70
81
  #
71
- # The above calls to <tt>scope</tt> define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red,
72
- # in effect, represents the query <tt>Shirt.where(:color => 'red')</tt>.
82
+ # The above calls to #scope define class methods <tt>Shirt.red</tt> and
83
+ # <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>, in effect,
84
+ # represents the query <tt>Shirt.where(color: 'red')</tt>.
85
+ #
86
+ # You should always pass a callable object to the scopes defined
87
+ # with #scope. This ensures that the scope is re-evaluated each
88
+ # time it is called.
73
89
  #
74
- # Note that this is simply 'syntactic sugar' for defining an actual class method:
90
+ # Note that this is simply 'syntactic sugar' for defining an actual
91
+ # class method:
75
92
  #
76
93
  # class Shirt < ActiveRecord::Base
77
94
  # def self.red
78
- # where(:color => 'red')
95
+ # where(color: 'red')
79
96
  # end
80
97
  # end
81
98
  #
82
- # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by Shirt.red is not an Array; it
83
- # resembles the association object constructed by a <tt>has_many</tt> declaration. For instance,
84
- # you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>, <tt>Shirt.red.where(:size => 'small')</tt>.
85
- # Also, just as with the association objects, named \scopes act like an Array, implementing Enumerable;
86
- # <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt>
87
- # all behave as if Shirt.red really was an Array.
88
- #
89
- # These named \scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce
90
- # all shirts that are both red and dry clean only.
91
- # Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt>
92
- # returns the number of garments for which these criteria obtain. Similarly with
93
- # <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
94
- #
95
- # All \scopes are available as class methods on the ActiveRecord::Base descendant upon which
96
- # the \scopes were defined. But they are also available to <tt>has_many</tt> associations. If,
99
+ # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by
100
+ # <tt>Shirt.red</tt> is not an Array but an ActiveRecord::Relation,
101
+ # which is composable with other scopes; it resembles the association object
102
+ # constructed by a {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
103
+ # declaration. For instance, you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
104
+ # <tt>Shirt.red.where(size: 'small')</tt>. Also, just as with the
105
+ # association objects, named \scopes act like an Array, implementing
106
+ # Enumerable; <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>,
107
+ # and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if
108
+ # <tt>Shirt.red</tt> really was an array.
109
+ #
110
+ # These named \scopes are composable. For instance,
111
+ # <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are
112
+ # both red and dry clean only. Nested finds and calculations also work
113
+ # with these compositions: <tt>Shirt.red.dry_clean_only.count</tt>
114
+ # returns the number of garments for which these criteria obtain.
115
+ # Similarly with <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
116
+ #
117
+ # All scopes are available as class methods on the ActiveRecord::Base
118
+ # descendant upon which the \scopes were defined. But they are also
119
+ # available to {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
120
+ # associations. If,
97
121
  #
98
122
  # class Person < ActiveRecord::Base
99
123
  # has_many :shirts
100
124
  # end
101
125
  #
102
- # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of Elton's red, dry clean
103
- # only shirts.
104
- #
105
- # Named \scopes can also be procedural:
106
- #
107
- # class Shirt < ActiveRecord::Base
108
- # scope :colored, lambda { |color| where(:color => color) }
109
- # end
110
- #
111
- # In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
126
+ # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of
127
+ # Elton's red, dry clean only shirts.
112
128
  #
113
- # On Ruby 1.9 you can use the 'stabby lambda' syntax:
114
- #
115
- # scope :colored, ->(color) { where(:color => color) }
116
- #
117
- # Note that scopes defined with \scope will be evaluated when they are defined, rather than
118
- # when they are used. For example, the following would be incorrect:
119
- #
120
- # class Post < ActiveRecord::Base
121
- # scope :recent, where('published_at >= ?', Time.current - 1.week)
122
- # end
123
- #
124
- # The example above would be 'frozen' to the <tt>Time.current</tt> value when the <tt>Post</tt>
125
- # class was defined, and so the resultant SQL query would always be the same. The correct
126
- # way to do this would be via a lambda, which will re-evaluate the scope each time
127
- # it is called:
128
- #
129
- # class Post < ActiveRecord::Base
130
- # scope :recent, lambda { where('published_at >= ?', Time.current - 1.week) }
131
- # end
132
- #
133
- # Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:
129
+ # \Named scopes can also have extensions, just as with
130
+ # {has_many}[rdoc-ref:Associations::ClassMethods#has_many] declarations:
134
131
  #
135
132
  # class Shirt < ActiveRecord::Base
136
- # scope :red, where(:color => 'red') do
133
+ # scope :red, -> { where(color: 'red') } do
137
134
  # def dom_id
138
135
  # 'red_shirts'
139
136
  # end
@@ -143,59 +140,77 @@ module ActiveRecord
143
140
  # Scopes can also be used while creating/building a record.
144
141
  #
145
142
  # class Article < ActiveRecord::Base
146
- # scope :published, where(:published => true)
143
+ # scope :published, -> { where(published: true) }
147
144
  # end
148
145
  #
149
146
  # Article.published.new.published # => true
150
147
  # Article.published.create.published # => true
151
148
  #
152
- # Class methods on your model are automatically available
149
+ # \Class methods on your model are automatically available
153
150
  # on scopes. Assuming the following setup:
154
151
  #
155
152
  # class Article < ActiveRecord::Base
156
- # scope :published, where(:published => true)
157
- # scope :featured, where(:featured => true)
153
+ # scope :published, -> { where(published: true) }
154
+ # scope :featured, -> { where(featured: true) }
158
155
  #
159
156
  # def self.latest_article
160
157
  # order('published_at desc').first
161
158
  # end
162
159
  #
163
160
  # def self.titles
164
- # map(&:title)
161
+ # pluck(:title)
165
162
  # end
166
- #
167
163
  # end
168
164
  #
169
165
  # We are able to call the methods like this:
170
166
  #
171
167
  # Article.published.featured.latest_article
172
168
  # Article.featured.titles
169
+ def scope(name, body, &block)
170
+ unless body.respond_to?(:call)
171
+ raise ArgumentError, "The scope body needs to be callable."
172
+ end
173
173
 
174
- def scope(name, scope_options = {})
175
- name = name.to_sym
176
- valid_scope_name?(name)
177
- extension = Module.new(&Proc.new) if block_given?
174
+ if dangerous_class_method?(name)
175
+ raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
176
+ "on the model \"#{self.name}\", but Active Record already defined " \
177
+ "a class method with the same name."
178
+ end
178
179
 
179
- scope_proc = lambda do |*args|
180
- options = scope_options.respond_to?(:call) ? unscoped { scope_options.call(*args) } : scope_options
181
- options = scoped.apply_finder_options(options) if options.is_a?(Hash)
180
+ if method_defined_within?(name, Relation)
181
+ raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
182
+ "on the model \"#{self.name}\", but ActiveRecord::Relation already defined " \
183
+ "an instance method with the same name."
184
+ end
182
185
 
183
- relation = scoped.merge(options)
186
+ valid_scope_name?(name)
187
+ extension = Module.new(&block) if block
184
188
 
185
- extension ? relation.extending(extension) : relation
189
+ if body.respond_to?(:to_proc)
190
+ singleton_class.define_method(name) do |*args|
191
+ scope = all._exec_scope(name, *args, &body)
192
+ scope = scope.extending(extension) if extension
193
+ scope
194
+ end
195
+ else
196
+ singleton_class.define_method(name) do |*args|
197
+ scope = body.call(*args) || all
198
+ scope = scope.extending(extension) if extension
199
+ scope
200
+ end
186
201
  end
187
202
 
188
- singleton_class.send(:redefine_method, name, &scope_proc)
203
+ generate_relation_method(name)
189
204
  end
190
205
 
191
- protected
206
+ private
192
207
 
193
- def valid_scope_name?(name)
194
- if logger && respond_to?(name, true)
195
- logger.warn "Creating scope :#{name}. " \
196
- "Overwriting existing method #{self.name}.#{name}."
208
+ def valid_scope_name?(name)
209
+ if respond_to?(name, true) && logger
210
+ logger.warn "Creating scope :#{name}. " \
211
+ "Overwriting existing method #{self.name}.#{name}."
212
+ end
197
213
  end
198
- end
199
214
  end
200
215
  end
201
216
  end