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,6 +1,9 @@
1
- require 'active_support/core_ext/hash/except'
2
- require 'active_support/core_ext/object/try'
3
- require 'active_support/core_ext/hash/indifferent_access'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/except"
4
+ require "active_support/core_ext/module/redefine_method"
5
+ require "active_support/core_ext/object/try"
6
+ require "active_support/core_ext/hash/indifferent_access"
4
7
 
5
8
  module ActiveRecord
6
9
  module NestedAttributes #:nodoc:
@@ -10,8 +13,7 @@ module ActiveRecord
10
13
  extend ActiveSupport::Concern
11
14
 
12
15
  included do
13
- class_attribute :nested_attributes_options, instance_writer: false
14
- self.nested_attributes_options = {}
16
+ class_attribute :nested_attributes_options, instance_writer: false, default: {}
15
17
  end
16
18
 
17
19
  # = Active Record Nested Attributes
@@ -61,6 +63,18 @@ module ActiveRecord
61
63
  # member.update params[:member]
62
64
  # member.avatar.icon # => 'sad'
63
65
  #
66
+ # If you want to update the current avatar without providing the id, you must add <tt>:update_only</tt> option.
67
+ #
68
+ # class Member < ActiveRecord::Base
69
+ # has_one :avatar
70
+ # accepts_nested_attributes_for :avatar, update_only: true
71
+ # end
72
+ #
73
+ # params = { member: { avatar_attributes: { icon: 'sad' } } }
74
+ # member.update params[:member]
75
+ # member.avatar.id # => 2
76
+ # member.avatar.icon # => 'sad'
77
+ #
64
78
  # By default you will only be able to set and update attributes on the
65
79
  # associated model. If you want to destroy the associated model through the
66
80
  # attributes hash, you have to enable it first using the
@@ -267,7 +281,7 @@ module ActiveRecord
267
281
  # member.avatar_attributes = {icon: 'sad'}
268
282
  # member.avatar.width # => 200
269
283
  module ClassMethods
270
- REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |key, value| key == '_destroy' || value.blank? } }
284
+ REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |key, value| key == "_destroy" || value.blank? } }
271
285
 
272
286
  # Defines an attributes writer for the specified association(s).
273
287
  #
@@ -317,7 +331,7 @@ module ActiveRecord
317
331
  # # creates avatar_attributes= and posts_attributes=
318
332
  # accepts_nested_attributes_for :avatar, :posts, allow_destroy: true
319
333
  def accepts_nested_attributes_for(*attr_names)
320
- options = { :allow_destroy => false, :update_only => false }
334
+ options = { allow_destroy: false, update_only: false }
321
335
  options.update(attr_names.extract_options!)
322
336
  options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :update_only)
323
337
  options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
@@ -341,27 +355,25 @@ module ActiveRecord
341
355
 
342
356
  private
343
357
 
344
- # Generates a writer method for this association. Serves as a point for
345
- # accessing the objects in the association. For example, this method
346
- # could generate the following:
347
- #
348
- # def pirate_attributes=(attributes)
349
- # assign_nested_attributes_for_one_to_one_association(:pirate, attributes)
350
- # end
351
- #
352
- # This redirects the attempts to write objects in an association through
353
- # the helper methods defined below. Makes it seem like the nested
354
- # associations are just regular associations.
355
- def generate_association_writer(association_name, type)
356
- generated_association_methods.module_eval <<-eoruby, __FILE__, __LINE__ + 1
357
- if method_defined?(:#{association_name}_attributes=)
358
- remove_method(:#{association_name}_attributes=)
359
- end
360
- def #{association_name}_attributes=(attributes)
361
- assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
362
- end
363
- eoruby
364
- end
358
+ # Generates a writer method for this association. Serves as a point for
359
+ # accessing the objects in the association. For example, this method
360
+ # could generate the following:
361
+ #
362
+ # def pirate_attributes=(attributes)
363
+ # assign_nested_attributes_for_one_to_one_association(:pirate, attributes)
364
+ # end
365
+ #
366
+ # This redirects the attempts to write objects in an association through
367
+ # the helper methods defined below. Makes it seem like the nested
368
+ # associations are just regular associations.
369
+ def generate_association_writer(association_name, type)
370
+ generated_association_methods.module_eval <<-eoruby, __FILE__, __LINE__ + 1
371
+ silence_redefinition_of_method :#{association_name}_attributes=
372
+ def #{association_name}_attributes=(attributes)
373
+ assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
374
+ end
375
+ eoruby
376
+ end
365
377
  end
366
378
 
367
379
  # Returns ActiveRecord::AutosaveAssociation::marked_for_destruction? It's
@@ -375,213 +387,214 @@ module ActiveRecord
375
387
 
376
388
  private
377
389
 
378
- # Attribute hash keys that should not be assigned as normal attributes.
379
- # These hash keys are nested attributes implementation details.
380
- UNASSIGNABLE_KEYS = %w( id _destroy )
381
-
382
- # Assigns the given attributes to the association.
383
- #
384
- # If an associated record does not yet exist, one will be instantiated. If
385
- # an associated record already exists, the method's behavior depends on
386
- # the value of the update_only option. If update_only is +false+ and the
387
- # given attributes include an <tt>:id</tt> that matches the existing record's
388
- # id, then the existing record will be modified. If no <tt>:id</tt> is provided
389
- # it will be replaced with a new record. If update_only is +true+ the existing
390
- # record will be modified regardless of whether an <tt>:id</tt> is provided.
391
- #
392
- # If the given attributes include a matching <tt>:id</tt> attribute, or
393
- # update_only is true, and a <tt>:_destroy</tt> key set to a truthy value,
394
- # then the existing record will be marked for destruction.
395
- def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
396
- options = self.nested_attributes_options[association_name]
397
- if attributes.respond_to?(:permitted?)
398
- attributes = attributes.to_h
399
- end
400
- attributes = attributes.with_indifferent_access
401
- existing_record = send(association_name)
390
+ # Attribute hash keys that should not be assigned as normal attributes.
391
+ # These hash keys are nested attributes implementation details.
392
+ UNASSIGNABLE_KEYS = %w( id _destroy )
393
+
394
+ # Assigns the given attributes to the association.
395
+ #
396
+ # If an associated record does not yet exist, one will be instantiated. If
397
+ # an associated record already exists, the method's behavior depends on
398
+ # the value of the update_only option. If update_only is +false+ and the
399
+ # given attributes include an <tt>:id</tt> that matches the existing record's
400
+ # id, then the existing record will be modified. If no <tt>:id</tt> is provided
401
+ # it will be replaced with a new record. If update_only is +true+ the existing
402
+ # record will be modified regardless of whether an <tt>:id</tt> is provided.
403
+ #
404
+ # If the given attributes include a matching <tt>:id</tt> attribute, or
405
+ # update_only is true, and a <tt>:_destroy</tt> key set to a truthy value,
406
+ # then the existing record will be marked for destruction.
407
+ def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
408
+ options = nested_attributes_options[association_name]
409
+ if attributes.respond_to?(:permitted?)
410
+ attributes = attributes.to_h
411
+ end
412
+ attributes = attributes.with_indifferent_access
413
+ existing_record = send(association_name)
402
414
 
403
- if (options[:update_only] || !attributes['id'].blank?) && existing_record &&
404
- (options[:update_only] || existing_record.id.to_s == attributes['id'].to_s)
405
- assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) unless call_reject_if(association_name, attributes)
415
+ if (options[:update_only] || !attributes["id"].blank?) && existing_record &&
416
+ (options[:update_only] || existing_record.id.to_s == attributes["id"].to_s)
417
+ assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) unless call_reject_if(association_name, attributes)
406
418
 
407
- elsif attributes['id'].present?
408
- raise_nested_attributes_record_not_found!(association_name, attributes['id'])
419
+ elsif attributes["id"].present?
420
+ raise_nested_attributes_record_not_found!(association_name, attributes["id"])
409
421
 
410
- elsif !reject_new_record?(association_name, attributes)
411
- assignable_attributes = attributes.except(*UNASSIGNABLE_KEYS)
422
+ elsif !reject_new_record?(association_name, attributes)
423
+ assignable_attributes = attributes.except(*UNASSIGNABLE_KEYS)
412
424
 
413
- if existing_record && existing_record.new_record?
414
- existing_record.assign_attributes(assignable_attributes)
415
- association(association_name).initialize_attributes(existing_record)
416
- else
417
- method = "build_#{association_name}"
418
- if respond_to?(method)
419
- send(method, assignable_attributes)
425
+ if existing_record && existing_record.new_record?
426
+ existing_record.assign_attributes(assignable_attributes)
427
+ association(association_name).initialize_attributes(existing_record)
420
428
  else
421
- raise ArgumentError, "Cannot build association `#{association_name}'. Are you trying to build a polymorphic one-to-one association?"
429
+ method = :"build_#{association_name}"
430
+ if respond_to?(method)
431
+ send(method, assignable_attributes)
432
+ else
433
+ raise ArgumentError, "Cannot build association `#{association_name}'. Are you trying to build a polymorphic one-to-one association?"
434
+ end
422
435
  end
423
436
  end
424
437
  end
425
- end
426
438
 
427
- # Assigns the given attributes to the collection association.
428
- #
429
- # Hashes with an <tt>:id</tt> value matching an existing associated record
430
- # will update that record. Hashes without an <tt>:id</tt> value will build
431
- # a new record for the association. Hashes with a matching <tt>:id</tt>
432
- # value and a <tt>:_destroy</tt> key set to a truthy value will mark the
433
- # matched record for destruction.
434
- #
435
- # For example:
436
- #
437
- # assign_nested_attributes_for_collection_association(:people, {
438
- # '1' => { id: '1', name: 'Peter' },
439
- # '2' => { name: 'John' },
440
- # '3' => { id: '2', _destroy: true }
441
- # })
442
- #
443
- # Will update the name of the Person with ID 1, build a new associated
444
- # person with the name 'John', and mark the associated Person with ID 2
445
- # for destruction.
446
- #
447
- # Also accepts an Array of attribute hashes:
448
- #
449
- # assign_nested_attributes_for_collection_association(:people, [
450
- # { id: '1', name: 'Peter' },
451
- # { name: 'John' },
452
- # { id: '2', _destroy: true }
453
- # ])
454
- def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
455
- options = self.nested_attributes_options[association_name]
456
- if attributes_collection.respond_to?(:permitted?)
457
- attributes_collection = attributes_collection.to_h
458
- end
439
+ # Assigns the given attributes to the collection association.
440
+ #
441
+ # Hashes with an <tt>:id</tt> value matching an existing associated record
442
+ # will update that record. Hashes without an <tt>:id</tt> value will build
443
+ # a new record for the association. Hashes with a matching <tt>:id</tt>
444
+ # value and a <tt>:_destroy</tt> key set to a truthy value will mark the
445
+ # matched record for destruction.
446
+ #
447
+ # For example:
448
+ #
449
+ # assign_nested_attributes_for_collection_association(:people, {
450
+ # '1' => { id: '1', name: 'Peter' },
451
+ # '2' => { name: 'John' },
452
+ # '3' => { id: '2', _destroy: true }
453
+ # })
454
+ #
455
+ # Will update the name of the Person with ID 1, build a new associated
456
+ # person with the name 'John', and mark the associated Person with ID 2
457
+ # for destruction.
458
+ #
459
+ # Also accepts an Array of attribute hashes:
460
+ #
461
+ # assign_nested_attributes_for_collection_association(:people, [
462
+ # { id: '1', name: 'Peter' },
463
+ # { name: 'John' },
464
+ # { id: '2', _destroy: true }
465
+ # ])
466
+ def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
467
+ options = nested_attributes_options[association_name]
468
+ if attributes_collection.respond_to?(:permitted?)
469
+ attributes_collection = attributes_collection.to_h
470
+ end
459
471
 
460
- unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
461
- raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
462
- end
472
+ unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
473
+ raise ArgumentError, "Hash or Array expected for attribute `#{association_name}`, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
474
+ end
463
475
 
464
- check_record_limit!(options[:limit], attributes_collection)
476
+ check_record_limit!(options[:limit], attributes_collection)
465
477
 
466
- if attributes_collection.is_a? Hash
467
- keys = attributes_collection.keys
468
- attributes_collection = if keys.include?('id') || keys.include?(:id)
469
- [attributes_collection]
470
- else
471
- attributes_collection.values
478
+ if attributes_collection.is_a? Hash
479
+ keys = attributes_collection.keys
480
+ attributes_collection = if keys.include?("id") || keys.include?(:id)
481
+ [attributes_collection]
482
+ else
483
+ attributes_collection.values
484
+ end
472
485
  end
473
- end
474
-
475
- association = association(association_name)
476
486
 
477
- existing_records = if association.loaded?
478
- association.target
479
- else
480
- attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact
481
- attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
482
- end
487
+ association = association(association_name)
483
488
 
484
- attributes_collection.each do |attributes|
485
- if attributes.respond_to?(:permitted?)
486
- attributes = attributes.to_h
489
+ existing_records = if association.loaded?
490
+ association.target
491
+ else
492
+ attribute_ids = attributes_collection.map { |a| a["id"] || a[:id] }.compact
493
+ attribute_ids.empty? ? [] : association.scope.where(association.klass.primary_key => attribute_ids)
487
494
  end
488
- attributes = attributes.with_indifferent_access
489
495
 
490
- if attributes['id'].blank?
491
- unless reject_new_record?(association_name, attributes)
492
- association.build(attributes.except(*UNASSIGNABLE_KEYS))
496
+ attributes_collection.each do |attributes|
497
+ if attributes.respond_to?(:permitted?)
498
+ attributes = attributes.to_h
493
499
  end
494
- elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s }
495
- unless call_reject_if(association_name, attributes)
496
- # Make sure we are operating on the actual object which is in the association's
497
- # proxy_target array (either by finding it, or adding it if not found)
498
- # Take into account that the proxy_target may have changed due to callbacks
499
- target_record = association.target.detect { |record| record.id.to_s == attributes['id'].to_s }
500
- if target_record
501
- existing_record = target_record
502
- else
503
- association.add_to_target(existing_record, :skip_callbacks)
504
- end
500
+ attributes = attributes.with_indifferent_access
505
501
 
506
- assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
502
+ if attributes["id"].blank?
503
+ unless reject_new_record?(association_name, attributes)
504
+ association.reader.build(attributes.except(*UNASSIGNABLE_KEYS))
505
+ end
506
+ elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes["id"].to_s }
507
+ unless call_reject_if(association_name, attributes)
508
+ # Make sure we are operating on the actual object which is in the association's
509
+ # proxy_target array (either by finding it, or adding it if not found)
510
+ # Take into account that the proxy_target may have changed due to callbacks
511
+ target_record = association.target.detect { |record| record.id.to_s == attributes["id"].to_s }
512
+ if target_record
513
+ existing_record = target_record
514
+ else
515
+ association.add_to_target(existing_record, :skip_callbacks)
516
+ end
517
+
518
+ assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
519
+ end
520
+ else
521
+ raise_nested_attributes_record_not_found!(association_name, attributes["id"])
507
522
  end
508
- else
509
- raise_nested_attributes_record_not_found!(association_name, attributes['id'])
510
523
  end
511
524
  end
512
- end
513
525
 
514
- # Takes in a limit and checks if the attributes_collection has too many
515
- # records. It accepts limit in the form of symbol, proc, or
516
- # number-like object (anything that can be compared with an integer).
517
- #
518
- # Raises TooManyRecords error if the attributes_collection is
519
- # larger than the limit.
520
- def check_record_limit!(limit, attributes_collection)
521
- if limit
522
- limit = case limit
523
- when Symbol
524
- send(limit)
525
- when Proc
526
- limit.call
527
- else
528
- limit
529
- end
526
+ # Takes in a limit and checks if the attributes_collection has too many
527
+ # records. It accepts limit in the form of symbol, proc, or
528
+ # number-like object (anything that can be compared with an integer).
529
+ #
530
+ # Raises TooManyRecords error if the attributes_collection is
531
+ # larger than the limit.
532
+ def check_record_limit!(limit, attributes_collection)
533
+ if limit
534
+ limit = \
535
+ case limit
536
+ when Symbol
537
+ send(limit)
538
+ when Proc
539
+ limit.call
540
+ else
541
+ limit
542
+ end
530
543
 
531
- if limit && attributes_collection.size > limit
532
- raise TooManyRecords, "Maximum #{limit} records are allowed. Got #{attributes_collection.size} records instead."
544
+ if limit && attributes_collection.size > limit
545
+ raise TooManyRecords, "Maximum #{limit} records are allowed. Got #{attributes_collection.size} records instead."
546
+ end
533
547
  end
534
548
  end
535
- end
536
549
 
537
- # Updates a record with the +attributes+ or marks it for destruction if
538
- # +allow_destroy+ is +true+ and has_destroy_flag? returns +true+.
539
- def assign_to_or_mark_for_destruction(record, attributes, allow_destroy)
540
- record.assign_attributes(attributes.except(*UNASSIGNABLE_KEYS))
541
- record.mark_for_destruction if has_destroy_flag?(attributes) && allow_destroy
542
- end
550
+ # Updates a record with the +attributes+ or marks it for destruction if
551
+ # +allow_destroy+ is +true+ and has_destroy_flag? returns +true+.
552
+ def assign_to_or_mark_for_destruction(record, attributes, allow_destroy)
553
+ record.assign_attributes(attributes.except(*UNASSIGNABLE_KEYS))
554
+ record.mark_for_destruction if has_destroy_flag?(attributes) && allow_destroy
555
+ end
543
556
 
544
- # Determines if a hash contains a truthy _destroy key.
545
- def has_destroy_flag?(hash)
546
- Type::Boolean.new.cast(hash['_destroy'])
547
- end
557
+ # Determines if a hash contains a truthy _destroy key.
558
+ def has_destroy_flag?(hash)
559
+ Type::Boolean.new.cast(hash["_destroy"])
560
+ end
548
561
 
549
- # Determines if a new record should be rejected by checking
550
- # has_destroy_flag? or if a <tt>:reject_if</tt> proc exists for this
551
- # association and evaluates to +true+.
552
- def reject_new_record?(association_name, attributes)
553
- will_be_destroyed?(association_name, attributes) || call_reject_if(association_name, attributes)
554
- end
562
+ # Determines if a new record should be rejected by checking
563
+ # has_destroy_flag? or if a <tt>:reject_if</tt> proc exists for this
564
+ # association and evaluates to +true+.
565
+ def reject_new_record?(association_name, attributes)
566
+ will_be_destroyed?(association_name, attributes) || call_reject_if(association_name, attributes)
567
+ end
555
568
 
556
- # Determines if a record with the particular +attributes+ should be
557
- # rejected by calling the reject_if Symbol or Proc (if defined).
558
- # The reject_if option is defined by +accepts_nested_attributes_for+.
559
- #
560
- # Returns false if there is a +destroy_flag+ on the attributes.
561
- def call_reject_if(association_name, attributes)
562
- return false if will_be_destroyed?(association_name, attributes)
569
+ # Determines if a record with the particular +attributes+ should be
570
+ # rejected by calling the reject_if Symbol or Proc (if defined).
571
+ # The reject_if option is defined by +accepts_nested_attributes_for+.
572
+ #
573
+ # Returns false if there is a +destroy_flag+ on the attributes.
574
+ def call_reject_if(association_name, attributes)
575
+ return false if will_be_destroyed?(association_name, attributes)
563
576
 
564
- case callback = self.nested_attributes_options[association_name][:reject_if]
565
- when Symbol
566
- method(callback).arity == 0 ? send(callback) : send(callback, attributes)
567
- when Proc
568
- callback.call(attributes)
577
+ case callback = nested_attributes_options[association_name][:reject_if]
578
+ when Symbol
579
+ method(callback).arity == 0 ? send(callback) : send(callback, attributes)
580
+ when Proc
581
+ callback.call(attributes)
582
+ end
569
583
  end
570
- end
571
584
 
572
- # Only take into account the destroy flag if <tt>:allow_destroy</tt> is true
573
- def will_be_destroyed?(association_name, attributes)
574
- allow_destroy?(association_name) && has_destroy_flag?(attributes)
575
- end
585
+ # Only take into account the destroy flag if <tt>:allow_destroy</tt> is true
586
+ def will_be_destroyed?(association_name, attributes)
587
+ allow_destroy?(association_name) && has_destroy_flag?(attributes)
588
+ end
576
589
 
577
- def allow_destroy?(association_name)
578
- self.nested_attributes_options[association_name][:allow_destroy]
579
- end
590
+ def allow_destroy?(association_name)
591
+ nested_attributes_options[association_name][:allow_destroy]
592
+ end
580
593
 
581
- def raise_nested_attributes_record_not_found!(association_name, record_id)
582
- model = self.class._reflect_on_association(association_name).klass.name
583
- raise RecordNotFound.new("Couldn't find #{model} with ID=#{record_id} for #{self.class.name} with ID=#{id}",
584
- model, 'id', record_id)
585
- end
594
+ def raise_nested_attributes_record_not_found!(association_name, record_id)
595
+ model = self.class._reflect_on_association(association_name).klass.name
596
+ raise RecordNotFound.new("Couldn't find #{model} with ID=#{record_id} for #{self.class.name} with ID=#{id}",
597
+ model, "id", record_id)
598
+ end
586
599
  end
587
600
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record No Touching
3
5
  module NoTouching
4
6
  extend ActiveSupport::Concern
5
7
 
6
8
  module ClassMethods
7
- # Lets you selectively disable calls to `touch` for the
9
+ # Lets you selectively disable calls to +touch+ for the
8
10
  # duration of a block.
9
11
  #
10
12
  # ==== Examples
@@ -41,6 +43,13 @@ module ActiveRecord
41
43
  end
42
44
  end
43
45
 
46
+ # Returns +true+ if the class has +no_touching+ set, +false+ otherwise.
47
+ #
48
+ # Project.no_touching do
49
+ # Project.first.no_touching? # true
50
+ # Message.first.no_touching? # false
51
+ # end
52
+ #
44
53
  def no_touching?
45
54
  NoTouching.applied_to?(self.class)
46
55
  end
@@ -1,14 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module NullRelation # :nodoc:
3
- def exec_queries
4
- @records = [].freeze
5
- end
6
-
7
5
  def pluck(*column_names)
8
6
  []
9
7
  end
10
8
 
11
- def delete_all(_conditions = nil)
9
+ def delete_all
12
10
  0
13
11
  end
14
12
 
@@ -20,10 +18,6 @@ module ActiveRecord
20
18
  0
21
19
  end
22
20
 
23
- def size
24
- calculate :size, nil
25
- end
26
-
27
21
  def empty?
28
22
  true
29
23
  end
@@ -48,33 +42,12 @@ module ActiveRecord
48
42
  ""
49
43
  end
50
44
 
51
- def count(*)
52
- calculate :count, nil
53
- end
54
-
55
- def sum(*)
56
- calculate :sum, nil
57
- end
58
-
59
- def average(*)
60
- calculate :average, nil
61
- end
62
-
63
- def minimum(*)
64
- calculate :minimum, nil
65
- end
66
-
67
- def maximum(*)
68
- calculate :maximum, nil
69
- end
70
-
71
45
  def calculate(operation, _column_name)
72
- if [:count, :sum, :size].include? operation
46
+ case operation
47
+ when :count, :sum
73
48
  group_values.any? ? Hash.new : 0
74
- elsif [:average, :minimum, :maximum].include?(operation) && group_values.any?
75
- Hash.new
76
- else
77
- nil
49
+ when :average, :minimum, :maximum
50
+ group_values.any? ? Hash.new : nil
78
51
  end
79
52
  end
80
53
 
@@ -85,5 +58,11 @@ module ActiveRecord
85
58
  def or(other)
86
59
  other.spawn
87
60
  end
61
+
62
+ private
63
+
64
+ def exec_queries
65
+ @records = [].freeze
66
+ end
88
67
  end
89
68
  end