omg-activerecord 8.0.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (412) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +355 -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/aggregations.rb +287 -0
  8. data/lib/active_record/association_relation.rb +50 -0
  9. data/lib/active_record/associations/alias_tracker.rb +90 -0
  10. data/lib/active_record/associations/association.rb +417 -0
  11. data/lib/active_record/associations/association_scope.rb +175 -0
  12. data/lib/active_record/associations/belongs_to_association.rb +163 -0
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
  14. data/lib/active_record/associations/builder/association.rb +170 -0
  15. data/lib/active_record/associations/builder/belongs_to.rb +160 -0
  16. data/lib/active_record/associations/builder/collection_association.rb +80 -0
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +107 -0
  18. data/lib/active_record/associations/builder/has_many.rb +23 -0
  19. data/lib/active_record/associations/builder/has_one.rb +61 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +48 -0
  21. data/lib/active_record/associations/collection_association.rb +535 -0
  22. data/lib/active_record/associations/collection_proxy.rb +1163 -0
  23. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  24. data/lib/active_record/associations/errors.rb +265 -0
  25. data/lib/active_record/associations/foreign_association.rb +40 -0
  26. data/lib/active_record/associations/has_many_association.rb +167 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +232 -0
  28. data/lib/active_record/associations/has_one_association.rb +142 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency/join_association.rb +106 -0
  31. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  32. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  33. data/lib/active_record/associations/join_dependency.rb +301 -0
  34. data/lib/active_record/associations/nested_error.rb +47 -0
  35. data/lib/active_record/associations/preloader/association.rb +316 -0
  36. data/lib/active_record/associations/preloader/batch.rb +48 -0
  37. data/lib/active_record/associations/preloader/branch.rb +153 -0
  38. data/lib/active_record/associations/preloader/through_association.rb +150 -0
  39. data/lib/active_record/associations/preloader.rb +135 -0
  40. data/lib/active_record/associations/singular_association.rb +76 -0
  41. data/lib/active_record/associations/through_association.rb +132 -0
  42. data/lib/active_record/associations.rb +1897 -0
  43. data/lib/active_record/asynchronous_queries_tracker.rb +64 -0
  44. data/lib/active_record/attribute_assignment.rb +82 -0
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +106 -0
  46. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  47. data/lib/active_record/attribute_methods/dirty.rb +262 -0
  48. data/lib/active_record/attribute_methods/primary_key.rb +158 -0
  49. data/lib/active_record/attribute_methods/query.rb +50 -0
  50. data/lib/active_record/attribute_methods/read.rb +46 -0
  51. data/lib/active_record/attribute_methods/serialization.rb +232 -0
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +94 -0
  53. data/lib/active_record/attribute_methods/write.rb +49 -0
  54. data/lib/active_record/attribute_methods.rb +542 -0
  55. data/lib/active_record/attributes.rb +307 -0
  56. data/lib/active_record/autosave_association.rb +586 -0
  57. data/lib/active_record/base.rb +338 -0
  58. data/lib/active_record/callbacks.rb +452 -0
  59. data/lib/active_record/coders/column_serializer.rb +61 -0
  60. data/lib/active_record/coders/json.rb +15 -0
  61. data/lib/active_record/coders/yaml_column.rb +95 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +290 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +210 -0
  64. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +923 -0
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +31 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +747 -0
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +319 -0
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +239 -0
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +24 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +190 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +961 -0
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +106 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1883 -0
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +676 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +1218 -0
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1016 -0
  78. data/lib/active_record/connection_adapters/column.rb +122 -0
  79. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  80. data/lib/active_record/connection_adapters/mysql/column.rb +28 -0
  81. data/lib/active_record/connection_adapters/mysql/database_statements.rb +95 -0
  82. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  83. data/lib/active_record/connection_adapters/mysql/quoting.rb +114 -0
  84. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +106 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +106 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +97 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +300 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  89. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +96 -0
  90. data/lib/active_record/connection_adapters/mysql2_adapter.rb +196 -0
  91. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  92. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  93. data/lib/active_record/connection_adapters/postgresql/column.rb +82 -0
  94. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +231 -0
  95. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +91 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +54 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +31 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +20 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +109 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +42 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +74 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +124 -0
  115. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  116. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  117. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  118. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +125 -0
  119. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +45 -0
  120. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  121. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  122. data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -0
  123. data/lib/active_record/connection_adapters/postgresql/quoting.rb +238 -0
  124. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +71 -0
  125. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +169 -0
  126. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +392 -0
  127. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +127 -0
  128. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1162 -0
  129. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  130. data/lib/active_record/connection_adapters/postgresql/utils.rb +79 -0
  131. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1182 -0
  132. data/lib/active_record/connection_adapters/schema_cache.rb +478 -0
  133. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  134. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  135. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +145 -0
  136. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  137. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +116 -0
  138. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +37 -0
  139. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +39 -0
  140. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +47 -0
  141. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +221 -0
  142. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +843 -0
  143. data/lib/active_record/connection_adapters/statement_pool.rb +67 -0
  144. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +69 -0
  145. data/lib/active_record/connection_adapters/trilogy_adapter.rb +212 -0
  146. data/lib/active_record/connection_adapters.rb +176 -0
  147. data/lib/active_record/connection_handling.rb +413 -0
  148. data/lib/active_record/core.rb +836 -0
  149. data/lib/active_record/counter_cache.rb +230 -0
  150. data/lib/active_record/database_configurations/connection_url_resolver.rb +105 -0
  151. data/lib/active_record/database_configurations/database_config.rb +104 -0
  152. data/lib/active_record/database_configurations/hash_config.rb +172 -0
  153. data/lib/active_record/database_configurations/url_config.rb +78 -0
  154. data/lib/active_record/database_configurations.rb +309 -0
  155. data/lib/active_record/delegated_type.rb +289 -0
  156. data/lib/active_record/deprecator.rb +7 -0
  157. data/lib/active_record/destroy_association_async_job.rb +38 -0
  158. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  159. data/lib/active_record/dynamic_matchers.rb +121 -0
  160. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  161. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  162. data/lib/active_record/encryption/cipher.rb +53 -0
  163. data/lib/active_record/encryption/config.rb +70 -0
  164. data/lib/active_record/encryption/configurable.rb +60 -0
  165. data/lib/active_record/encryption/context.rb +42 -0
  166. data/lib/active_record/encryption/contexts.rb +76 -0
  167. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  168. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  169. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  170. data/lib/active_record/encryption/encrypted_attribute_type.rb +184 -0
  171. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  172. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  173. data/lib/active_record/encryption/encryptor.rb +177 -0
  174. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  175. data/lib/active_record/encryption/errors.rb +15 -0
  176. data/lib/active_record/encryption/extended_deterministic_queries.rb +159 -0
  177. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  178. data/lib/active_record/encryption/key.rb +28 -0
  179. data/lib/active_record/encryption/key_generator.rb +53 -0
  180. data/lib/active_record/encryption/key_provider.rb +46 -0
  181. data/lib/active_record/encryption/message.rb +33 -0
  182. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  183. data/lib/active_record/encryption/message_serializer.rb +96 -0
  184. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  185. data/lib/active_record/encryption/properties.rb +76 -0
  186. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  187. data/lib/active_record/encryption/scheme.rb +107 -0
  188. data/lib/active_record/encryption.rb +58 -0
  189. data/lib/active_record/enum.rb +424 -0
  190. data/lib/active_record/errors.rb +614 -0
  191. data/lib/active_record/explain.rb +63 -0
  192. data/lib/active_record/explain_registry.rb +37 -0
  193. data/lib/active_record/explain_subscriber.rb +34 -0
  194. data/lib/active_record/fixture_set/file.rb +89 -0
  195. data/lib/active_record/fixture_set/model_metadata.rb +42 -0
  196. data/lib/active_record/fixture_set/render_context.rb +19 -0
  197. data/lib/active_record/fixture_set/table_row.rb +208 -0
  198. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  199. data/lib/active_record/fixtures.rb +850 -0
  200. data/lib/active_record/future_result.rb +182 -0
  201. data/lib/active_record/gem_version.rb +17 -0
  202. data/lib/active_record/inheritance.rb +366 -0
  203. data/lib/active_record/insert_all.rb +328 -0
  204. data/lib/active_record/integration.rb +209 -0
  205. data/lib/active_record/internal_metadata.rb +164 -0
  206. data/lib/active_record/legacy_yaml_adapter.rb +15 -0
  207. data/lib/active_record/locale/en.yml +48 -0
  208. data/lib/active_record/locking/optimistic.rb +228 -0
  209. data/lib/active_record/locking/pessimistic.rb +102 -0
  210. data/lib/active_record/log_subscriber.rb +149 -0
  211. data/lib/active_record/marshalling.rb +56 -0
  212. data/lib/active_record/message_pack.rb +124 -0
  213. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  214. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  215. data/lib/active_record/middleware/database_selector.rb +87 -0
  216. data/lib/active_record/middleware/shard_selector.rb +62 -0
  217. data/lib/active_record/migration/command_recorder.rb +406 -0
  218. data/lib/active_record/migration/compatibility.rb +490 -0
  219. data/lib/active_record/migration/default_strategy.rb +22 -0
  220. data/lib/active_record/migration/execution_strategy.rb +19 -0
  221. data/lib/active_record/migration/join_table.rb +16 -0
  222. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  223. data/lib/active_record/migration.rb +1626 -0
  224. data/lib/active_record/model_schema.rb +635 -0
  225. data/lib/active_record/nested_attributes.rb +633 -0
  226. data/lib/active_record/no_touching.rb +65 -0
  227. data/lib/active_record/normalization.rb +163 -0
  228. data/lib/active_record/persistence.rb +968 -0
  229. data/lib/active_record/promise.rb +84 -0
  230. data/lib/active_record/query_cache.rb +56 -0
  231. data/lib/active_record/query_logs.rb +247 -0
  232. data/lib/active_record/query_logs_formatter.rb +30 -0
  233. data/lib/active_record/querying.rb +122 -0
  234. data/lib/active_record/railtie.rb +440 -0
  235. data/lib/active_record/railties/console_sandbox.rb +5 -0
  236. data/lib/active_record/railties/controller_runtime.rb +65 -0
  237. data/lib/active_record/railties/databases.rake +641 -0
  238. data/lib/active_record/railties/job_runtime.rb +23 -0
  239. data/lib/active_record/readonly_attributes.rb +66 -0
  240. data/lib/active_record/reflection.rb +1287 -0
  241. data/lib/active_record/relation/batches/batch_enumerator.rb +115 -0
  242. data/lib/active_record/relation/batches.rb +491 -0
  243. data/lib/active_record/relation/calculations.rb +679 -0
  244. data/lib/active_record/relation/delegation.rb +154 -0
  245. data/lib/active_record/relation/finder_methods.rb +661 -0
  246. data/lib/active_record/relation/from_clause.rb +30 -0
  247. data/lib/active_record/relation/merger.rb +192 -0
  248. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  249. data/lib/active_record/relation/predicate_builder/association_query_value.rb +76 -0
  250. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  251. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +60 -0
  252. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  253. data/lib/active_record/relation/predicate_builder/relation_handler.rb +24 -0
  254. data/lib/active_record/relation/predicate_builder.rb +181 -0
  255. data/lib/active_record/relation/query_attribute.rb +68 -0
  256. data/lib/active_record/relation/query_methods.rb +2235 -0
  257. data/lib/active_record/relation/record_fetch_warning.rb +52 -0
  258. data/lib/active_record/relation/spawn_methods.rb +78 -0
  259. data/lib/active_record/relation/where_clause.rb +218 -0
  260. data/lib/active_record/relation.rb +1495 -0
  261. data/lib/active_record/result.rb +249 -0
  262. data/lib/active_record/runtime_registry.rb +82 -0
  263. data/lib/active_record/sanitization.rb +254 -0
  264. data/lib/active_record/schema.rb +77 -0
  265. data/lib/active_record/schema_dumper.rb +364 -0
  266. data/lib/active_record/schema_migration.rb +106 -0
  267. data/lib/active_record/scoping/default.rb +205 -0
  268. data/lib/active_record/scoping/named.rb +202 -0
  269. data/lib/active_record/scoping.rb +136 -0
  270. data/lib/active_record/secure_password.rb +60 -0
  271. data/lib/active_record/secure_token.rb +66 -0
  272. data/lib/active_record/serialization.rb +29 -0
  273. data/lib/active_record/signed_id.rb +137 -0
  274. data/lib/active_record/statement_cache.rb +164 -0
  275. data/lib/active_record/store.rb +299 -0
  276. data/lib/active_record/suppressor.rb +59 -0
  277. data/lib/active_record/table_metadata.rb +85 -0
  278. data/lib/active_record/tasks/database_tasks.rb +681 -0
  279. data/lib/active_record/tasks/mysql_database_tasks.rb +120 -0
  280. data/lib/active_record/tasks/postgresql_database_tasks.rb +147 -0
  281. data/lib/active_record/tasks/sqlite_database_tasks.rb +89 -0
  282. data/lib/active_record/test_databases.rb +24 -0
  283. data/lib/active_record/test_fixtures.rb +321 -0
  284. data/lib/active_record/testing/query_assertions.rb +121 -0
  285. data/lib/active_record/timestamp.rb +177 -0
  286. data/lib/active_record/token_for.rb +123 -0
  287. data/lib/active_record/touch_later.rb +70 -0
  288. data/lib/active_record/transaction.rb +132 -0
  289. data/lib/active_record/transactions.rb +523 -0
  290. data/lib/active_record/translation.rb +22 -0
  291. data/lib/active_record/type/adapter_specific_registry.rb +144 -0
  292. data/lib/active_record/type/date.rb +9 -0
  293. data/lib/active_record/type/date_time.rb +9 -0
  294. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  295. data/lib/active_record/type/hash_lookup_type_map.rb +57 -0
  296. data/lib/active_record/type/internal/timezone.rb +22 -0
  297. data/lib/active_record/type/json.rb +30 -0
  298. data/lib/active_record/type/serialized.rb +76 -0
  299. data/lib/active_record/type/text.rb +11 -0
  300. data/lib/active_record/type/time.rb +35 -0
  301. data/lib/active_record/type/type_map.rb +58 -0
  302. data/lib/active_record/type/unsigned_integer.rb +16 -0
  303. data/lib/active_record/type.rb +83 -0
  304. data/lib/active_record/type_caster/connection.rb +33 -0
  305. data/lib/active_record/type_caster/map.rb +23 -0
  306. data/lib/active_record/type_caster.rb +9 -0
  307. data/lib/active_record/validations/absence.rb +25 -0
  308. data/lib/active_record/validations/associated.rb +65 -0
  309. data/lib/active_record/validations/length.rb +26 -0
  310. data/lib/active_record/validations/numericality.rb +36 -0
  311. data/lib/active_record/validations/presence.rb +45 -0
  312. data/lib/active_record/validations/uniqueness.rb +295 -0
  313. data/lib/active_record/validations.rb +101 -0
  314. data/lib/active_record/version.rb +10 -0
  315. data/lib/active_record.rb +616 -0
  316. data/lib/arel/alias_predication.rb +9 -0
  317. data/lib/arel/attributes/attribute.rb +33 -0
  318. data/lib/arel/collectors/bind.rb +31 -0
  319. data/lib/arel/collectors/composite.rb +46 -0
  320. data/lib/arel/collectors/plain_string.rb +20 -0
  321. data/lib/arel/collectors/sql_string.rb +27 -0
  322. data/lib/arel/collectors/substitute_binds.rb +35 -0
  323. data/lib/arel/crud.rb +48 -0
  324. data/lib/arel/delete_manager.rb +32 -0
  325. data/lib/arel/errors.rb +19 -0
  326. data/lib/arel/expressions.rb +29 -0
  327. data/lib/arel/factory_methods.rb +53 -0
  328. data/lib/arel/filter_predications.rb +9 -0
  329. data/lib/arel/insert_manager.rb +48 -0
  330. data/lib/arel/math.rb +45 -0
  331. data/lib/arel/nodes/ascending.rb +23 -0
  332. data/lib/arel/nodes/binary.rb +125 -0
  333. data/lib/arel/nodes/bind_param.rb +44 -0
  334. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  335. data/lib/arel/nodes/case.rb +55 -0
  336. data/lib/arel/nodes/casted.rb +62 -0
  337. data/lib/arel/nodes/comment.rb +29 -0
  338. data/lib/arel/nodes/count.rb +12 -0
  339. data/lib/arel/nodes/cte.rb +36 -0
  340. data/lib/arel/nodes/delete_statement.rb +44 -0
  341. data/lib/arel/nodes/descending.rb +23 -0
  342. data/lib/arel/nodes/equality.rb +15 -0
  343. data/lib/arel/nodes/extract.rb +24 -0
  344. data/lib/arel/nodes/false.rb +16 -0
  345. data/lib/arel/nodes/filter.rb +10 -0
  346. data/lib/arel/nodes/fragments.rb +35 -0
  347. data/lib/arel/nodes/full_outer_join.rb +8 -0
  348. data/lib/arel/nodes/function.rb +45 -0
  349. data/lib/arel/nodes/grouping.rb +11 -0
  350. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  351. data/lib/arel/nodes/in.rb +15 -0
  352. data/lib/arel/nodes/infix_operation.rb +92 -0
  353. data/lib/arel/nodes/inner_join.rb +8 -0
  354. data/lib/arel/nodes/insert_statement.rb +37 -0
  355. data/lib/arel/nodes/join_source.rb +20 -0
  356. data/lib/arel/nodes/leading_join.rb +8 -0
  357. data/lib/arel/nodes/matches.rb +18 -0
  358. data/lib/arel/nodes/named_function.rb +23 -0
  359. data/lib/arel/nodes/nary.rb +39 -0
  360. data/lib/arel/nodes/node.rb +161 -0
  361. data/lib/arel/nodes/node_expression.rb +13 -0
  362. data/lib/arel/nodes/ordering.rb +27 -0
  363. data/lib/arel/nodes/outer_join.rb +8 -0
  364. data/lib/arel/nodes/over.rb +15 -0
  365. data/lib/arel/nodes/regexp.rb +16 -0
  366. data/lib/arel/nodes/right_outer_join.rb +8 -0
  367. data/lib/arel/nodes/select_core.rb +67 -0
  368. data/lib/arel/nodes/select_statement.rb +41 -0
  369. data/lib/arel/nodes/sql_literal.rb +32 -0
  370. data/lib/arel/nodes/string_join.rb +11 -0
  371. data/lib/arel/nodes/table_alias.rb +35 -0
  372. data/lib/arel/nodes/terminal.rb +16 -0
  373. data/lib/arel/nodes/true.rb +16 -0
  374. data/lib/arel/nodes/unary.rb +44 -0
  375. data/lib/arel/nodes/unary_operation.rb +20 -0
  376. data/lib/arel/nodes/unqualified_column.rb +22 -0
  377. data/lib/arel/nodes/update_statement.rb +46 -0
  378. data/lib/arel/nodes/values_list.rb +9 -0
  379. data/lib/arel/nodes/window.rb +126 -0
  380. data/lib/arel/nodes/with.rb +11 -0
  381. data/lib/arel/nodes.rb +75 -0
  382. data/lib/arel/order_predications.rb +13 -0
  383. data/lib/arel/predications.rb +260 -0
  384. data/lib/arel/select_manager.rb +276 -0
  385. data/lib/arel/table.rb +121 -0
  386. data/lib/arel/tree_manager.rb +65 -0
  387. data/lib/arel/update_manager.rb +49 -0
  388. data/lib/arel/visitors/dot.rb +299 -0
  389. data/lib/arel/visitors/mysql.rb +111 -0
  390. data/lib/arel/visitors/postgresql.rb +99 -0
  391. data/lib/arel/visitors/sqlite.rb +38 -0
  392. data/lib/arel/visitors/to_sql.rb +1033 -0
  393. data/lib/arel/visitors/visitor.rb +45 -0
  394. data/lib/arel/visitors.rb +13 -0
  395. data/lib/arel/window_predications.rb +9 -0
  396. data/lib/arel.rb +73 -0
  397. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  398. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  399. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  400. data/lib/rails/generators/active_record/migration/migration_generator.rb +76 -0
  401. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +29 -0
  402. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  403. data/lib/rails/generators/active_record/migration.rb +54 -0
  404. data/lib/rails/generators/active_record/model/USAGE +113 -0
  405. data/lib/rails/generators/active_record/model/model_generator.rb +94 -0
  406. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  407. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  408. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  409. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  410. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  411. data/lib/rails/generators/active_record.rb +19 -0
  412. metadata +505 -0
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+
5
+ module ActiveRecord
6
+ module AttributeMethods
7
+ # = Active Record Attribute Methods Primary Key
8
+ module PrimaryKey
9
+ extend ActiveSupport::Concern
10
+
11
+ # Returns this record's primary key value wrapped in an array if one is
12
+ # available.
13
+ def to_key
14
+ key = id
15
+ Array(key) if key
16
+ end
17
+
18
+ # Returns the primary key column's value. If the primary key is composite,
19
+ # returns an array of the primary key column values.
20
+ def id
21
+ _read_attribute(@primary_key)
22
+ end
23
+
24
+ def primary_key_values_present? # :nodoc:
25
+ !!id
26
+ end
27
+
28
+ # Sets the primary key column's value. If the primary key is composite,
29
+ # raises TypeError when the set value not enumerable.
30
+ def id=(value)
31
+ _write_attribute(@primary_key, value)
32
+ end
33
+
34
+ # Queries the primary key column's value. If the primary key is composite,
35
+ # all primary key column values must be queryable.
36
+ def id?
37
+ _query_attribute(@primary_key)
38
+ end
39
+
40
+ # Returns the primary key column's value before type cast. If the primary key is composite,
41
+ # returns an array of primary key column values before type cast.
42
+ def id_before_type_cast
43
+ attribute_before_type_cast(@primary_key)
44
+ end
45
+
46
+ # Returns the primary key column's previous value. If the primary key is composite,
47
+ # returns an array of primary key column previous values.
48
+ def id_was
49
+ attribute_was(@primary_key)
50
+ end
51
+
52
+ # Returns the primary key column's value from the database. If the primary key is composite,
53
+ # returns an array of primary key column values from database.
54
+ def id_in_database
55
+ attribute_in_database(@primary_key)
56
+ end
57
+
58
+ def id_for_database # :nodoc:
59
+ @attributes[@primary_key].value_for_database
60
+ end
61
+
62
+ private
63
+ def attribute_method?(attr_name)
64
+ attr_name == "id" || super
65
+ end
66
+
67
+ module ClassMethods
68
+ ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was id_in_database id_for_database).to_set
69
+ PRIMARY_KEY_NOT_SET = BasicObject.new
70
+
71
+ def instance_method_already_implemented?(method_name)
72
+ super || primary_key && ID_ATTRIBUTE_METHODS.include?(method_name)
73
+ end
74
+
75
+ def dangerous_attribute_method?(method_name)
76
+ super && !ID_ATTRIBUTE_METHODS.include?(method_name)
77
+ end
78
+
79
+ # Defines the primary key field -- can be overridden in subclasses.
80
+ # Overwriting will negate any effect of the +primary_key_prefix_type+
81
+ # setting, though.
82
+ def primary_key
83
+ reset_primary_key if PRIMARY_KEY_NOT_SET.equal?(@primary_key)
84
+ @primary_key
85
+ end
86
+
87
+ def composite_primary_key? # :nodoc:
88
+ reset_primary_key if PRIMARY_KEY_NOT_SET.equal?(@primary_key)
89
+ @composite_primary_key
90
+ end
91
+
92
+ # Returns a quoted version of the primary key name, used to construct
93
+ # SQL statements.
94
+ def quoted_primary_key
95
+ @quoted_primary_key ||= adapter_class.quote_column_name(primary_key)
96
+ end
97
+
98
+ def reset_primary_key # :nodoc:
99
+ if base_class?
100
+ self.primary_key = get_primary_key(base_class.name)
101
+ else
102
+ self.primary_key = base_class.primary_key
103
+ end
104
+ end
105
+
106
+ def get_primary_key(base_name) # :nodoc:
107
+ if base_name && primary_key_prefix_type == :table_name
108
+ base_name.foreign_key(false)
109
+ elsif base_name && primary_key_prefix_type == :table_name_with_underscore
110
+ base_name.foreign_key
111
+ elsif ActiveRecord::Base != self && table_exists?
112
+ schema_cache.primary_keys(table_name)
113
+ else
114
+ "id"
115
+ end
116
+ end
117
+
118
+ # Sets the name of the primary key column.
119
+ #
120
+ # class Project < ActiveRecord::Base
121
+ # self.primary_key = 'sysid'
122
+ # end
123
+ #
124
+ # You can also define the #primary_key method yourself:
125
+ #
126
+ # class Project < ActiveRecord::Base
127
+ # def self.primary_key
128
+ # 'foo_' + super
129
+ # end
130
+ # end
131
+ #
132
+ # Project.primary_key # => "foo_id"
133
+ def primary_key=(value)
134
+ @primary_key = if value.is_a?(Array)
135
+ @composite_primary_key = true
136
+ include CompositePrimaryKey
137
+ @primary_key = value.map { |v| -v.to_s }.freeze
138
+ elsif value
139
+ -value.to_s
140
+ end
141
+ @quoted_primary_key = nil
142
+ @attributes_builder = nil
143
+ end
144
+
145
+ private
146
+ def inherited(base)
147
+ super
148
+ base.class_eval do
149
+ @primary_key = PRIMARY_KEY_NOT_SET
150
+ @composite_primary_key = false
151
+ @quoted_primary_key = nil
152
+ @attributes_builder = nil
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module AttributeMethods
5
+ # = Active Record Attribute Methods \Query
6
+ module Query
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ attribute_method_suffix "?", parameters: false
11
+ end
12
+
13
+ def query_attribute(attr_name)
14
+ value = self.public_send(attr_name)
15
+
16
+ query_cast_attribute(attr_name, value)
17
+ end
18
+
19
+ def _query_attribute(attr_name) # :nodoc:
20
+ value = self._read_attribute(attr_name.to_s)
21
+
22
+ query_cast_attribute(attr_name, value)
23
+ end
24
+
25
+ alias :attribute? :query_attribute
26
+ private :attribute?
27
+
28
+ private
29
+ def query_cast_attribute(attr_name, value)
30
+ case value
31
+ when true then true
32
+ when false, nil then false
33
+ else
34
+ if !type_for_attribute(attr_name) { false }
35
+ if Numeric === value || !value.match?(/[^0-9]/)
36
+ !value.to_i.zero?
37
+ else
38
+ return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value)
39
+ !value.blank?
40
+ end
41
+ elsif value.respond_to?(:zero?)
42
+ !value.zero?
43
+ else
44
+ !value.blank?
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module AttributeMethods
5
+ # = Active Record Attribute Methods \Read
6
+ module Read
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods # :nodoc:
10
+ private
11
+ def define_method_attribute(canonical_name, owner:, as: canonical_name)
12
+ ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
13
+ owner, canonical_name
14
+ ) do |temp_method_name, attr_name_expr|
15
+ owner.define_cached_method(temp_method_name, as: as, namespace: :active_record) do |batch|
16
+ batch <<
17
+ "def #{temp_method_name}" <<
18
+ " _read_attribute(#{attr_name_expr}) { |n| missing_attribute(n, caller) }" <<
19
+ "end"
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # Returns the value of the attribute identified by +attr_name+ after it
26
+ # has been type cast. For example, a date attribute will cast "2004-12-12"
27
+ # to <tt>Date.new(2004, 12, 12)</tt>. (For information about specific type
28
+ # casting behavior, see the types under ActiveModel::Type.)
29
+ def read_attribute(attr_name, &block)
30
+ name = attr_name.to_s
31
+ name = self.class.attribute_aliases[name] || name
32
+
33
+ @attributes.fetch_value(name, &block)
34
+ end
35
+
36
+ # This method exists to avoid the expensive primary_key check internally, without
37
+ # breaking compatibility with the read_attribute API
38
+ def _read_attribute(attr_name, &block) # :nodoc:
39
+ @attributes.fetch_value(attr_name, &block)
40
+ end
41
+
42
+ alias :attribute :_read_attribute
43
+ private :attribute
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module AttributeMethods
5
+ # = Active Record Attribute Methods \Serialization
6
+ module Serialization
7
+ extend ActiveSupport::Concern
8
+
9
+ class ColumnNotSerializableError < StandardError
10
+ def initialize(name, type)
11
+ super <<~EOS
12
+ Column `#{name}` of type #{type.class} does not support `serialize` feature.
13
+ Usually it means that you are trying to use `serialize`
14
+ on a column that already implements serialization natively.
15
+ EOS
16
+ end
17
+ end
18
+
19
+ included do
20
+ class_attribute :default_column_serializer, instance_accessor: false, default: Coders::YAMLColumn
21
+ end
22
+
23
+ module ClassMethods
24
+ # If you have an attribute that needs to be saved to the database as a
25
+ # serialized object, and retrieved by deserializing into the same object,
26
+ # then specify the name of that attribute using this method and serialization
27
+ # will be handled automatically.
28
+ #
29
+ # The serialization format may be YAML, JSON, or any custom format using a
30
+ # custom coder class.
31
+ #
32
+ # Keep in mind that database adapters handle certain serialization tasks
33
+ # for you. For instance: +json+ and +jsonb+ types in PostgreSQL will be
34
+ # converted between JSON object/array syntax and Ruby +Hash+ or +Array+
35
+ # objects transparently. There is no need to use #serialize in this
36
+ # case.
37
+ #
38
+ # For more complex cases, such as conversion to or from your application
39
+ # domain objects, consider using the ActiveRecord::Attributes API.
40
+ #
41
+ # ==== Parameters
42
+ #
43
+ # * +attr_name+ - The name of the attribute to serialize.
44
+ # * +coder+ The serializer implementation to use, e.g. +JSON+.
45
+ # * The attribute value will be serialized
46
+ # using the coder's <tt>dump(value)</tt> method, and will be
47
+ # deserialized using the coder's <tt>load(string)</tt> method. The
48
+ # +dump+ method may return +nil+ to serialize the value as +NULL+.
49
+ # * +type+ - Optional. What the type of the serialized object should be.
50
+ # * Attempting to serialize another type will raise an
51
+ # ActiveRecord::SerializationTypeMismatch error.
52
+ # * If the column is +NULL+ or starting from a new record, the default value
53
+ # will set to +type.new+
54
+ # * +yaml+ - Optional. Yaml specific options. The allowed config is:
55
+ # * +:permitted_classes+ - +Array+ with the permitted classes.
56
+ # * +:unsafe_load+ - Unsafely load YAML blobs, allow YAML to load any class.
57
+ #
58
+ # ==== Options
59
+ #
60
+ # * +:default+ - The default value to use when no value is provided. If
61
+ # this option is not passed, the previous default value (if any) will
62
+ # be used. Otherwise, the default will be +nil+.
63
+ #
64
+ # ==== Choosing a serializer
65
+ #
66
+ # While any serialization format can be used, it is recommended to carefully
67
+ # evaluate the properties of a serializer before using it, as migrating to
68
+ # another format later on can be difficult.
69
+ #
70
+ # ===== Avoid accepting arbitrary types
71
+ #
72
+ # When serializing data in a column, it is heavily recommended to make sure
73
+ # only expected types will be serialized. For instance some serializer like
74
+ # +Marshal+ or +YAML+ are capable of serializing almost any Ruby object.
75
+ #
76
+ # This can lead to unexpected types being serialized, and it is important
77
+ # that type serialization remains backward and forward compatible as long
78
+ # as some database records still contain these serialized types.
79
+ #
80
+ # class Address
81
+ # def initialize(line, city, country)
82
+ # @line, @city, @country = line, city, country
83
+ # end
84
+ # end
85
+ #
86
+ # In the above example, if any of the +Address+ attributes is renamed,
87
+ # instances that were persisted before the change will be loaded with the
88
+ # old attributes. This problem is even worse when the serialized type comes
89
+ # from a dependency which doesn't expect to be serialized this way and may
90
+ # change its internal representation without notice.
91
+ #
92
+ # As such, it is heavily recommended to instead convert these objects into
93
+ # primitives of the serialization format, for example:
94
+ #
95
+ # class Address
96
+ # attr_reader :line, :city, :country
97
+ #
98
+ # def self.load(payload)
99
+ # data = YAML.safe_load(payload)
100
+ # new(data["line"], data["city"], data["country"])
101
+ # end
102
+ #
103
+ # def self.dump(address)
104
+ # YAML.safe_dump(
105
+ # "line" => address.line,
106
+ # "city" => address.city,
107
+ # "country" => address.country,
108
+ # )
109
+ # end
110
+ #
111
+ # def initialize(line, city, country)
112
+ # @line, @city, @country = line, city, country
113
+ # end
114
+ # end
115
+ #
116
+ # class User < ActiveRecord::Base
117
+ # serialize :address, coder: Address
118
+ # end
119
+ #
120
+ # This pattern allows to be more deliberate about what is serialized, and
121
+ # to evolve the format in a backward compatible way.
122
+ #
123
+ # ===== Ensure serialization stability
124
+ #
125
+ # Some serialization methods may accept some types they don't support by
126
+ # silently casting them to other types. This can cause bugs when the
127
+ # data is deserialized.
128
+ #
129
+ # For instance the +JSON+ serializer provided in the standard library will
130
+ # silently cast unsupported types to +String+:
131
+ #
132
+ # >> JSON.parse(JSON.dump(Struct.new(:foo)))
133
+ # => "#<Class:0x000000013090b4c0>"
134
+ #
135
+ # ==== Examples
136
+ #
137
+ # ===== Serialize the +preferences+ attribute using YAML
138
+ #
139
+ # class User < ActiveRecord::Base
140
+ # serialize :preferences, coder: YAML
141
+ # end
142
+ #
143
+ # ===== Serialize the +preferences+ attribute using JSON
144
+ #
145
+ # class User < ActiveRecord::Base
146
+ # serialize :preferences, coder: JSON
147
+ # end
148
+ #
149
+ # ===== Serialize the +preferences+ +Hash+ using YAML
150
+ #
151
+ # class User < ActiveRecord::Base
152
+ # serialize :preferences, type: Hash, coder: YAML
153
+ # end
154
+ #
155
+ # ===== Serializes +preferences+ to YAML, permitting select classes
156
+ #
157
+ # class User < ActiveRecord::Base
158
+ # serialize :preferences, coder: YAML, yaml: { permitted_classes: [Symbol, Time] }
159
+ # end
160
+ #
161
+ # ===== Serialize the +preferences+ attribute using a custom coder
162
+ #
163
+ # class Rot13JSON
164
+ # def self.rot13(string)
165
+ # string.tr("a-zA-Z", "n-za-mN-ZA-M")
166
+ # end
167
+ #
168
+ # # Serializes an attribute value to a string that will be stored in the database.
169
+ # def self.dump(value)
170
+ # rot13(ActiveSupport::JSON.dump(value))
171
+ # end
172
+ #
173
+ # # Deserializes a string from the database to an attribute value.
174
+ # def self.load(string)
175
+ # ActiveSupport::JSON.load(rot13(string))
176
+ # end
177
+ # end
178
+ #
179
+ # class User < ActiveRecord::Base
180
+ # serialize :preferences, coder: Rot13JSON
181
+ # end
182
+ #
183
+ def serialize(attr_name, coder: nil, type: Object, yaml: {}, **options)
184
+ coder ||= default_column_serializer
185
+ unless coder
186
+ raise ArgumentError, <<~MSG.squish
187
+ missing keyword: :coder
188
+
189
+ If no default coder is configured, a coder must be provided to `serialize`.
190
+ MSG
191
+ end
192
+
193
+ column_serializer = build_column_serializer(attr_name, coder, type, yaml)
194
+
195
+ attribute(attr_name, **options)
196
+
197
+ decorate_attributes([attr_name]) do |attr_name, cast_type|
198
+ if type_incompatible_with_serialize?(cast_type, coder, type)
199
+ raise ColumnNotSerializableError.new(attr_name, cast_type)
200
+ end
201
+
202
+ cast_type = cast_type.subtype if Type::Serialized === cast_type
203
+ Type::Serialized.new(cast_type, column_serializer)
204
+ end
205
+ end
206
+
207
+ private
208
+ def build_column_serializer(attr_name, coder, type, yaml = nil)
209
+ # When ::JSON is used, force it to go through the Active Support JSON encoder
210
+ # to ensure special objects (e.g. Active Record models) are dumped correctly
211
+ # using the #as_json hook.
212
+ coder = Coders::JSON if coder == ::JSON
213
+
214
+ if coder == ::YAML || coder == Coders::YAMLColumn
215
+ Coders::YAMLColumn.new(attr_name, type, **(yaml || {}))
216
+ elsif coder.respond_to?(:new) && !coder.respond_to?(:load)
217
+ coder.new(attr_name, type)
218
+ elsif type && type != Object
219
+ Coders::ColumnSerializer.new(attr_name, coder, type)
220
+ else
221
+ coder
222
+ end
223
+ end
224
+
225
+ def type_incompatible_with_serialize?(cast_type, coder, type)
226
+ cast_type.is_a?(ActiveRecord::Type::Json) && coder == ::JSON ||
227
+ cast_type.respond_to?(:type_cast_array, true) && type == ::Array
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/try"
4
+
5
+ module ActiveRecord
6
+ module AttributeMethods
7
+ module TimeZoneConversion
8
+ class TimeZoneConverter < DelegateClass(Type::Value) # :nodoc:
9
+ def self.new(subtype)
10
+ self === subtype ? subtype : super
11
+ end
12
+
13
+ def deserialize(value)
14
+ convert_time_to_time_zone(super)
15
+ end
16
+
17
+ def cast(value)
18
+ return if value.nil?
19
+
20
+ if value.is_a?(Hash)
21
+ set_time_zone_without_conversion(super)
22
+ elsif value.respond_to?(:in_time_zone)
23
+ begin
24
+ super(user_input_in_time_zone(value)) || super
25
+ rescue ArgumentError
26
+ nil
27
+ end
28
+ elsif value.respond_to?(:infinite?) && value.infinite?
29
+ value
30
+ else
31
+ map_avoiding_infinite_recursion(super) { |v| cast(v) }
32
+ end
33
+ end
34
+
35
+ def ==(other)
36
+ other.is_a?(self.class) && __getobj__ == other.__getobj__
37
+ end
38
+
39
+ private
40
+ def convert_time_to_time_zone(value)
41
+ return if value.nil?
42
+
43
+ if value.acts_like?(:time)
44
+ value.in_time_zone
45
+ elsif value.respond_to?(:infinite?) && value.infinite?
46
+ value
47
+ else
48
+ map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
49
+ end
50
+ end
51
+
52
+ def set_time_zone_without_conversion(value)
53
+ ::Time.zone.local_to_utc(value).try(:in_time_zone) if value
54
+ end
55
+
56
+ def map_avoiding_infinite_recursion(value)
57
+ map(value) do |v|
58
+ if value.equal?(v)
59
+ nil
60
+ else
61
+ yield(v)
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ extend ActiveSupport::Concern
68
+
69
+ included do
70
+ class_attribute :time_zone_aware_attributes, instance_writer: false, default: false
71
+ class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false, default: []
72
+ class_attribute :time_zone_aware_types, instance_writer: false, default: [ :datetime, :time ]
73
+ end
74
+
75
+ module ClassMethods # :nodoc:
76
+ private
77
+ def hook_attribute_type(name, cast_type)
78
+ if create_time_zone_conversion_attribute?(name, cast_type)
79
+ cast_type = TimeZoneConverter.new(cast_type)
80
+ end
81
+
82
+ super
83
+ end
84
+
85
+ def create_time_zone_conversion_attribute?(name, cast_type)
86
+ enabled_for_column = time_zone_aware_attributes &&
87
+ !skip_time_zone_conversion_for_attributes.include?(name.to_sym)
88
+
89
+ enabled_for_column && time_zone_aware_types.include?(cast_type.type)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module AttributeMethods
5
+ # = Active Record Attribute Methods \Write
6
+ module Write
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ attribute_method_suffix "=", parameters: "value"
11
+ end
12
+
13
+ module ClassMethods # :nodoc:
14
+ private
15
+ def define_method_attribute=(canonical_name, owner:, as: canonical_name)
16
+ ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
17
+ owner, canonical_name, writer: true,
18
+ ) do |temp_method_name, attr_name_expr|
19
+ owner.define_cached_method(temp_method_name, as: "#{as}=", namespace: :active_record) do |batch|
20
+ batch <<
21
+ "def #{temp_method_name}(value)" <<
22
+ " _write_attribute(#{attr_name_expr}, value)" <<
23
+ "end"
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ # Updates the attribute identified by +attr_name+ using the specified
30
+ # +value+. The attribute value will be type cast upon being read.
31
+ def write_attribute(attr_name, value)
32
+ name = attr_name.to_s
33
+ name = self.class.attribute_aliases[name] || name
34
+
35
+ name = @primary_key if name == "id" && @primary_key
36
+ @attributes.write_from_user(name, value)
37
+ end
38
+
39
+ # This method exists to avoid the expensive primary_key check internally, without
40
+ # breaking compatibility with the write_attribute API
41
+ def _write_attribute(attr_name, value) # :nodoc:
42
+ @attributes.write_from_user(attr_name, value)
43
+ end
44
+
45
+ alias :attribute= :_write_attribute
46
+ private :attribute=
47
+ end
48
+ end
49
+ end