activerecord 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 (340) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1086 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +219 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record.rb +195 -0
  8. data/lib/active_record/aggregations.rb +285 -0
  9. data/lib/active_record/association_relation.rb +49 -0
  10. data/lib/active_record/associations.rb +1865 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +340 -0
  13. data/lib/active_record/associations/association_scope.rb +166 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +124 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +36 -0
  16. data/lib/active_record/associations/builder/association.rb +136 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +130 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +72 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +114 -0
  20. data/lib/active_record/associations/builder/has_many.rb +19 -0
  21. data/lib/active_record/associations/builder/has_one.rb +64 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +44 -0
  23. data/lib/active_record/associations/collection_association.rb +498 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1128 -0
  25. data/lib/active_record/associations/foreign_association.rb +20 -0
  26. data/lib/active_record/associations/has_many_association.rb +136 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +220 -0
  28. data/lib/active_record/associations/has_one_association.rb +118 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +262 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +80 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +201 -0
  35. data/lib/active_record/associations/preloader/association.rb +133 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +116 -0
  37. data/lib/active_record/associations/singular_association.rb +59 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +85 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +420 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +81 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +221 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +136 -0
  45. data/lib/active_record/attribute_methods/query.rb +41 -0
  46. data/lib/active_record/attribute_methods/read.rb +47 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +61 -0
  50. data/lib/active_record/attributes.rb +279 -0
  51. data/lib/active_record/autosave_association.rb +512 -0
  52. data/lib/active_record/base.rb +328 -0
  53. data/lib/active_record/callbacks.rb +339 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1175 -0
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +85 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +516 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +155 -0
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +251 -0
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +713 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1475 -0
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +772 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +830 -0
  69. data/lib/active_record/connection_adapters/column.rb +95 -0
  70. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +202 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +146 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +184 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +953 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +141 -0
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +561 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +274 -0
  129. data/lib/active_record/core.rb +603 -0
  130. data/lib/active_record/counter_cache.rb +193 -0
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +122 -0
  137. data/lib/active_record/enum.rb +274 -0
  138. data/lib/active_record/errors.rb +388 -0
  139. data/lib/active_record/explain.rb +50 -0
  140. data/lib/active_record/explain_registry.rb +32 -0
  141. data/lib/active_record/explain_subscriber.rb +34 -0
  142. data/lib/active_record/fixture_set/file.rb +82 -0
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +738 -0
  148. data/lib/active_record/gem_version.rb +17 -0
  149. data/lib/active_record/inheritance.rb +293 -0
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +207 -0
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  154. data/lib/active_record/locale/en.yml +48 -0
  155. data/lib/active_record/locking/optimistic.rb +197 -0
  156. data/lib/active_record/locking/pessimistic.rb +89 -0
  157. data/lib/active_record/log_subscriber.rb +118 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +1397 -0
  162. data/lib/active_record/migration/command_recorder.rb +284 -0
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +17 -0
  165. data/lib/active_record/model_schema.rb +545 -0
  166. data/lib/active_record/nested_attributes.rb +600 -0
  167. data/lib/active_record/no_touching.rb +65 -0
  168. data/lib/active_record/null_relation.rb +68 -0
  169. data/lib/active_record/persistence.rb +967 -0
  170. data/lib/active_record/query_cache.rb +52 -0
  171. data/lib/active_record/querying.rb +82 -0
  172. data/lib/active_record/railtie.rb +263 -0
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +7 -0
  175. data/lib/active_record/railties/controller_runtime.rb +51 -0
  176. data/lib/active_record/railties/databases.rake +527 -0
  177. data/lib/active_record/readonly_attributes.rb +24 -0
  178. data/lib/active_record/reflection.rb +1042 -0
  179. data/lib/active_record/relation.rb +860 -0
  180. data/lib/active_record/relation/batches.rb +290 -0
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +424 -0
  183. data/lib/active_record/relation/delegation.rb +130 -0
  184. data/lib/active_record/relation/finder_methods.rb +561 -0
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +184 -0
  187. data/lib/active_record/relation/predicate_builder.rb +150 -0
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +1371 -0
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +77 -0
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +168 -0
  202. data/lib/active_record/runtime_registry.rb +24 -0
  203. data/lib/active_record/sanitization.rb +214 -0
  204. data/lib/active_record/schema.rb +61 -0
  205. data/lib/active_record/schema_dumper.rb +270 -0
  206. data/lib/active_record/schema_migration.rb +60 -0
  207. data/lib/active_record/scoping.rb +106 -0
  208. data/lib/active_record/scoping/default.rb +151 -0
  209. data/lib/active_record/scoping/named.rb +217 -0
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +22 -0
  212. data/lib/active_record/statement_cache.rb +148 -0
  213. data/lib/active_record/store.rb +290 -0
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +506 -0
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +167 -0
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +493 -0
  225. data/lib/active_record/translation.rb +24 -0
  226. data/lib/active_record/type.rb +78 -0
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +9 -0
  229. data/lib/active_record/type/date_time.rb +9 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +71 -0
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +21 -0
  237. data/lib/active_record/type/type_map.rb +62 -0
  238. data/lib/active_record/type/unsigned_integer.rb +17 -0
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +94 -0
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +60 -0
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +68 -0
  247. data/lib/active_record/validations/uniqueness.rb +226 -0
  248. data/lib/active_record/version.rb +10 -0
  249. data/lib/arel.rb +58 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +19 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +48 -0
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +75 -0
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  337. data/lib/rails/generators/active_record/model/model_generator.rb +49 -0
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  340. metadata +418 -0
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module SecureToken
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ # Example using #has_secure_token
9
+ #
10
+ # # Schema: User(token:string, auth_token:string)
11
+ # class User < ActiveRecord::Base
12
+ # has_secure_token
13
+ # has_secure_token :auth_token
14
+ # end
15
+ #
16
+ # user = User.new
17
+ # user.save
18
+ # user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
19
+ # user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
20
+ # user.regenerate_token # => true
21
+ # user.regenerate_auth_token # => true
22
+ #
23
+ # <tt>SecureRandom::base58</tt> is used to generate the 24-character unique token, so collisions are highly unlikely.
24
+ #
25
+ # Note that it's still possible to generate a race condition in the database in the same way that
26
+ # {validates_uniqueness_of}[rdoc-ref:Validations::ClassMethods#validates_uniqueness_of] can.
27
+ # You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
28
+ def has_secure_token(attribute = :token)
29
+ # Load securerandom only when has_secure_token is used.
30
+ require "active_support/core_ext/securerandom"
31
+ define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
32
+ before_create { send("#{attribute}=", self.class.generate_unique_secure_token) unless send("#{attribute}?") }
33
+ end
34
+
35
+ def generate_unique_secure_token
36
+ SecureRandom.base58(24)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord #:nodoc:
4
+ # = Active Record \Serialization
5
+ module Serialization
6
+ extend ActiveSupport::Concern
7
+ include ActiveModel::Serializers::JSON
8
+
9
+ included do
10
+ self.include_root_in_json = false
11
+ end
12
+
13
+ def serializable_hash(options = nil)
14
+ options = options.try(:dup) || {}
15
+
16
+ options[:except] = Array(options[:except]).map(&:to_s)
17
+ options[:except] |= Array(self.class.inheritance_column)
18
+
19
+ super(options)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # Statement cache is used to cache a single statement in order to avoid creating the AST again.
5
+ # Initializing the cache is done by passing the statement in the create block:
6
+ #
7
+ # cache = StatementCache.create(Book.connection) do |params|
8
+ # Book.where(name: "my book").where("author_id > 3")
9
+ # end
10
+ #
11
+ # The cached statement is executed by using the
12
+ # {connection.execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute] method:
13
+ #
14
+ # cache.execute([], Book.connection)
15
+ #
16
+ # The relation returned by the block is cached, and for each
17
+ # {execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute]
18
+ # call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
19
+ #
20
+ # If you want to cache the statement without the values you can use the +bind+ method of the
21
+ # block parameter.
22
+ #
23
+ # cache = StatementCache.create(Book.connection) do |params|
24
+ # Book.where(name: params.bind)
25
+ # end
26
+ #
27
+ # And pass the bind values as the first argument of +execute+ call.
28
+ #
29
+ # cache.execute(["my book"], Book.connection)
30
+ class StatementCache # :nodoc:
31
+ class Substitute; end # :nodoc:
32
+
33
+ class Query # :nodoc:
34
+ def initialize(sql)
35
+ @sql = sql
36
+ end
37
+
38
+ def sql_for(binds, connection)
39
+ @sql
40
+ end
41
+ end
42
+
43
+ class PartialQuery < Query # :nodoc:
44
+ def initialize(values)
45
+ @values = values
46
+ @indexes = values.each_with_index.find_all { |thing, i|
47
+ Substitute === thing
48
+ }.map(&:last)
49
+ end
50
+
51
+ def sql_for(binds, connection)
52
+ val = @values.dup
53
+ casted_binds = binds.map(&:value_for_database)
54
+ @indexes.each { |i| val[i] = connection.quote(casted_binds.shift) }
55
+ val.join
56
+ end
57
+ end
58
+
59
+ class PartialQueryCollector
60
+ def initialize
61
+ @parts = []
62
+ @binds = []
63
+ end
64
+
65
+ def <<(str)
66
+ @parts << str
67
+ self
68
+ end
69
+
70
+ def add_bind(obj)
71
+ @binds << obj
72
+ @parts << Substitute.new
73
+ self
74
+ end
75
+
76
+ def value
77
+ [@parts, @binds]
78
+ end
79
+ end
80
+
81
+ def self.query(sql)
82
+ Query.new(sql)
83
+ end
84
+
85
+ def self.partial_query(values)
86
+ PartialQuery.new(values)
87
+ end
88
+
89
+ def self.partial_query_collector
90
+ PartialQueryCollector.new
91
+ end
92
+
93
+ class Params # :nodoc:
94
+ def bind; Substitute.new; end
95
+ end
96
+
97
+ class BindMap # :nodoc:
98
+ def initialize(bound_attributes)
99
+ @indexes = []
100
+ @bound_attributes = bound_attributes
101
+
102
+ bound_attributes.each_with_index do |attr, i|
103
+ if Substitute === attr.value
104
+ @indexes << i
105
+ end
106
+ end
107
+ end
108
+
109
+ def bind(values)
110
+ bas = @bound_attributes.dup
111
+ @indexes.each_with_index { |offset, i| bas[offset] = bas[offset].with_cast_value(values[i]) }
112
+ bas
113
+ end
114
+ end
115
+
116
+ def self.create(connection, callable = nil, &block)
117
+ relation = (callable || block).call Params.new
118
+ query_builder, binds = connection.cacheable_query(self, relation.arel)
119
+ bind_map = BindMap.new(binds)
120
+ new(query_builder, bind_map, relation.klass)
121
+ end
122
+
123
+ def initialize(query_builder, bind_map, klass)
124
+ @query_builder = query_builder
125
+ @bind_map = bind_map
126
+ @klass = klass
127
+ end
128
+
129
+ def execute(params, connection, &block)
130
+ bind_values = bind_map.bind params
131
+
132
+ sql = query_builder.sql_for bind_values, connection
133
+
134
+ klass.find_by_sql(sql, bind_values, preparable: true, &block)
135
+ rescue ::RangeError
136
+ nil
137
+ end
138
+
139
+ def self.unsupported_value?(value)
140
+ case value
141
+ when NilClass, Array, Range, Hash, Relation, Base then true
142
+ end
143
+ end
144
+
145
+ private
146
+ attr_reader :query_builder, :bind_map, :klass
147
+ end
148
+ end
@@ -0,0 +1,290 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/indifferent_access"
4
+
5
+ module ActiveRecord
6
+ # Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.
7
+ # It's like a simple key/value store baked into your record when you don't care about being able to
8
+ # query that store outside the context of a single record.
9
+ #
10
+ # You can then declare accessors to this store that are then accessible just like any other attribute
11
+ # of the model. This is very helpful for easily exposing store keys to a form or elsewhere that's
12
+ # already built around just accessing attributes on the model.
13
+ #
14
+ # Every accessor comes with dirty tracking methods (+key_changed?+, +key_was+ and +key_change+) and
15
+ # methods to access the changes made during the last save (+saved_change_to_key?+, +saved_change_to_key+ and
16
+ # +key_before_last_save+).
17
+ #
18
+ # NOTE: There is no +key_will_change!+ method for accessors, use +store_will_change!+ instead.
19
+ #
20
+ # Make sure that you declare the database column used for the serialized store as a text, so there's
21
+ # plenty of room.
22
+ #
23
+ # You can set custom coder to encode/decode your serialized attributes to/from different formats.
24
+ # JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
25
+ #
26
+ # NOTE: If you are using structured database data types (eg. PostgreSQL +hstore+/+json+, or MySQL 5.7+
27
+ # +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
28
+ # Simply use {.store_accessor}[rdoc-ref:ClassMethods#store_accessor] instead to generate
29
+ # the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
30
+ # using a symbol.
31
+ #
32
+ # NOTE: The default validations with the exception of +uniqueness+ will work.
33
+ # For example, if you want to check for +uniqueness+ with +hstore+ you will
34
+ # need to use a custom validation to handle it.
35
+ #
36
+ # Examples:
37
+ #
38
+ # class User < ActiveRecord::Base
39
+ # store :settings, accessors: [ :color, :homepage ], coder: JSON
40
+ # store :parent, accessors: [ :name ], coder: JSON, prefix: true
41
+ # store :spouse, accessors: [ :name ], coder: JSON, prefix: :partner
42
+ # store :settings, accessors: [ :two_factor_auth ], suffix: true
43
+ # store :settings, accessors: [ :login_retry ], suffix: :config
44
+ # end
45
+ #
46
+ # u = User.new(color: 'black', homepage: '37signals.com', parent_name: 'Mary', partner_name: 'Lily')
47
+ # u.color # Accessor stored attribute
48
+ # u.parent_name # Accessor stored attribute with prefix
49
+ # u.partner_name # Accessor stored attribute with custom prefix
50
+ # u.two_factor_auth_settings # Accessor stored attribute with suffix
51
+ # u.login_retry_config # Accessor stored attribute with custom suffix
52
+ # u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
53
+ #
54
+ # # There is no difference between strings and symbols for accessing custom attributes
55
+ # u.settings[:country] # => 'Denmark'
56
+ # u.settings['country'] # => 'Denmark'
57
+ #
58
+ # # Dirty tracking
59
+ # u.color = 'green'
60
+ # u.color_changed? # => true
61
+ # u.color_was # => 'black'
62
+ # u.color_change # => ['black', 'red']
63
+ #
64
+ # # Add additional accessors to an existing store through store_accessor
65
+ # class SuperUser < User
66
+ # store_accessor :settings, :privileges, :servants
67
+ # store_accessor :parent, :birthday, prefix: true
68
+ # store_accessor :settings, :secret_question, suffix: :config
69
+ # end
70
+ #
71
+ # The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
72
+ #
73
+ # User.stored_attributes[:settings] # [:color, :homepage, :two_factor_auth, :login_retry]
74
+ #
75
+ # == Overwriting default accessors
76
+ #
77
+ # All stored values are automatically available through accessors on the Active Record
78
+ # object, but sometimes you want to specialize this behavior. This can be done by overwriting
79
+ # the default accessors (using the same name as the attribute) and calling <tt>super</tt>
80
+ # to actually change things.
81
+ #
82
+ # class Song < ActiveRecord::Base
83
+ # # Uses a stored integer to hold the volume adjustment of the song
84
+ # store :settings, accessors: [:volume_adjustment]
85
+ #
86
+ # def volume_adjustment=(decibels)
87
+ # super(decibels.to_i)
88
+ # end
89
+ #
90
+ # def volume_adjustment
91
+ # super.to_i
92
+ # end
93
+ # end
94
+ module Store
95
+ extend ActiveSupport::Concern
96
+
97
+ included do
98
+ class << self
99
+ attr_accessor :local_stored_attributes
100
+ end
101
+ end
102
+
103
+ module ClassMethods
104
+ def store(store_attribute, options = {})
105
+ serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
106
+ store_accessor(store_attribute, options[:accessors], options.slice(:prefix, :suffix)) if options.has_key? :accessors
107
+ end
108
+
109
+ def store_accessor(store_attribute, *keys, prefix: nil, suffix: nil)
110
+ keys = keys.flatten
111
+
112
+ accessor_prefix =
113
+ case prefix
114
+ when String, Symbol
115
+ "#{prefix}_"
116
+ when TrueClass
117
+ "#{store_attribute}_"
118
+ else
119
+ ""
120
+ end
121
+ accessor_suffix =
122
+ case suffix
123
+ when String, Symbol
124
+ "_#{suffix}"
125
+ when TrueClass
126
+ "_#{store_attribute}"
127
+ else
128
+ ""
129
+ end
130
+
131
+ _store_accessors_module.module_eval do
132
+ keys.each do |key|
133
+ accessor_key = "#{accessor_prefix}#{key}#{accessor_suffix}"
134
+
135
+ define_method("#{accessor_key}=") do |value|
136
+ write_store_attribute(store_attribute, key, value)
137
+ end
138
+
139
+ define_method(accessor_key) do
140
+ read_store_attribute(store_attribute, key)
141
+ end
142
+
143
+ define_method("#{accessor_key}_changed?") do
144
+ return false unless attribute_changed?(store_attribute)
145
+ prev_store, new_store = changes[store_attribute]
146
+ prev_store&.dig(key) != new_store&.dig(key)
147
+ end
148
+
149
+ define_method("#{accessor_key}_change") do
150
+ return unless attribute_changed?(store_attribute)
151
+ prev_store, new_store = changes[store_attribute]
152
+ [prev_store&.dig(key), new_store&.dig(key)]
153
+ end
154
+
155
+ define_method("#{accessor_key}_was") do
156
+ return unless attribute_changed?(store_attribute)
157
+ prev_store, _new_store = changes[store_attribute]
158
+ prev_store&.dig(key)
159
+ end
160
+
161
+ define_method("saved_change_to_#{accessor_key}?") do
162
+ return false unless saved_change_to_attribute?(store_attribute)
163
+ prev_store, new_store = saved_change_to_attribute(store_attribute)
164
+ prev_store&.dig(key) != new_store&.dig(key)
165
+ end
166
+
167
+ define_method("saved_change_to_#{accessor_key}") do
168
+ return unless saved_change_to_attribute?(store_attribute)
169
+ prev_store, new_store = saved_change_to_attribute(store_attribute)
170
+ [prev_store&.dig(key), new_store&.dig(key)]
171
+ end
172
+
173
+ define_method("#{accessor_key}_before_last_save") do
174
+ return unless saved_change_to_attribute?(store_attribute)
175
+ prev_store, _new_store = saved_change_to_attribute(store_attribute)
176
+ prev_store&.dig(key)
177
+ end
178
+ end
179
+ end
180
+
181
+ # assign new store attribute and create new hash to ensure that each class in the hierarchy
182
+ # has its own hash of stored attributes.
183
+ self.local_stored_attributes ||= {}
184
+ self.local_stored_attributes[store_attribute] ||= []
185
+ self.local_stored_attributes[store_attribute] |= keys
186
+ end
187
+
188
+ def _store_accessors_module # :nodoc:
189
+ @_store_accessors_module ||= begin
190
+ mod = Module.new
191
+ include mod
192
+ mod
193
+ end
194
+ end
195
+
196
+ def stored_attributes
197
+ parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
198
+ if local_stored_attributes
199
+ parent.merge!(local_stored_attributes) { |k, a, b| a | b }
200
+ end
201
+ parent
202
+ end
203
+ end
204
+
205
+ private
206
+ def read_store_attribute(store_attribute, key) # :doc:
207
+ accessor = store_accessor_for(store_attribute)
208
+ accessor.read(self, store_attribute, key)
209
+ end
210
+
211
+ def write_store_attribute(store_attribute, key, value) # :doc:
212
+ accessor = store_accessor_for(store_attribute)
213
+ accessor.write(self, store_attribute, key, value)
214
+ end
215
+
216
+ def store_accessor_for(store_attribute)
217
+ type_for_attribute(store_attribute).accessor
218
+ end
219
+
220
+ class HashAccessor # :nodoc:
221
+ def self.read(object, attribute, key)
222
+ prepare(object, attribute)
223
+ object.public_send(attribute)[key]
224
+ end
225
+
226
+ def self.write(object, attribute, key, value)
227
+ prepare(object, attribute)
228
+ if value != read(object, attribute, key)
229
+ object.public_send :"#{attribute}_will_change!"
230
+ object.public_send(attribute)[key] = value
231
+ end
232
+ end
233
+
234
+ def self.prepare(object, attribute)
235
+ object.public_send :"#{attribute}=", {} unless object.send(attribute)
236
+ end
237
+ end
238
+
239
+ class StringKeyedHashAccessor < HashAccessor # :nodoc:
240
+ def self.read(object, attribute, key)
241
+ super object, attribute, key.to_s
242
+ end
243
+
244
+ def self.write(object, attribute, key, value)
245
+ super object, attribute, key.to_s, value
246
+ end
247
+ end
248
+
249
+ class IndifferentHashAccessor < ActiveRecord::Store::HashAccessor # :nodoc:
250
+ def self.prepare(object, store_attribute)
251
+ attribute = object.send(store_attribute)
252
+ unless attribute.is_a?(ActiveSupport::HashWithIndifferentAccess)
253
+ attribute = IndifferentCoder.as_indifferent_hash(attribute)
254
+ object.send :"#{store_attribute}=", attribute
255
+ end
256
+ attribute
257
+ end
258
+ end
259
+
260
+ class IndifferentCoder # :nodoc:
261
+ def initialize(attr_name, coder_or_class_name)
262
+ @coder =
263
+ if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
264
+ coder_or_class_name
265
+ else
266
+ ActiveRecord::Coders::YAMLColumn.new(attr_name, coder_or_class_name || Object)
267
+ end
268
+ end
269
+
270
+ def dump(obj)
271
+ @coder.dump self.class.as_indifferent_hash(obj)
272
+ end
273
+
274
+ def load(yaml)
275
+ self.class.as_indifferent_hash(@coder.load(yaml || ""))
276
+ end
277
+
278
+ def self.as_indifferent_hash(obj)
279
+ case obj
280
+ when ActiveSupport::HashWithIndifferentAccess
281
+ obj
282
+ when Hash
283
+ obj.with_indifferent_access
284
+ else
285
+ ActiveSupport::HashWithIndifferentAccess.new
286
+ end
287
+ end
288
+ end
289
+ end
290
+ end