activerecord 4.2.0 → 6.1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  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 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,6 +1,4 @@
1
- require 'active_support/core_ext/array'
2
- require 'active_support/core_ext/hash/except'
3
- require 'active_support/core_ext/kernel/singleton_class'
1
+ # frozen_string_literal: true
4
2
 
5
3
  module ActiveRecord
6
4
  # = Active Record \Named \Scopes
@@ -9,7 +7,7 @@ module ActiveRecord
9
7
  extend ActiveSupport::Concern
10
8
 
11
9
  module ClassMethods
12
- # Returns an <tt>ActiveRecord::Relation</tt> scope object.
10
+ # Returns an ActiveRecord::Relation scope object.
13
11
  #
14
12
  # posts = Post.all
15
13
  # posts.size # Fires "select count(*) from posts" and returns the count
@@ -20,32 +18,49 @@ module ActiveRecord
20
18
  # fruits = fruits.limit(10) if limited?
21
19
  #
22
20
  # You can define a scope that applies to all finders using
23
- # <tt>ActiveRecord::Base.default_scope</tt>.
21
+ # {default_scope}[rdoc-ref:Scoping::Default::ClassMethods#default_scope].
24
22
  def all
25
- if current_scope
26
- current_scope.clone
23
+ scope = current_scope
24
+
25
+ if scope
26
+ if self == scope.klass
27
+ scope.clone
28
+ else
29
+ relation.merge!(scope)
30
+ end
27
31
  else
28
32
  default_scoped
29
33
  end
30
34
  end
31
35
 
32
- def default_scoped # :nodoc:
33
- relation.merge(build_default_scope)
36
+ def scope_for_association(scope = relation) # :nodoc:
37
+ if current_scope&.empty_scope?
38
+ scope
39
+ else
40
+ default_scoped(scope)
41
+ end
34
42
  end
35
43
 
36
- # Collects attributes from scopes that should be applied when creating
37
- # an AR instance for the particular class this is called on.
38
- def scope_attributes # :nodoc:
39
- all.scope_for_create
44
+ # Returns a scope for the model with default scopes.
45
+ def default_scoped(scope = relation)
46
+ build_default_scope(scope) || scope
40
47
  end
41
48
 
42
- # Are there default attributes associated with this scope?
43
- def scope_attributes? # :nodoc:
44
- current_scope || default_scopes.any?
49
+ def default_extensions # :nodoc:
50
+ if scope = scope_for_association || build_default_scope
51
+ scope.extensions
52
+ else
53
+ []
54
+ end
45
55
  end
46
56
 
47
- # Adds a class method for retrieving and querying objects. A \scope
48
- # represents a narrowing of a database query, such as
57
+ # Adds a class method for retrieving and querying objects.
58
+ # The method is intended to return an ActiveRecord::Relation
59
+ # object, which is composable with other scopes.
60
+ # If it returns +nil+ or +false+, an
61
+ # {all}[rdoc-ref:Scoping::Named::ClassMethods#all] scope is returned instead.
62
+ #
63
+ # A \scope represents a narrowing of a database query, such as
49
64
  # <tt>where(color: :red).select('shirts.*').includes(:washing_instructions)</tt>.
50
65
  #
51
66
  # class Shirt < ActiveRecord::Base
@@ -53,14 +68,10 @@ module ActiveRecord
53
68
  # scope :dry_clean_only, -> { joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true) }
54
69
  # end
55
70
  #
56
- # The above calls to +scope+ define class methods <tt>Shirt.red</tt> and
71
+ # The above calls to #scope define class methods <tt>Shirt.red</tt> and
57
72
  # <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>, in effect,
58
73
  # represents the query <tt>Shirt.where(color: 'red')</tt>.
59
74
  #
60
- # You should always pass a callable object to the scopes defined
61
- # with +scope+. This ensures that the scope is re-evaluated each
62
- # time it is called.
63
- #
64
75
  # Note that this is simply 'syntactic sugar' for defining an actual
65
76
  # class method:
66
77
  #
@@ -71,14 +82,15 @@ module ActiveRecord
71
82
  # end
72
83
  #
73
84
  # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by
74
- # <tt>Shirt.red</tt> is not an Array; it resembles the association object
75
- # constructed by a +has_many+ declaration. For instance, you can invoke
76
- # <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
85
+ # <tt>Shirt.red</tt> is not an Array but an ActiveRecord::Relation,
86
+ # which is composable with other scopes; it resembles the association object
87
+ # constructed by a {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
88
+ # declaration. For instance, you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
77
89
  # <tt>Shirt.red.where(size: 'small')</tt>. Also, just as with the
78
90
  # association objects, named \scopes act like an Array, implementing
79
91
  # Enumerable; <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>,
80
92
  # and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if
81
- # <tt>Shirt.red</tt> really was an Array.
93
+ # <tt>Shirt.red</tt> really was an array.
82
94
  #
83
95
  # These named \scopes are composable. For instance,
84
96
  # <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are
@@ -89,7 +101,8 @@ module ActiveRecord
89
101
  #
90
102
  # All scopes are available as class methods on the ActiveRecord::Base
91
103
  # descendant upon which the \scopes were defined. But they are also
92
- # available to +has_many+ associations. If,
104
+ # available to {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
105
+ # associations. If,
93
106
  #
94
107
  # class Person < ActiveRecord::Base
95
108
  # has_many :shirts
@@ -98,8 +111,8 @@ module ActiveRecord
98
111
  # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of
99
112
  # Elton's red, dry clean only shirts.
100
113
  #
101
- # \Named scopes can also have extensions, just as with +has_many+
102
- # declarations:
114
+ # \Named scopes can also have extensions, just as with
115
+ # {has_many}[rdoc-ref:Associations::ClassMethods#has_many] declarations:
103
116
  #
104
117
  # class Shirt < ActiveRecord::Base
105
118
  # scope :red, -> { where(color: 'red') } do
@@ -140,7 +153,7 @@ module ActiveRecord
140
153
  # Article.featured.titles
141
154
  def scope(name, body, &block)
142
155
  unless body.respond_to?(:call)
143
- raise ArgumentError, 'The scope body needs to be callable.'
156
+ raise ArgumentError, "The scope body needs to be callable."
144
157
  end
145
158
 
146
159
  if dangerous_class_method?(name)
@@ -149,15 +162,44 @@ module ActiveRecord
149
162
  "a class method with the same name."
150
163
  end
151
164
 
152
- extension = Module.new(&block) if block
165
+ if method_defined_within?(name, Relation)
166
+ raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
167
+ "on the model \"#{self.name}\", but ActiveRecord::Relation already defined " \
168
+ "an instance method with the same name."
169
+ end
153
170
 
154
- singleton_class.send(:define_method, name) do |*args|
155
- scope = all.scoping { body.call(*args) }
156
- scope = scope.extending(extension) if extension
171
+ valid_scope_name?(name)
172
+ extension = Module.new(&block) if block
157
173
 
158
- scope || all
174
+ if body.respond_to?(:to_proc)
175
+ singleton_class.define_method(name) do |*args|
176
+ scope = all._exec_scope(*args, &body)
177
+ scope = scope.extending(extension) if extension
178
+ scope
179
+ end
180
+ else
181
+ singleton_class.define_method(name) do |*args|
182
+ scope = body.call(*args) || all
183
+ scope = scope.extending(extension) if extension
184
+ scope
185
+ end
159
186
  end
187
+ singleton_class.send(:ruby2_keywords, name) if respond_to?(:ruby2_keywords, true)
188
+
189
+ generate_relation_method(name)
160
190
  end
191
+
192
+ private
193
+ def singleton_method_added(name)
194
+ generate_relation_method(name) if Kernel.respond_to?(name) && !ActiveRecord::Relation.method_defined?(name)
195
+ end
196
+
197
+ def valid_scope_name?(name)
198
+ if respond_to?(name, true) && logger
199
+ logger.warn "Creating scope :#{name}. " \
200
+ "Overwriting existing method #{self.name}.#{name}."
201
+ end
202
+ end
161
203
  end
162
204
  end
163
205
  end
@@ -1,4 +1,6 @@
1
- require 'active_support/per_thread_registry'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/per_thread_registry"
2
4
 
3
5
  module ActiveRecord
4
6
  module Scoping
@@ -9,25 +11,35 @@ module ActiveRecord
9
11
  include Named
10
12
  end
11
13
 
12
- module ClassMethods
13
- def current_scope #:nodoc:
14
- ScopeRegistry.value_for(:current_scope, base_class.to_s)
14
+ module ClassMethods # :nodoc:
15
+ # Collects attributes from scopes that should be applied when creating
16
+ # an AR instance for the particular class this is called on.
17
+ def scope_attributes
18
+ all.scope_for_create
19
+ end
20
+
21
+ # Are there attributes associated with this scope?
22
+ def scope_attributes?
23
+ current_scope
24
+ end
25
+
26
+ def current_scope(skip_inherited_scope = false)
27
+ ScopeRegistry.value_for(:current_scope, self, skip_inherited_scope)
15
28
  end
16
29
 
17
- def current_scope=(scope) #:nodoc:
18
- ScopeRegistry.set_value_for(:current_scope, base_class.to_s, scope)
30
+ def current_scope=(scope)
31
+ ScopeRegistry.set_value_for(:current_scope, self, scope)
19
32
  end
20
33
  end
21
34
 
22
- def populate_with_current_scope_attributes
35
+ def populate_with_current_scope_attributes # :nodoc:
23
36
  return unless self.class.scope_attributes?
24
37
 
25
- self.class.scope_attributes.each do |att,value|
26
- send("#{att}=", value) if respond_to?("#{att}=")
27
- end
38
+ attributes = self.class.scope_attributes
39
+ _assign_attributes(attributes) if attributes.any?
28
40
  end
29
41
 
30
- def initialize_internals_callback
42
+ def initialize_internals_callback # :nodoc:
31
43
  super
32
44
  populate_with_current_scope_attributes
33
45
  end
@@ -42,18 +54,18 @@ module ActiveRecord
42
54
  # following code:
43
55
  #
44
56
  # registry = ActiveRecord::Scoping::ScopeRegistry
45
- # registry.set_value_for(:current_scope, "Board", some_new_scope)
57
+ # registry.set_value_for(:current_scope, Board, some_new_scope)
46
58
  #
47
59
  # Now when you run:
48
60
  #
49
- # registry.value_for(:current_scope, "Board")
61
+ # registry.value_for(:current_scope, Board)
50
62
  #
51
- # You will obtain whatever was defined in +some_new_scope+. The +value_for+
52
- # and +set_value_for+ methods are delegated to the current +ScopeRegistry+
63
+ # You will obtain whatever was defined in +some_new_scope+. The #value_for
64
+ # and #set_value_for methods are delegated to the current ScopeRegistry
53
65
  # object, so the above example code can also be called as:
54
66
  #
55
67
  # ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope,
56
- # "Board", some_new_scope)
68
+ # Board, some_new_scope)
57
69
  class ScopeRegistry # :nodoc:
58
70
  extend ActiveSupport::PerThreadRegistry
59
71
 
@@ -63,25 +75,31 @@ module ActiveRecord
63
75
  @registry = Hash.new { |hash, key| hash[key] = {} }
64
76
  end
65
77
 
66
- # Obtains the value for a given +scope_name+ and +variable_name+.
67
- def value_for(scope_type, variable_name)
78
+ # Obtains the value for a given +scope_type+ and +model+.
79
+ def value_for(scope_type, model, skip_inherited_scope = false)
68
80
  raise_invalid_scope_type!(scope_type)
69
- @registry[scope_type][variable_name]
81
+ return @registry[scope_type][model.name] if skip_inherited_scope
82
+ klass = model
83
+ base = model.base_class
84
+ while klass <= base
85
+ value = @registry[scope_type][klass.name]
86
+ return value if value
87
+ klass = klass.superclass
88
+ end
70
89
  end
71
90
 
72
- # Sets the +value+ for a given +scope_type+ and +variable_name+.
73
- def set_value_for(scope_type, variable_name, value)
91
+ # Sets the +value+ for a given +scope_type+ and +model+.
92
+ def set_value_for(scope_type, model, value)
74
93
  raise_invalid_scope_type!(scope_type)
75
- @registry[scope_type][variable_name] = value
94
+ @registry[scope_type][model.name] = value
76
95
  end
77
96
 
78
97
  private
79
-
80
- def raise_invalid_scope_type!(scope_type)
81
- if !VALID_SCOPE_TYPES.include?(scope_type)
82
- raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
98
+ def raise_invalid_scope_type!(scope_type)
99
+ if !VALID_SCOPE_TYPES.include?(scope_type)
100
+ raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
101
+ end
83
102
  end
84
- end
85
103
  end
86
104
  end
87
105
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module SecureToken
5
+ class MinimumLengthError < StandardError; end
6
+
7
+ MINIMUM_TOKEN_LENGTH = 24
8
+
9
+ extend ActiveSupport::Concern
10
+
11
+ module ClassMethods
12
+ # Example using #has_secure_token
13
+ #
14
+ # # Schema: User(token:string, auth_token:string)
15
+ # class User < ActiveRecord::Base
16
+ # has_secure_token
17
+ # has_secure_token :auth_token, length: 36
18
+ # end
19
+ #
20
+ # user = User.new
21
+ # user.save
22
+ # user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
23
+ # user.auth_token # => "tU9bLuZseefXQ4yQxQo8wjtBvsAfPc78os6R"
24
+ # user.regenerate_token # => true
25
+ # user.regenerate_auth_token # => true
26
+ #
27
+ # <tt>SecureRandom::base58</tt> is used to generate at minimum a 24-character unique token, so collisions are highly unlikely.
28
+ #
29
+ # Note that it's still possible to generate a race condition in the database in the same way that
30
+ # {validates_uniqueness_of}[rdoc-ref:Validations::ClassMethods#validates_uniqueness_of] can.
31
+ # You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
32
+ def has_secure_token(attribute = :token, length: MINIMUM_TOKEN_LENGTH)
33
+ if length < MINIMUM_TOKEN_LENGTH
34
+ raise MinimumLengthError, "Token requires a minimum length of #{MINIMUM_TOKEN_LENGTH} characters."
35
+ end
36
+
37
+ # Load securerandom only when has_secure_token is used.
38
+ require "active_support/core_ext/securerandom"
39
+ define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token(length: length) }
40
+ before_create { send("#{attribute}=", self.class.generate_unique_secure_token(length: length)) unless send("#{attribute}?") }
41
+ end
42
+
43
+ def generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH)
44
+ SecureRandom.base58(length)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord #:nodoc:
2
- # = Active Record Serialization
4
+ # = Active Record \Serialization
3
5
  module Serialization
4
6
  extend ActiveSupport::Concern
5
7
  include ActiveModel::Serializers::JSON
@@ -9,14 +11,14 @@ module ActiveRecord #:nodoc:
9
11
  end
10
12
 
11
13
  def serializable_hash(options = nil)
12
- options = options.try(:clone) || {}
14
+ if self.class._has_attribute?(self.class.inheritance_column)
15
+ options = options ? options.dup : {}
13
16
 
14
- options[:except] = Array(options[:except]).map { |n| n.to_s }
15
- options[:except] |= Array(self.class.inheritance_column)
17
+ options[:except] = Array(options[:except]).map(&:to_s)
18
+ options[:except] |= Array(self.class.inheritance_column)
19
+ end
16
20
 
17
21
  super(options)
18
22
  end
19
23
  end
20
24
  end
21
-
22
- require 'active_record/serializers/xml_serializer'
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # = Active Record Signed Id
5
+ module SignedId
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ ##
10
+ # :singleton-method:
11
+ # Set the secret used for the signed id verifier instance when using Active Record outside of Rails.
12
+ # Within Rails, this is automatically set using the Rails application key generator.
13
+ mattr_accessor :signed_id_verifier_secret, instance_writer: false
14
+ end
15
+
16
+ module ClassMethods
17
+ # Lets you find a record based on a signed id that's safe to put into the world without risk of tampering.
18
+ # This is particularly useful for things like password reset or email verification, where you want
19
+ # the bearer of the signed id to be able to interact with the underlying record, but usually only within
20
+ # a certain time period.
21
+ #
22
+ # You set the time period that the signed id is valid for during generation, using the instance method
23
+ # <tt>signed_id(expires_in: 15.minutes)</tt>. If the time has elapsed before a signed find is attempted,
24
+ # the signed id will no longer be valid, and nil is returned.
25
+ #
26
+ # It's possible to further restrict the use of a signed id with a purpose. This helps when you have a
27
+ # general base model, like a User, which might have signed ids for several things, like password reset
28
+ # or email verification. The purpose that was set during generation must match the purpose set when
29
+ # finding. If there's a mismatch, nil is again returned.
30
+ #
31
+ # ==== Examples
32
+ #
33
+ # signed_id = User.first.signed_id expires_in: 15.minutes, purpose: :password_reset
34
+ #
35
+ # User.find_signed signed_id # => nil, since the purpose does not match
36
+ #
37
+ # travel 16.minutes
38
+ # User.find_signed signed_id, purpose: :password_reset # => nil, since the signed id has expired
39
+ #
40
+ # travel_back
41
+ # User.find_signed signed_id, purpose: :password_reset # => User.first
42
+ def find_signed(signed_id, purpose: nil)
43
+ raise UnknownPrimaryKey.new(self) if primary_key.nil?
44
+
45
+ if id = signed_id_verifier.verified(signed_id, purpose: combine_signed_id_purposes(purpose))
46
+ find_by primary_key => id
47
+ end
48
+ end
49
+
50
+ # Works like +find_signed+, but will raise an +ActiveSupport::MessageVerifier::InvalidSignature+
51
+ # exception if the +signed_id+ has either expired, has a purpose mismatch, is for another record,
52
+ # or has been tampered with. It will also raise an +ActiveRecord::RecordNotFound+ exception if
53
+ # the valid signed id can't find a record.
54
+ #
55
+ # === Examples
56
+ #
57
+ # User.find_signed! "bad data" # => ActiveSupport::MessageVerifier::InvalidSignature
58
+ #
59
+ # signed_id = User.first.signed_id
60
+ # User.first.destroy
61
+ # User.find_signed! signed_id # => ActiveRecord::RecordNotFound
62
+ def find_signed!(signed_id, purpose: nil)
63
+ if id = signed_id_verifier.verify(signed_id, purpose: combine_signed_id_purposes(purpose))
64
+ find(id)
65
+ end
66
+ end
67
+
68
+ # The verifier instance that all signed ids are generated and verified from. By default, it'll be initialized
69
+ # with the class-level +signed_id_verifier_secret+, which within Rails comes from the
70
+ # Rails.application.key_generator. By default, it's SHA256 for the digest and JSON for the serialization.
71
+ def signed_id_verifier
72
+ @signed_id_verifier ||= begin
73
+ secret = signed_id_verifier_secret
74
+ secret = secret.call if secret.respond_to?(:call)
75
+
76
+ if secret.nil?
77
+ raise ArgumentError, "You must set ActiveRecord::Base.signed_id_verifier_secret to use signed ids"
78
+ else
79
+ ActiveSupport::MessageVerifier.new secret, digest: "SHA256", serializer: JSON
80
+ end
81
+ end
82
+ end
83
+
84
+ # Allows you to pass in a custom verifier used for the signed ids. This also allows you to use different
85
+ # verifiers for different classes. This is also helpful if you need to rotate keys, as you can prepare
86
+ # your custom verifier for that in advance. See +ActiveSupport::MessageVerifier+ for details.
87
+ def signed_id_verifier=(verifier)
88
+ @signed_id_verifier = verifier
89
+ end
90
+
91
+ # :nodoc:
92
+ def combine_signed_id_purposes(purpose)
93
+ [ base_class.name.underscore, purpose.to_s ].compact_blank.join("/")
94
+ end
95
+ end
96
+
97
+
98
+ # Returns a signed id that's generated using a preconfigured +ActiveSupport::MessageVerifier+ instance.
99
+ # This signed id is tamper proof, so it's safe to send in an email or otherwise share with the outside world.
100
+ # It can further more be set to expire (the default is not to expire), and scoped down with a specific purpose.
101
+ # If the expiration date has been exceeded before +find_signed+ is called, the id won't find the designated
102
+ # record. If a purpose is set, this too must match.
103
+ #
104
+ # If you accidentally let a signed id out in the wild that you wish to retract sooner than its expiration date
105
+ # (or maybe you forgot to set an expiration date while meaning to!), you can use the purpose to essentially
106
+ # version the signed_id, like so:
107
+ #
108
+ # user.signed_id purpose: :v2
109
+ #
110
+ # And you then change your +find_signed+ calls to require this new purpose. Any old signed ids that were not
111
+ # created with the purpose will no longer find the record.
112
+ def signed_id(expires_in: nil, purpose: nil)
113
+ self.class.signed_id_verifier.generate id, expires_in: expires_in, purpose: self.class.combine_signed_id_purposes(purpose)
114
+ end
115
+ end
116
+ end