activerecord 6.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (340) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1013 -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 +40 -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 +332 -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 +258 -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 +508 -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 +1165 -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 +512 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +154 -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 +761 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +821 -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 +200 -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 +182 -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 +949 -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 +118 -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 +557 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +267 -0
  129. data/lib/active_record/core.rb +599 -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 +92 -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 +542 -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 +859 -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 +552 -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 +1359 -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 +51 -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 +415 -0
@@ -0,0 +1,207 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/filters"
4
+
5
+ module ActiveRecord
6
+ module Integration
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ ##
11
+ # :singleton-method:
12
+ # Indicates the format used to generate the timestamp in the cache key, if
13
+ # versioning is off. Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
14
+ #
15
+ # This is +:usec+, by default.
16
+ class_attribute :cache_timestamp_format, instance_writer: false, default: :usec
17
+
18
+ ##
19
+ # :singleton-method:
20
+ # Indicates whether to use a stable #cache_key method that is accompanied
21
+ # by a changing version in the #cache_version method.
22
+ #
23
+ # This is +true+, by default on Rails 5.2 and above.
24
+ class_attribute :cache_versioning, instance_writer: false, default: false
25
+
26
+ ##
27
+ # :singleton-method:
28
+ # Indicates whether to use a stable #cache_key method that is accompanied
29
+ # by a changing version in the #cache_version method on collections.
30
+ #
31
+ # This is +false+, by default until Rails 6.1.
32
+ class_attribute :collection_cache_versioning, instance_writer: false, default: false
33
+ end
34
+
35
+ # Returns a +String+, which Action Pack uses for constructing a URL to this
36
+ # object. The default implementation returns this record's id as a +String+,
37
+ # or +nil+ if this record's unsaved.
38
+ #
39
+ # For example, suppose that you have a User model, and that you have a
40
+ # <tt>resources :users</tt> route. Normally, +user_path+ will
41
+ # construct a path with the user object's 'id' in it:
42
+ #
43
+ # user = User.find_by(name: 'Phusion')
44
+ # user_path(user) # => "/users/1"
45
+ #
46
+ # You can override +to_param+ in your model to make +user_path+ construct
47
+ # a path using the user's name instead of the user's id:
48
+ #
49
+ # class User < ActiveRecord::Base
50
+ # def to_param # overridden
51
+ # name
52
+ # end
53
+ # end
54
+ #
55
+ # user = User.find_by(name: 'Phusion')
56
+ # user_path(user) # => "/users/Phusion"
57
+ def to_param
58
+ # We can't use alias_method here, because method 'id' optimizes itself on the fly.
59
+ id && id.to_s # Be sure to stringify the id for routes
60
+ end
61
+
62
+ # Returns a stable cache key that can be used to identify this record.
63
+ #
64
+ # Product.new.cache_key # => "products/new"
65
+ # Product.find(5).cache_key # => "products/5"
66
+ #
67
+ # If ActiveRecord::Base.cache_versioning is turned off, as it was in Rails 5.1 and earlier,
68
+ # the cache key will also include a version.
69
+ #
70
+ # Product.cache_versioning = false
71
+ # Product.find(5).cache_key # => "products/5-20071224150000" (updated_at available)
72
+ def cache_key
73
+ if new_record?
74
+ "#{model_name.cache_key}/new"
75
+ else
76
+ if cache_version
77
+ "#{model_name.cache_key}/#{id}"
78
+ else
79
+ timestamp = max_updated_column_timestamp
80
+
81
+ if timestamp
82
+ timestamp = timestamp.utc.to_s(cache_timestamp_format)
83
+ "#{model_name.cache_key}/#{id}-#{timestamp}"
84
+ else
85
+ "#{model_name.cache_key}/#{id}"
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ # Returns a cache version that can be used together with the cache key to form
92
+ # a recyclable caching scheme. By default, the #updated_at column is used for the
93
+ # cache_version, but this method can be overwritten to return something else.
94
+ #
95
+ # Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to
96
+ # +false+ (which it is by default until Rails 6.0).
97
+ def cache_version
98
+ return unless cache_versioning
99
+
100
+ if has_attribute?("updated_at")
101
+ timestamp = updated_at_before_type_cast
102
+ if can_use_fast_cache_version?(timestamp)
103
+ raw_timestamp_to_cache_version(timestamp)
104
+ elsif timestamp = updated_at
105
+ timestamp.utc.to_s(cache_timestamp_format)
106
+ end
107
+ else
108
+ if self.class.has_attribute?("updated_at")
109
+ raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
110
+ end
111
+ end
112
+ end
113
+
114
+ # Returns a cache key along with the version.
115
+ def cache_key_with_version
116
+ if version = cache_version
117
+ "#{cache_key}-#{version}"
118
+ else
119
+ cache_key
120
+ end
121
+ end
122
+
123
+ module ClassMethods
124
+ # Defines your model's +to_param+ method to generate "pretty" URLs
125
+ # using +method_name+, which can be any attribute or method that
126
+ # responds to +to_s+.
127
+ #
128
+ # class User < ActiveRecord::Base
129
+ # to_param :name
130
+ # end
131
+ #
132
+ # user = User.find_by(name: 'Fancy Pants')
133
+ # user.id # => 123
134
+ # user_path(user) # => "/users/123-fancy-pants"
135
+ #
136
+ # Values longer than 20 characters will be truncated. The value
137
+ # is truncated word by word.
138
+ #
139
+ # user = User.find_by(name: 'David Heinemeier Hansson')
140
+ # user.id # => 125
141
+ # user_path(user) # => "/users/125-david-heinemeier"
142
+ #
143
+ # Because the generated param begins with the record's +id+, it is
144
+ # suitable for passing to +find+. In a controller, for example:
145
+ #
146
+ # params[:id] # => "123-fancy-pants"
147
+ # User.find(params[:id]).id # => 123
148
+ def to_param(method_name = nil)
149
+ if method_name.nil?
150
+ super()
151
+ else
152
+ define_method :to_param do
153
+ if (default = super()) &&
154
+ (result = send(method_name).to_s).present? &&
155
+ (param = result.squish.parameterize.truncate(20, separator: /-/, omission: "")).present?
156
+ "#{default}-#{param}"
157
+ else
158
+ default
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ def collection_cache_key(collection = all, timestamp_column = :updated_at) # :nodoc:
165
+ collection.send(:compute_cache_key, timestamp_column)
166
+ end
167
+ end
168
+
169
+ private
170
+ # Detects if the value before type cast
171
+ # can be used to generate a cache_version.
172
+ #
173
+ # The fast cache version only works with a
174
+ # string value directly from the database.
175
+ #
176
+ # We also must check if the timestamp format has been changed
177
+ # or if the timezone is not set to UTC then
178
+ # we cannot apply our transformations correctly.
179
+ def can_use_fast_cache_version?(timestamp)
180
+ timestamp.is_a?(String) &&
181
+ cache_timestamp_format == :usec &&
182
+ default_timezone == :utc &&
183
+ !updated_at_came_from_user?
184
+ end
185
+
186
+ # Converts a raw database string to `:usec`
187
+ # format.
188
+ #
189
+ # Example:
190
+ #
191
+ # timestamp = "2018-10-15 20:02:15.266505"
192
+ # raw_timestamp_to_cache_version(timestamp)
193
+ # # => "20181015200215266505"
194
+ #
195
+ # PostgreSQL truncates trailing zeros,
196
+ # https://github.com/postgres/postgres/commit/3e1beda2cde3495f41290e1ece5d544525810214
197
+ # to account for this we pad the output with zeros
198
+ def raw_timestamp_to_cache_version(timestamp)
199
+ key = timestamp.delete("- :.")
200
+ if key.length < 20
201
+ key.ljust(20, "0")
202
+ else
203
+ key
204
+ end
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/scoping/default"
4
+ require "active_record/scoping/named"
5
+
6
+ module ActiveRecord
7
+ # This class is used to create a table that keeps track of values and keys such
8
+ # as which environment migrations were run in.
9
+ class InternalMetadata < ActiveRecord::Base # :nodoc:
10
+ class << self
11
+ def _internal?
12
+ true
13
+ end
14
+
15
+ def primary_key
16
+ "key"
17
+ end
18
+
19
+ def table_name
20
+ "#{table_name_prefix}#{internal_metadata_table_name}#{table_name_suffix}"
21
+ end
22
+
23
+ def []=(key, value)
24
+ find_or_initialize_by(key: key).update!(value: value)
25
+ end
26
+
27
+ def [](key)
28
+ where(key: key).pluck(:value).first
29
+ end
30
+
31
+ def table_exists?
32
+ connection.table_exists?(table_name)
33
+ end
34
+
35
+ # Creates an internal metadata table with columns +key+ and +value+
36
+ def create_table
37
+ unless table_exists?
38
+ key_options = connection.internal_string_options_for_primary_key
39
+
40
+ connection.create_table(table_name, id: false) do |t|
41
+ t.string :key, key_options
42
+ t.string :value
43
+ t.timestamps
44
+ end
45
+ end
46
+ end
47
+
48
+ def drop_table
49
+ connection.drop_table table_name, if_exists: true
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module LegacyYamlAdapter
5
+ def self.convert(klass, coder)
6
+ return coder unless coder.is_a?(Psych::Coder)
7
+
8
+ case coder["active_record_yaml_version"]
9
+ when 1, 2 then coder
10
+ else
11
+ if coder["attributes"].is_a?(ActiveModel::AttributeSet)
12
+ Rails420.convert(klass, coder)
13
+ else
14
+ Rails41.convert(klass, coder)
15
+ end
16
+ end
17
+ end
18
+
19
+ module Rails420
20
+ def self.convert(klass, coder)
21
+ attribute_set = coder["attributes"]
22
+
23
+ klass.attribute_names.each do |attr_name|
24
+ attribute = attribute_set[attr_name]
25
+ if attribute.type.is_a?(Delegator)
26
+ type_from_klass = klass.type_for_attribute(attr_name)
27
+ attribute_set[attr_name] = attribute.with_type(type_from_klass)
28
+ end
29
+ end
30
+
31
+ coder
32
+ end
33
+ end
34
+
35
+ module Rails41
36
+ def self.convert(klass, coder)
37
+ attributes = klass.attributes_builder
38
+ .build_from_database(coder["attributes"])
39
+ new_record = coder["attributes"][klass.primary_key].blank?
40
+
41
+ {
42
+ "attributes" => attributes,
43
+ "new_record" => new_record,
44
+ }
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,48 @@
1
+ en:
2
+ # Attributes names common to most models
3
+ #attributes:
4
+ #created_at: "Created at"
5
+ #updated_at: "Updated at"
6
+
7
+ # Default error messages
8
+ errors:
9
+ messages:
10
+ required: "must exist"
11
+ taken: "has already been taken"
12
+
13
+ # Active Record models configuration
14
+ activerecord:
15
+ errors:
16
+ messages:
17
+ record_invalid: "Validation failed: %{errors}"
18
+ restrict_dependent_destroy:
19
+ has_one: "Cannot delete record because a dependent %{record} exists"
20
+ has_many: "Cannot delete record because dependent %{record} exist"
21
+ # Append your own errors here or at the model/attributes scope.
22
+
23
+ # You can define own errors for models or model attributes.
24
+ # The values :model, :attribute and :value are always available for interpolation.
25
+ #
26
+ # For example,
27
+ # models:
28
+ # user:
29
+ # blank: "This is a custom blank message for %{model}: %{attribute}"
30
+ # attributes:
31
+ # login:
32
+ # blank: "This is a custom blank message for User login"
33
+ # Will define custom blank validation message for User model and
34
+ # custom blank validation message for login attribute of User model.
35
+ #models:
36
+
37
+ # Translate model names. Used in Model.human_name().
38
+ #models:
39
+ # For example,
40
+ # user: "Dude"
41
+ # will translate User model name to "Dude"
42
+
43
+ # Translate model attribute names. Used in Model.human_attribute_name(attribute).
44
+ #attributes:
45
+ # For example,
46
+ # user:
47
+ # login: "Handle"
48
+ # will translate User attribute "login" as "Handle"
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Locking
5
+ # == What is Optimistic Locking
6
+ #
7
+ # Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of
8
+ # conflicts with the data. It does this by checking whether another process has made changes to a record since
9
+ # it was opened, an <tt>ActiveRecord::StaleObjectError</tt> exception is thrown if that has occurred
10
+ # and the update is ignored.
11
+ #
12
+ # Check out <tt>ActiveRecord::Locking::Pessimistic</tt> for an alternative.
13
+ #
14
+ # == Usage
15
+ #
16
+ # Active Record supports optimistic locking if the +lock_version+ field is present. Each update to the
17
+ # record increments the +lock_version+ column and the locking facilities ensure that records instantiated twice
18
+ # will let the last one saved raise a +StaleObjectError+ if the first was also updated. Example:
19
+ #
20
+ # p1 = Person.find(1)
21
+ # p2 = Person.find(1)
22
+ #
23
+ # p1.first_name = "Michael"
24
+ # p1.save
25
+ #
26
+ # p2.first_name = "should fail"
27
+ # p2.save # Raises an ActiveRecord::StaleObjectError
28
+ #
29
+ # Optimistic locking will also check for stale data when objects are destroyed. Example:
30
+ #
31
+ # p1 = Person.find(1)
32
+ # p2 = Person.find(1)
33
+ #
34
+ # p1.first_name = "Michael"
35
+ # p1.save
36
+ #
37
+ # p2.destroy # Raises an ActiveRecord::StaleObjectError
38
+ #
39
+ # You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
40
+ # or otherwise apply the business logic needed to resolve the conflict.
41
+ #
42
+ # This locking mechanism will function inside a single Ruby process. To make it work across all
43
+ # web requests, the recommended approach is to add +lock_version+ as a hidden field to your form.
44
+ #
45
+ # This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>.
46
+ # To override the name of the +lock_version+ column, set the <tt>locking_column</tt> class attribute:
47
+ #
48
+ # class Person < ActiveRecord::Base
49
+ # self.locking_column = :lock_person
50
+ # end
51
+ #
52
+ module Optimistic
53
+ extend ActiveSupport::Concern
54
+
55
+ included do
56
+ class_attribute :lock_optimistically, instance_writer: false, default: true
57
+ end
58
+
59
+ def locking_enabled? #:nodoc:
60
+ self.class.locking_enabled?
61
+ end
62
+
63
+ private
64
+ def _create_record(attribute_names = self.attribute_names)
65
+ if locking_enabled?
66
+ # We always want to persist the locking version, even if we don't detect
67
+ # a change from the default, since the database might have no default
68
+ attribute_names |= [self.class.locking_column]
69
+ end
70
+ super
71
+ end
72
+
73
+ def _touch_row(attribute_names, time)
74
+ @_touch_attr_names << self.class.locking_column if locking_enabled?
75
+ super
76
+ end
77
+
78
+ def _update_row(attribute_names, attempted_action = "update")
79
+ return super unless locking_enabled?
80
+
81
+ begin
82
+ locking_column = self.class.locking_column
83
+ previous_lock_value = read_attribute_before_type_cast(locking_column)
84
+ attribute_names << locking_column
85
+
86
+ self[locking_column] += 1
87
+
88
+ affected_rows = self.class._update_record(
89
+ attributes_with_values(attribute_names),
90
+ @primary_key => id_in_database,
91
+ locking_column => previous_lock_value
92
+ )
93
+
94
+ if affected_rows != 1
95
+ raise ActiveRecord::StaleObjectError.new(self, attempted_action)
96
+ end
97
+
98
+ affected_rows
99
+
100
+ # If something went wrong, revert the locking_column value.
101
+ rescue Exception
102
+ self[locking_column] = previous_lock_value.to_i
103
+ raise
104
+ end
105
+ end
106
+
107
+ def destroy_row
108
+ return super unless locking_enabled?
109
+
110
+ locking_column = self.class.locking_column
111
+
112
+ affected_rows = self.class._delete_record(
113
+ @primary_key => id_in_database,
114
+ locking_column => read_attribute_before_type_cast(locking_column)
115
+ )
116
+
117
+ if affected_rows != 1
118
+ raise ActiveRecord::StaleObjectError.new(self, "destroy")
119
+ end
120
+
121
+ affected_rows
122
+ end
123
+
124
+ module ClassMethods
125
+ DEFAULT_LOCKING_COLUMN = "lock_version"
126
+
127
+ # Returns true if the +lock_optimistically+ flag is set to true
128
+ # (which it is, by default) and the table includes the
129
+ # +locking_column+ column (defaults to +lock_version+).
130
+ def locking_enabled?
131
+ lock_optimistically && columns_hash[locking_column]
132
+ end
133
+
134
+ # Set the column to use for optimistic locking. Defaults to +lock_version+.
135
+ def locking_column=(value)
136
+ reload_schema_from_cache
137
+ @locking_column = value.to_s
138
+ end
139
+
140
+ # The version column used for optimistic locking. Defaults to +lock_version+.
141
+ def locking_column
142
+ @locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
143
+ @locking_column
144
+ end
145
+
146
+ # Reset the column used for optimistic locking back to the +lock_version+ default.
147
+ def reset_locking_column
148
+ self.locking_column = DEFAULT_LOCKING_COLUMN
149
+ end
150
+
151
+ # Make sure the lock version column gets updated when counters are
152
+ # updated.
153
+ def update_counters(id, counters)
154
+ counters = counters.merge(locking_column => 1) if locking_enabled?
155
+ super
156
+ end
157
+
158
+ private
159
+
160
+ # We need to apply this decorator here, rather than on module inclusion. The closure
161
+ # created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the
162
+ # sub class being decorated. As such, changes to `lock_optimistically`, or
163
+ # `locking_column` would not be picked up.
164
+ def inherited(subclass)
165
+ subclass.class_eval do
166
+ is_lock_column = ->(name, _) { lock_optimistically && name == locking_column }
167
+ decorate_matching_attribute_types(is_lock_column, "_optimistic_locking") do |type|
168
+ LockingType.new(type)
169
+ end
170
+ end
171
+ super
172
+ end
173
+ end
174
+ end
175
+
176
+ # In de/serialize we change `nil` to 0, so that we can allow passing
177
+ # `nil` values to `lock_version`, and not result in `ActiveRecord::StaleObjectError`
178
+ # during update record.
179
+ class LockingType < DelegateClass(Type::Value) # :nodoc:
180
+ def deserialize(value)
181
+ super.to_i
182
+ end
183
+
184
+ def serialize(value)
185
+ super.to_i
186
+ end
187
+
188
+ def init_with(coder)
189
+ __setobj__(coder["subtype"])
190
+ end
191
+
192
+ def encode_with(coder)
193
+ coder["subtype"] = __getobj__
194
+ end
195
+ end
196
+ end
197
+ end