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,164 @@
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(ClothingItem.lease_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([], ClothingItem.lease_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(ClothingItem.lease_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"], ClothingItem.lease_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
+ @indexes.each do |i|
54
+ value = binds.shift
55
+ if ActiveModel::Attribute === value
56
+ value = value.value_for_database
57
+ end
58
+ val[i] = connection.quote(value)
59
+ end
60
+ val.join
61
+ end
62
+ end
63
+
64
+ class PartialQueryCollector
65
+ attr_accessor :preparable, :retryable
66
+
67
+ def initialize
68
+ @parts = []
69
+ @binds = []
70
+ end
71
+
72
+ def <<(str)
73
+ @parts << str
74
+ self
75
+ end
76
+
77
+ def add_bind(obj)
78
+ @binds << obj
79
+ @parts << Substitute.new
80
+ self
81
+ end
82
+
83
+ def add_binds(binds, proc_for_binds = nil)
84
+ @binds.concat proc_for_binds ? binds.map(&proc_for_binds) : binds
85
+ binds.size.times do |i|
86
+ @parts << ", " unless i == 0
87
+ @parts << Substitute.new
88
+ end
89
+ self
90
+ end
91
+
92
+ def value
93
+ [@parts, @binds]
94
+ end
95
+ end
96
+
97
+ def self.query(sql)
98
+ Query.new(sql)
99
+ end
100
+
101
+ def self.partial_query(values)
102
+ PartialQuery.new(values)
103
+ end
104
+
105
+ def self.partial_query_collector
106
+ PartialQueryCollector.new
107
+ end
108
+
109
+ class Params # :nodoc:
110
+ def bind; Substitute.new; end
111
+ end
112
+
113
+ class BindMap # :nodoc:
114
+ def initialize(bound_attributes)
115
+ @indexes = []
116
+ @bound_attributes = bound_attributes
117
+
118
+ bound_attributes.each_with_index do |attr, i|
119
+ if ActiveModel::Attribute === attr && Substitute === attr.value
120
+ @indexes << i
121
+ end
122
+ end
123
+ end
124
+
125
+ def bind(values)
126
+ bas = @bound_attributes.dup
127
+ @indexes.each_with_index { |offset, i| bas[offset] = bas[offset].with_cast_value(values[i]) }
128
+ bas
129
+ end
130
+ end
131
+
132
+ def self.create(connection, callable = nil, &block)
133
+ relation = (callable || block).call Params.new
134
+ query_builder, binds = connection.cacheable_query(self, relation.arel)
135
+ bind_map = BindMap.new(binds)
136
+ new(query_builder, bind_map, relation.model)
137
+ end
138
+
139
+ def initialize(query_builder, bind_map, model)
140
+ @query_builder = query_builder
141
+ @bind_map = bind_map
142
+ @model = model
143
+ end
144
+
145
+ def execute(params, connection, allow_retry: false, async: false, &block)
146
+ bind_values = @bind_map.bind params
147
+ sql = @query_builder.sql_for bind_values, connection
148
+
149
+ if async
150
+ @model.async_find_by_sql(sql, bind_values, preparable: true, allow_retry: allow_retry, &block)
151
+ else
152
+ @model.find_by_sql(sql, bind_values, preparable: true, allow_retry: allow_retry, &block)
153
+ end
154
+ rescue ::RangeError
155
+ async ? Promise.wrap([]) : []
156
+ end
157
+
158
+ def self.unsupported_value?(value)
159
+ case value
160
+ when NilClass, Array, Range, Hash, Relation, Base then true
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,299 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/indifferent_access"
4
+
5
+ module ActiveRecord
6
+ # = Active Record \Store
7
+ #
8
+ # Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.
9
+ # It's like a simple key/value store baked into your record when you don't care about being able to
10
+ # query that store outside the context of a single record.
11
+ #
12
+ # You can then declare accessors to this store that are then accessible just like any other attribute
13
+ # of the model. This is very helpful for easily exposing store keys to a form or elsewhere that's
14
+ # already built around just accessing attributes on the model.
15
+ #
16
+ # Every accessor comes with dirty tracking methods (+key_changed?+, +key_was+ and +key_change+) and
17
+ # methods to access the changes made during the last save (+saved_change_to_key?+, +saved_change_to_key+ and
18
+ # +key_before_last_save+).
19
+ #
20
+ # NOTE: There is no +key_will_change!+ method for accessors, use +store_will_change!+ instead.
21
+ #
22
+ # Make sure that you declare the database column used for the serialized store as a text, so there's
23
+ # plenty of room.
24
+ #
25
+ # You can set custom coder to encode/decode your serialized attributes to/from different formats.
26
+ # JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
27
+ #
28
+ # NOTE: If you are using structured database data types (e.g. PostgreSQL +hstore+/+json+, MySQL 5.7+
29
+ # +json+, or SQLite 3.38+ +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
30
+ # Simply use {.store_accessor}[rdoc-ref:ClassMethods#store_accessor] instead to generate
31
+ # the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
32
+ # using a symbol.
33
+ #
34
+ # NOTE: The default validations with the exception of +uniqueness+ will work.
35
+ # For example, if you want to check for +uniqueness+ with +hstore+ you will
36
+ # need to use a custom validation to handle it.
37
+ #
38
+ # Examples:
39
+ #
40
+ # class User < ActiveRecord::Base
41
+ # store :settings, accessors: [ :color, :homepage ], coder: JSON
42
+ # store :parent, accessors: [ :name ], coder: JSON, prefix: true
43
+ # store :spouse, accessors: [ :name ], coder: JSON, prefix: :partner
44
+ # store :settings, accessors: [ :two_factor_auth ], suffix: true
45
+ # store :settings, accessors: [ :login_retry ], suffix: :config
46
+ # end
47
+ #
48
+ # u = User.new(color: 'black', homepage: '37signals.com', parent_name: 'Mary', partner_name: 'Lily')
49
+ # u.color # Accessor stored attribute
50
+ # u.parent_name # Accessor stored attribute with prefix
51
+ # u.partner_name # Accessor stored attribute with custom prefix
52
+ # u.two_factor_auth_settings # Accessor stored attribute with suffix
53
+ # u.login_retry_config # Accessor stored attribute with custom suffix
54
+ # u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
55
+ #
56
+ # # There is no difference between strings and symbols for accessing custom attributes
57
+ # u.settings[:country] # => 'Denmark'
58
+ # u.settings['country'] # => 'Denmark'
59
+ #
60
+ # # Dirty tracking
61
+ # u.color = 'green'
62
+ # u.color_changed? # => true
63
+ # u.color_was # => 'black'
64
+ # u.color_change # => ['black', 'green']
65
+ #
66
+ # # Add additional accessors to an existing store through store_accessor
67
+ # class SuperUser < User
68
+ # store_accessor :settings, :privileges, :servants
69
+ # store_accessor :parent, :birthday, prefix: true
70
+ # store_accessor :settings, :secret_question, suffix: :config
71
+ # end
72
+ #
73
+ # The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
74
+ #
75
+ # User.stored_attributes[:settings] # => [:color, :homepage, :two_factor_auth, :login_retry]
76
+ #
77
+ # == Overwriting default accessors
78
+ #
79
+ # All stored values are automatically available through accessors on the Active Record
80
+ # object, but sometimes you want to specialize this behavior. This can be done by overwriting
81
+ # the default accessors (using the same name as the attribute) and calling <tt>super</tt>
82
+ # to actually change things.
83
+ #
84
+ # class Song < ActiveRecord::Base
85
+ # # Uses a stored integer to hold the volume adjustment of the song
86
+ # store :settings, accessors: [:volume_adjustment]
87
+ #
88
+ # def volume_adjustment=(decibels)
89
+ # super(decibels.to_i)
90
+ # end
91
+ #
92
+ # def volume_adjustment
93
+ # super.to_i
94
+ # end
95
+ # end
96
+ module Store
97
+ extend ActiveSupport::Concern
98
+
99
+ included do
100
+ class << self
101
+ attr_accessor :local_stored_attributes
102
+ end
103
+ end
104
+
105
+ module ClassMethods
106
+ def store(store_attribute, options = {})
107
+ coder = build_column_serializer(store_attribute, options[:coder], Object, options[:yaml])
108
+ serialize store_attribute, coder: IndifferentCoder.new(store_attribute, coder)
109
+ store_accessor(store_attribute, options[:accessors], **options.slice(:prefix, :suffix)) if options.has_key? :accessors
110
+ end
111
+
112
+ def store_accessor(store_attribute, *keys, prefix: nil, suffix: nil)
113
+ keys = keys.flatten
114
+
115
+ accessor_prefix =
116
+ case prefix
117
+ when String, Symbol
118
+ "#{prefix}_"
119
+ when TrueClass
120
+ "#{store_attribute}_"
121
+ else
122
+ ""
123
+ end
124
+ accessor_suffix =
125
+ case suffix
126
+ when String, Symbol
127
+ "_#{suffix}"
128
+ when TrueClass
129
+ "_#{store_attribute}"
130
+ else
131
+ ""
132
+ end
133
+
134
+ _store_accessors_module.module_eval do
135
+ keys.each do |key|
136
+ accessor_key = "#{accessor_prefix}#{key}#{accessor_suffix}"
137
+
138
+ define_method("#{accessor_key}=") do |value|
139
+ write_store_attribute(store_attribute, key, value)
140
+ end
141
+
142
+ define_method(accessor_key) do
143
+ read_store_attribute(store_attribute, key)
144
+ end
145
+
146
+ define_method("#{accessor_key}_changed?") do
147
+ return false unless attribute_changed?(store_attribute)
148
+ prev_store, new_store = changes[store_attribute]
149
+ prev_store&.dig(key) != new_store&.dig(key)
150
+ end
151
+
152
+ define_method("#{accessor_key}_change") do
153
+ return unless attribute_changed?(store_attribute)
154
+ prev_store, new_store = changes[store_attribute]
155
+ [prev_store&.dig(key), new_store&.dig(key)]
156
+ end
157
+
158
+ define_method("#{accessor_key}_was") do
159
+ return unless attribute_changed?(store_attribute)
160
+ prev_store, _new_store = changes[store_attribute]
161
+ prev_store&.dig(key)
162
+ end
163
+
164
+ define_method("saved_change_to_#{accessor_key}?") do
165
+ return false unless saved_change_to_attribute?(store_attribute)
166
+ prev_store, new_store = saved_changes[store_attribute]
167
+ prev_store&.dig(key) != new_store&.dig(key)
168
+ end
169
+
170
+ define_method("saved_change_to_#{accessor_key}") do
171
+ return unless saved_change_to_attribute?(store_attribute)
172
+ prev_store, new_store = saved_changes[store_attribute]
173
+ [prev_store&.dig(key), new_store&.dig(key)]
174
+ end
175
+
176
+ define_method("#{accessor_key}_before_last_save") do
177
+ return unless saved_change_to_attribute?(store_attribute)
178
+ prev_store, _new_store = saved_changes[store_attribute]
179
+ prev_store&.dig(key)
180
+ end
181
+ end
182
+ end
183
+
184
+ # assign new store attribute and create new hash to ensure that each class in the hierarchy
185
+ # has its own hash of stored attributes.
186
+ self.local_stored_attributes ||= {}
187
+ self.local_stored_attributes[store_attribute] ||= []
188
+ self.local_stored_attributes[store_attribute] |= keys
189
+ end
190
+
191
+ def _store_accessors_module # :nodoc:
192
+ @_store_accessors_module ||= begin
193
+ mod = Module.new
194
+ include mod
195
+ mod
196
+ end
197
+ end
198
+
199
+ def stored_attributes
200
+ parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
201
+ if local_stored_attributes
202
+ parent.merge!(local_stored_attributes) { |k, a, b| a | b }
203
+ end
204
+ parent
205
+ end
206
+ end
207
+
208
+ private
209
+ def read_store_attribute(store_attribute, key) # :doc:
210
+ accessor = store_accessor_for(store_attribute)
211
+ accessor.read(self, store_attribute, key)
212
+ end
213
+
214
+ def write_store_attribute(store_attribute, key, value) # :doc:
215
+ accessor = store_accessor_for(store_attribute)
216
+ accessor.write(self, store_attribute, key, value)
217
+ end
218
+
219
+ def store_accessor_for(store_attribute)
220
+ type_for_attribute(store_attribute).tap do |type|
221
+ unless type.respond_to?(:accessor)
222
+ raise ConfigurationError, "the column '#{store_attribute}' has not been configured as a store. Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your database supports it, use a structured column type like hstore or json."
223
+ end
224
+ end.accessor
225
+ end
226
+
227
+ class HashAccessor # :nodoc:
228
+ def self.read(object, attribute, key)
229
+ prepare(object, attribute)
230
+ object.public_send(attribute)[key]
231
+ end
232
+
233
+ def self.write(object, attribute, key, value)
234
+ prepare(object, attribute)
235
+ object.public_send(attribute)[key] = value if value != read(object, attribute, key)
236
+ end
237
+
238
+ def self.prepare(object, attribute)
239
+ object.public_send :"#{attribute}=", {} unless object.send(attribute)
240
+ end
241
+ end
242
+
243
+ class StringKeyedHashAccessor < HashAccessor # :nodoc:
244
+ def self.read(object, attribute, key)
245
+ super object, attribute, key.to_s
246
+ end
247
+
248
+ def self.write(object, attribute, key, value)
249
+ super object, attribute, key.to_s, value
250
+ end
251
+ end
252
+
253
+ class IndifferentHashAccessor < ActiveRecord::Store::HashAccessor # :nodoc:
254
+ def self.prepare(object, store_attribute)
255
+ attribute = object.send(store_attribute)
256
+ unless attribute.is_a?(ActiveSupport::HashWithIndifferentAccess)
257
+ attribute = IndifferentCoder.as_indifferent_hash(attribute)
258
+ object.public_send :"#{store_attribute}=", attribute
259
+ end
260
+ attribute
261
+ end
262
+ end
263
+
264
+ class IndifferentCoder # :nodoc:
265
+ def initialize(attr_name, coder_or_class_name)
266
+ @coder =
267
+ if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
268
+ coder_or_class_name
269
+ else
270
+ ActiveRecord::Coders::YAMLColumn.new(attr_name, coder_or_class_name || Object)
271
+ end
272
+ end
273
+
274
+ def dump(obj)
275
+ @coder.dump as_regular_hash(obj)
276
+ end
277
+
278
+ def load(yaml)
279
+ self.class.as_indifferent_hash(@coder.load(yaml || ""))
280
+ end
281
+
282
+ def self.as_indifferent_hash(obj)
283
+ case obj
284
+ when ActiveSupport::HashWithIndifferentAccess
285
+ obj
286
+ when Hash
287
+ obj.with_indifferent_access
288
+ else
289
+ ActiveSupport::HashWithIndifferentAccess.new
290
+ end
291
+ end
292
+
293
+ private
294
+ def as_regular_hash(obj)
295
+ obj.respond_to?(:to_hash) ? obj.to_hash : {}
296
+ end
297
+ end
298
+ end
299
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # = Active Record \Suppressor
5
+ #
6
+ # ActiveRecord::Suppressor prevents the receiver from being saved during
7
+ # a given block.
8
+ #
9
+ # For example, here's a pattern of creating notifications when new comments
10
+ # are posted. (The notification may in turn trigger an email, a push
11
+ # notification, or just appear in the UI somewhere):
12
+ #
13
+ # class Comment < ActiveRecord::Base
14
+ # belongs_to :commentable, polymorphic: true
15
+ # after_create -> { Notification.create! comment: self,
16
+ # recipients: commentable.recipients }
17
+ # end
18
+ #
19
+ # That's what you want the bulk of the time. New comment creates a new
20
+ # Notification. But there may well be off cases, like copying a commentable
21
+ # and its comments, where you don't want that. So you'd have a concern
22
+ # something like this:
23
+ #
24
+ # module Copyable
25
+ # def copy_to(destination)
26
+ # Notification.suppress do
27
+ # # Copy logic that creates new comments that we do not want
28
+ # # triggering notifications.
29
+ # end
30
+ # end
31
+ # end
32
+ module Suppressor
33
+ extend ActiveSupport::Concern
34
+
35
+ class << self
36
+ def registry # :nodoc:
37
+ ActiveSupport::IsolatedExecutionState[:active_record_suppressor_registry] ||= {}
38
+ end
39
+ end
40
+
41
+ module ClassMethods
42
+ def suppress(&block)
43
+ previous_state = Suppressor.registry[name]
44
+ Suppressor.registry[name] = true
45
+ yield
46
+ ensure
47
+ Suppressor.registry[name] = previous_state
48
+ end
49
+ end
50
+
51
+ def save(**) # :nodoc:
52
+ Suppressor.registry[self.class.name] ? true : super
53
+ end
54
+
55
+ def save!(**) # :nodoc:
56
+ Suppressor.registry[self.class.name] ? true : super
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class TableMetadata # :nodoc:
5
+ delegate :join_primary_key, :join_primary_type, :join_foreign_key, :join_foreign_type, to: :reflection
6
+
7
+ def initialize(klass, arel_table, reflection = nil)
8
+ @klass = klass
9
+ @arel_table = arel_table
10
+ @reflection = reflection
11
+ end
12
+
13
+ def primary_key
14
+ klass&.primary_key
15
+ end
16
+
17
+ def type(column_name)
18
+ arel_table.type_for_attribute(column_name)
19
+ end
20
+
21
+ def has_column?(column_name)
22
+ klass&.columns_hash&.key?(column_name)
23
+ end
24
+
25
+ def associated_with?(table_name)
26
+ klass&._reflect_on_association(table_name)
27
+ end
28
+
29
+ def associated_table(table_name)
30
+ reflection = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.singularize)
31
+
32
+ if !reflection && table_name == arel_table.name
33
+ return self
34
+ end
35
+
36
+ if reflection
37
+ association_klass = reflection.klass unless reflection.polymorphic?
38
+ elsif block_given?
39
+ association_klass = yield table_name
40
+ end
41
+
42
+ if association_klass
43
+ arel_table = association_klass.arel_table
44
+ arel_table = arel_table.alias(table_name) if arel_table.name != table_name
45
+ TableMetadata.new(association_klass, arel_table, reflection)
46
+ else
47
+ type_caster = TypeCaster::Connection.new(klass, table_name)
48
+ arel_table = Arel::Table.new(table_name, type_caster: type_caster)
49
+ TableMetadata.new(nil, arel_table, reflection)
50
+ end
51
+ end
52
+
53
+ def polymorphic_association?
54
+ reflection&.polymorphic?
55
+ end
56
+
57
+ def polymorphic_name_association
58
+ reflection&.polymorphic_name
59
+ end
60
+
61
+ def through_association?
62
+ reflection&.through_reflection?
63
+ end
64
+
65
+ def reflect_on_aggregation(aggregation_name)
66
+ klass&.reflect_on_aggregation(aggregation_name)
67
+ end
68
+ alias :aggregated_with? :reflect_on_aggregation
69
+
70
+ def predicate_builder
71
+ if klass
72
+ predicate_builder = klass.predicate_builder.dup
73
+ predicate_builder.instance_variable_set(:@table, self)
74
+ predicate_builder
75
+ else
76
+ PredicateBuilder.new(self)
77
+ end
78
+ end
79
+
80
+ attr_reader :arel_table
81
+
82
+ private
83
+ attr_reader :klass, :reflection
84
+ end
85
+ end