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,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class LogSubscriber < ActiveSupport::LogSubscriber
3
5
  IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN"]
4
6
 
7
+ class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
8
+
5
9
  def self.runtime=(value)
6
10
  ActiveRecord::RuntimeRegistry.sql_runtime = value
7
11
  end
@@ -15,11 +19,6 @@ module ActiveRecord
15
19
  rt
16
20
  end
17
21
 
18
- def initialize
19
- super
20
- @odd = false
21
- end
22
-
23
22
  def sql(event)
24
23
  self.class.runtime += event.duration
25
24
  return unless logger.debug?
@@ -29,11 +28,12 @@ module ActiveRecord
29
28
  return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
30
29
 
31
30
  name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
31
+ name = "CACHE #{name}" if payload[:cached]
32
32
  sql = payload[:sql]
33
33
  binds = nil
34
34
 
35
35
  unless (payload[:binds] || []).empty?
36
- casted_params = type_casted_binds(payload[:binds], payload[:type_casted_binds])
36
+ casted_params = type_casted_binds(payload[:type_casted_binds])
37
37
  binds = " " + payload[:binds].zip(casted_params).map { |attr, value|
38
38
  render_bind(attr, value)
39
39
  }.inspect
@@ -46,31 +46,30 @@ module ActiveRecord
46
46
  end
47
47
 
48
48
  private
49
+ def type_casted_binds(casted_binds)
50
+ casted_binds.respond_to?(:call) ? casted_binds.call : casted_binds
51
+ end
49
52
 
50
- def type_casted_binds(binds, casted_binds)
51
- casted_binds || ActiveRecord::Base.connection.type_casted_binds(binds)
52
- end
53
+ def render_bind(attr, value)
54
+ if attr.is_a?(Array)
55
+ attr = attr.first
56
+ elsif attr.type.binary? && attr.value
57
+ value = "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
58
+ end
53
59
 
54
- def render_bind(attr, value)
55
- if attr.is_a?(Array)
56
- attr = attr.first
57
- elsif attr.type.binary? && attr.value
58
- value = "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
60
+ [attr && attr.name, value]
59
61
  end
60
62
 
61
- [attr && attr.name, value]
62
- end
63
-
64
- def colorize_payload_name(name, payload_name)
65
- if payload_name.blank? || payload_name == "SQL" # SQL vs Model Load/Exists
66
- color(name, MAGENTA, true)
67
- else
68
- color(name, CYAN, true)
63
+ def colorize_payload_name(name, payload_name)
64
+ if payload_name.blank? || payload_name == "SQL" # SQL vs Model Load/Exists
65
+ color(name, MAGENTA, true)
66
+ else
67
+ color(name, CYAN, true)
68
+ end
69
69
  end
70
- end
71
70
 
72
- def sql_color(sql)
73
- case sql
71
+ def sql_color(sql)
72
+ case sql
74
73
  when /\A\s*rollback/mi
75
74
  RED
76
75
  when /select .*for update/mi, /\A\s*lock/mi
@@ -87,12 +86,32 @@ module ActiveRecord
87
86
  CYAN
88
87
  else
89
88
  MAGENTA
89
+ end
90
90
  end
91
- end
92
91
 
93
- def logger
94
- ActiveRecord::Base.logger
95
- end
92
+ def logger
93
+ ActiveRecord::Base.logger
94
+ end
95
+
96
+ def debug(progname = nil, &block)
97
+ return unless super
98
+
99
+ if ActiveRecord::Base.verbose_query_logs
100
+ log_query_source
101
+ end
102
+ end
103
+
104
+ def log_query_source
105
+ source = extract_query_source_location(caller)
106
+
107
+ if source
108
+ logger.debug(" ↳ #{source}")
109
+ end
110
+ end
111
+
112
+ def extract_query_source_location(locations)
113
+ backtrace_cleaner.clean(locations.lazy).first
114
+ end
96
115
  end
97
116
  end
98
117
 
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Middleware
5
+ class DatabaseSelector
6
+ class Resolver
7
+ # The session class is used by the DatabaseSelector::Resolver to save
8
+ # timestamps of the last write in the session.
9
+ #
10
+ # The last_write is used to determine whether it's safe to read
11
+ # from the replica or the request needs to be sent to the primary.
12
+ class Session # :nodoc:
13
+ def self.call(request)
14
+ new(request.session)
15
+ end
16
+
17
+ # Converts time to a timestamp that represents milliseconds since
18
+ # epoch.
19
+ def self.convert_time_to_timestamp(time)
20
+ time.to_i * 1000 + time.usec / 1000
21
+ end
22
+
23
+ # Converts milliseconds since epoch timestamp into a time object.
24
+ def self.convert_timestamp_to_time(timestamp)
25
+ timestamp ? Time.at(timestamp / 1000, (timestamp % 1000) * 1000) : Time.at(0)
26
+ end
27
+
28
+ def initialize(session)
29
+ @session = session
30
+ end
31
+
32
+ attr_reader :session
33
+
34
+ def last_write_timestamp
35
+ self.class.convert_timestamp_to_time(session[:last_write])
36
+ end
37
+
38
+ def update_last_write_timestamp
39
+ session[:last_write] = self.class.convert_time_to_timestamp(Time.now)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/middleware/database_selector/resolver/session"
4
+
5
+ module ActiveRecord
6
+ module Middleware
7
+ class DatabaseSelector
8
+ # The Resolver class is used by the DatabaseSelector middleware to
9
+ # determine which database the request should use.
10
+ #
11
+ # To change the behavior of the Resolver class in your application,
12
+ # create a custom resolver class that inherits from
13
+ # DatabaseSelector::Resolver and implements the methods that need to
14
+ # be changed.
15
+ #
16
+ # By default the Resolver class will send read traffic to the replica
17
+ # if it's been 2 seconds since the last write.
18
+ class Resolver # :nodoc:
19
+ SEND_TO_REPLICA_DELAY = 2.seconds
20
+
21
+ def self.call(context, options = {})
22
+ new(context, options)
23
+ end
24
+
25
+ def initialize(context, options = {})
26
+ @context = context
27
+ @options = options
28
+ @delay = @options && @options[:delay] ? @options[:delay] : SEND_TO_REPLICA_DELAY
29
+ @instrumenter = ActiveSupport::Notifications.instrumenter
30
+ end
31
+
32
+ attr_reader :context, :delay, :instrumenter
33
+
34
+ def read(&blk)
35
+ if read_from_primary?
36
+ read_from_primary(&blk)
37
+ else
38
+ read_from_replica(&blk)
39
+ end
40
+ end
41
+
42
+ def write(&blk)
43
+ write_to_primary(&blk)
44
+ end
45
+
46
+ private
47
+
48
+ def read_from_primary(&blk)
49
+ ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role, prevent_writes: true) do
50
+ instrumenter.instrument("database_selector.active_record.read_from_primary") do
51
+ yield
52
+ end
53
+ end
54
+ end
55
+
56
+ def read_from_replica(&blk)
57
+ ActiveRecord::Base.connected_to(role: ActiveRecord::Base.reading_role) do
58
+ instrumenter.instrument("database_selector.active_record.read_from_replica") do
59
+ yield
60
+ end
61
+ end
62
+ end
63
+
64
+ def write_to_primary(&blk)
65
+ ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role, prevent_writes: false) do
66
+ instrumenter.instrument("database_selector.active_record.wrote_to_primary") do
67
+ yield
68
+ ensure
69
+ context.update_last_write_timestamp
70
+ end
71
+ end
72
+ end
73
+
74
+ def read_from_primary?
75
+ !time_since_last_write_ok?
76
+ end
77
+
78
+ def send_to_replica_delay
79
+ delay
80
+ end
81
+
82
+ def time_since_last_write_ok?
83
+ Time.now - context.last_write_timestamp >= send_to_replica_delay
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/middleware/database_selector/resolver"
4
+
5
+ module ActiveRecord
6
+ module Middleware
7
+ # The DatabaseSelector Middleware provides a framework for automatically
8
+ # swapping from the primary to the replica database connection. Rails
9
+ # provides a basic framework to determine when to swap and allows for
10
+ # applications to write custom strategy classes to override the default
11
+ # behavior.
12
+ #
13
+ # The resolver class defines when the application should switch (i.e. read
14
+ # from the primary if a write occurred less than 2 seconds ago) and a
15
+ # resolver context class that sets a value that helps the resolver class
16
+ # decide when to switch.
17
+ #
18
+ # Rails default middleware uses the request's session to set a timestamp
19
+ # that informs the application when to read from a primary or read from a
20
+ # replica.
21
+ #
22
+ # To use the DatabaseSelector in your application with default settings add
23
+ # the following options to your environment config:
24
+ #
25
+ # config.active_record.database_selector = { delay: 2.seconds }
26
+ # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
27
+ # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
28
+ #
29
+ # New applications will include these lines commented out in the production.rb.
30
+ #
31
+ # The default behavior can be changed by setting the config options to a
32
+ # custom class:
33
+ #
34
+ # config.active_record.database_selector = { delay: 2.seconds }
35
+ # config.active_record.database_resolver = MyResolver
36
+ # config.active_record.database_resolver_context = MyResolver::MySession
37
+ class DatabaseSelector
38
+ def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
39
+ @app = app
40
+ @resolver_klass = resolver_klass || Resolver
41
+ @context_klass = context_klass || Resolver::Session
42
+ @options = options
43
+ end
44
+
45
+ attr_reader :resolver_klass, :context_klass, :options
46
+
47
+ # Middleware that determines which database connection to use in a multiple
48
+ # database application.
49
+ def call(env)
50
+ request = ActionDispatch::Request.new(env)
51
+
52
+ select_database(request) do
53
+ @app.call(env)
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def select_database(request, &blk)
60
+ context = context_klass.call(request)
61
+ resolver = resolver_klass.call(context, options)
62
+
63
+ if reading_request?(request)
64
+ resolver.read(&blk)
65
+ else
66
+ resolver.write(&blk)
67
+ end
68
+ end
69
+
70
+ def reading_request?(request)
71
+ request.get? || request.head?
72
+ end
73
+ end
74
+ end
75
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class Migration
3
5
  # <tt>ActiveRecord::Migration::CommandRecorder</tt> records commands done during
@@ -12,6 +14,8 @@ module ActiveRecord
12
14
  # * change_column
13
15
  # * change_column_default (must supply a :from and :to option)
14
16
  # * change_column_null
17
+ # * change_column_comment (must supply a :from and :to option)
18
+ # * change_table_comment (must supply a :from and :to option)
15
19
  # * create_join_table
16
20
  # * create_table
17
21
  # * disable_extension
@@ -33,7 +37,8 @@ module ActiveRecord
33
37
  :change_column_default, :add_reference, :remove_reference, :transaction,
34
38
  :drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension,
35
39
  :change_column, :execute, :remove_columns, :change_column_null,
36
- :add_foreign_key, :remove_foreign_key
40
+ :add_foreign_key, :remove_foreign_key,
41
+ :change_column_comment, :change_table_comment
37
42
  ]
38
43
  include JoinTable
39
44
 
@@ -83,7 +88,7 @@ module ActiveRecord
83
88
  # invert the +command+.
84
89
  def inverse_of(command, args, &block)
85
90
  method = :"invert_#{command}"
86
- raise IrreversibleMigration, <<-MSG.strip_heredoc unless respond_to?(method, true)
91
+ raise IrreversibleMigration, <<~MSG unless respond_to?(method, true)
87
92
  This migration uses #{command}, which is not automatically reversible.
88
93
  To make the migration reversible you can either:
89
94
  1. Define #up and #down methods in place of the #change method.
@@ -92,10 +97,6 @@ module ActiveRecord
92
97
  send(method, args, &block)
93
98
  end
94
99
 
95
- def respond_to?(*args) # :nodoc:
96
- super || delegate.respond_to?(*args)
97
- end
98
-
99
100
  ReversibleAndIrreversibleMethods.each do |method|
100
101
  class_eval <<-EOV, __FILE__, __LINE__ + 1
101
102
  def #{method}(*args, &block) # def create_table(*args, &block)
@@ -110,129 +111,174 @@ module ActiveRecord
110
111
  yield delegate.update_table_definition(table_name, self)
111
112
  end
112
113
 
114
+ def replay(migration)
115
+ commands.each do |cmd, args, block|
116
+ migration.send(cmd, *args, &block)
117
+ end
118
+ end
119
+
113
120
  private
114
121
 
115
- module StraightReversions
116
- private
117
- { transaction: :transaction,
118
- execute_block: :execute_block,
119
- create_table: :drop_table,
120
- create_join_table: :drop_join_table,
121
- add_column: :remove_column,
122
- add_timestamps: :remove_timestamps,
123
- add_reference: :remove_reference,
124
- enable_extension: :disable_extension
125
- }.each do |cmd, inv|
126
- [[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
127
- class_eval <<-EOV, __FILE__, __LINE__ + 1
128
- def invert_#{method}(args, &block) # def invert_create_table(args, &block)
129
- [:#{inverse}, args, block] # [:drop_table, args, block]
130
- end # end
131
- EOV
122
+ module StraightReversions # :nodoc:
123
+ private
124
+ {
125
+ execute_block: :execute_block,
126
+ create_table: :drop_table,
127
+ create_join_table: :drop_join_table,
128
+ add_column: :remove_column,
129
+ add_timestamps: :remove_timestamps,
130
+ add_reference: :remove_reference,
131
+ enable_extension: :disable_extension
132
+ }.each do |cmd, inv|
133
+ [[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
134
+ class_eval <<-EOV, __FILE__, __LINE__ + 1
135
+ def invert_#{method}(args, &block) # def invert_create_table(args, &block)
136
+ [:#{inverse}, args, block] # [:drop_table, args, block]
137
+ end # end
138
+ EOV
139
+ end
140
+ end
141
+ end
142
+
143
+ include StraightReversions
144
+
145
+ def invert_transaction(args)
146
+ sub_recorder = CommandRecorder.new(delegate)
147
+ sub_recorder.revert { yield }
148
+
149
+ invertions_proc = proc {
150
+ sub_recorder.replay(self)
151
+ }
152
+
153
+ [:transaction, args, invertions_proc]
154
+ end
155
+
156
+ def invert_drop_table(args, &block)
157
+ if args.size == 1 && block == nil
158
+ raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
132
159
  end
160
+ super
133
161
  end
134
- end
135
162
 
136
- include StraightReversions
163
+ def invert_rename_table(args)
164
+ [:rename_table, args.reverse]
165
+ end
137
166
 
138
- def invert_drop_table(args, &block)
139
- if args.size == 1 && block == nil
140
- raise ActiveRecord::IrreversibleMigration, "To avoid mistakes, drop_table is only reversible if given options or a block (can be empty)."
167
+ def invert_remove_column(args)
168
+ raise ActiveRecord::IrreversibleMigration, "remove_column is only reversible if given a type." if args.size <= 2
169
+ super
141
170
  end
142
- super
143
- end
144
171
 
145
- def invert_rename_table(args)
146
- [:rename_table, args.reverse]
147
- end
172
+ def invert_rename_index(args)
173
+ [:rename_index, [args.first] + args.last(2).reverse]
174
+ end
148
175
 
149
- def invert_remove_column(args)
150
- raise ActiveRecord::IrreversibleMigration, "remove_column is only reversible if given a type." if args.size <= 2
151
- super
152
- end
176
+ def invert_rename_column(args)
177
+ [:rename_column, [args.first] + args.last(2).reverse]
178
+ end
153
179
 
154
- def invert_rename_index(args)
155
- [:rename_index, [args.first] + args.last(2).reverse]
156
- end
180
+ def invert_add_index(args)
181
+ table, columns, options = *args
182
+ options ||= {}
157
183
 
158
- def invert_rename_column(args)
159
- [:rename_column, [args.first] + args.last(2).reverse]
160
- end
184
+ options_hash = options.slice(:name, :algorithm)
185
+ options_hash[:column] = columns if !options_hash[:name]
186
+
187
+ [:remove_index, [table, options_hash]]
188
+ end
161
189
 
162
- def invert_add_index(args)
163
- table, columns, options = *args
164
- options ||= {}
190
+ def invert_remove_index(args)
191
+ table, options_or_column = *args
192
+ if (options = options_or_column).is_a?(Hash)
193
+ unless options[:column]
194
+ raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
195
+ end
196
+ options = options.dup
197
+ [:add_index, [table, options.delete(:column), options]]
198
+ elsif (column = options_or_column).present?
199
+ [:add_index, [table, column]]
200
+ end
201
+ end
165
202
 
166
- index_name = options[:name]
167
- options_hash = index_name ? { name: index_name } : { column: columns }
203
+ alias :invert_add_belongs_to :invert_add_reference
204
+ alias :invert_remove_belongs_to :invert_remove_reference
168
205
 
169
- [:remove_index, [table, options_hash]]
170
- end
206
+ def invert_change_column_default(args)
207
+ table, column, options = *args
171
208
 
172
- def invert_remove_index(args)
173
- table, options_or_column = *args
174
- if (options = options_or_column).is_a?(Hash)
175
- unless options[:column]
176
- raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
209
+ unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
210
+ raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
177
211
  end
178
- options = options.dup
179
- [:add_index, [table, options.delete(:column), options]]
180
- elsif (column = options_or_column).present?
181
- [:add_index, [table, column]]
212
+
213
+ [:change_column_default, [table, column, from: options[:to], to: options[:from]]]
182
214
  end
183
- end
184
215
 
185
- alias :invert_add_belongs_to :invert_add_reference
186
- alias :invert_remove_belongs_to :invert_remove_reference
216
+ def invert_change_column_null(args)
217
+ args[2] = !args[2]
218
+ [:change_column_null, args]
219
+ end
187
220
 
188
- def invert_change_column_default(args)
189
- table, column, options = *args
221
+ def invert_add_foreign_key(args)
222
+ from_table, to_table, add_options = args
223
+ add_options ||= {}
190
224
 
191
- unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
192
- raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
225
+ if add_options[:name]
226
+ options = { name: add_options[:name] }
227
+ elsif add_options[:column]
228
+ options = { column: add_options[:column] }
229
+ else
230
+ options = to_table
231
+ end
232
+
233
+ [:remove_foreign_key, [from_table, options]]
193
234
  end
194
235
 
195
- [:change_column_default, [table, column, from: options[:to], to: options[:from]]]
196
- end
236
+ def invert_remove_foreign_key(args)
237
+ options = args.extract_options!
238
+ from_table, to_table = args
197
239
 
198
- def invert_change_column_null(args)
199
- args[2] = !args[2]
200
- [:change_column_null, args]
201
- end
240
+ to_table ||= options.delete(:to_table)
202
241
 
203
- def invert_add_foreign_key(args)
204
- from_table, to_table, add_options = args
205
- add_options ||= {}
242
+ raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil?
206
243
 
207
- if add_options[:name]
208
- options = { name: add_options[:name] }
209
- elsif add_options[:column]
210
- options = { column: add_options[:column] }
211
- else
212
- options = to_table
244
+ reversed_args = [from_table, to_table]
245
+ reversed_args << options unless options.empty?
246
+
247
+ [:add_foreign_key, reversed_args]
213
248
  end
214
249
 
215
- [:remove_foreign_key, [from_table, options]]
216
- end
250
+ def invert_change_column_comment(args)
251
+ table, column, options = *args
217
252
 
218
- def invert_remove_foreign_key(args)
219
- from_table, to_table, remove_options = args
220
- raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil? || to_table.is_a?(Hash)
253
+ unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
254
+ raise ActiveRecord::IrreversibleMigration, "change_column_comment is only reversible if given a :from and :to option."
255
+ end
221
256
 
222
- reversed_args = [from_table, to_table]
223
- reversed_args << remove_options if remove_options
257
+ [:change_column_comment, [table, column, from: options[:to], to: options[:from]]]
258
+ end
224
259
 
225
- [:add_foreign_key, reversed_args]
226
- end
260
+ def invert_change_table_comment(args)
261
+ table, options = *args
227
262
 
228
- # Forwards any missing method call to the \target.
229
- def method_missing(method, *args, &block)
230
- if @delegate.respond_to?(method)
231
- @delegate.send(method, *args, &block)
232
- else
233
- super
263
+ unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
264
+ raise ActiveRecord::IrreversibleMigration, "change_table_comment is only reversible if given a :from and :to option."
265
+ end
266
+
267
+ [:change_table_comment, [table, from: options[:to], to: options[:from]]]
268
+ end
269
+
270
+ def respond_to_missing?(method, _)
271
+ super || delegate.respond_to?(method)
272
+ end
273
+
274
+ # Forwards any missing method call to the \target.
275
+ def method_missing(method, *args, &block)
276
+ if delegate.respond_to?(method)
277
+ delegate.public_send(method, *args, &block)
278
+ else
279
+ super
280
+ end
234
281
  end
235
- end
236
282
  end
237
283
  end
238
284
  end