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,535 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/enumerable"
4
+
5
+ module ActiveRecord
6
+ module Associations
7
+ # = Active Record Association Collection
8
+ #
9
+ # CollectionAssociation is an abstract class that provides common stuff to
10
+ # ease the implementation of association proxies that represent
11
+ # collections. See the class hierarchy in Association.
12
+ #
13
+ # CollectionAssociation:
14
+ # HasManyAssociation => has_many
15
+ # HasManyThroughAssociation + ThroughAssociation => has_many :through
16
+ #
17
+ # The CollectionAssociation class provides common methods to the collections
18
+ # defined by +has_and_belongs_to_many+, +has_many+ or +has_many+ with
19
+ # the <tt>:through association</tt> option.
20
+ #
21
+ # You need to be careful with assumptions regarding the target: The proxy
22
+ # does not fetch records from the database until it needs them, but new
23
+ # ones created with +build+ are added to the target. So, the target may be
24
+ # non-empty and still lack children waiting to be read from the database.
25
+ # If you look directly to the database you cannot assume that's the entire
26
+ # collection because new records may have been added to the target, etc.
27
+ #
28
+ # If you need to work on all current children, new and existing records,
29
+ # +load_target+ and the +loaded+ flag are your friends.
30
+ class CollectionAssociation < Association # :nodoc:
31
+ attr_accessor :nested_attributes_target
32
+
33
+ # Implements the reader method, e.g. foo.items for Foo.has_many :items
34
+ def reader
35
+ ensure_klass_exists!
36
+
37
+ if stale_target?
38
+ reload
39
+ end
40
+
41
+ @proxy ||= CollectionProxy.create(klass, self)
42
+ @proxy.reset_scope
43
+ end
44
+
45
+ # Implements the writer method, e.g. foo.items= for Foo.has_many :items
46
+ def writer(records)
47
+ replace(records)
48
+ end
49
+
50
+ # Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items
51
+ def ids_reader
52
+ if loaded?
53
+ target.pluck(*reflection.association_primary_key)
54
+ elsif !target.empty?
55
+ load_target.pluck(*reflection.association_primary_key)
56
+ else
57
+ @association_ids ||= scope.pluck(*reflection.association_primary_key)
58
+ end
59
+ end
60
+
61
+ # Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items
62
+ def ids_writer(ids)
63
+ primary_key = reflection.association_primary_key
64
+ pk_type = klass.type_for_attribute(primary_key)
65
+ ids = Array(ids).compact_blank
66
+ ids.map! { |id| pk_type.cast(id) }
67
+
68
+ records = if klass.composite_primary_key?
69
+ klass.where(primary_key => ids).index_by do |record|
70
+ primary_key.map { |primary_key| record._read_attribute(primary_key) }
71
+ end
72
+ else
73
+ klass.where(primary_key => ids).index_by do |record|
74
+ record._read_attribute(primary_key)
75
+ end
76
+ end.values_at(*ids).compact
77
+
78
+ if records.size != ids.size
79
+ found_ids = records.map { |record| record._read_attribute(primary_key) }
80
+ not_found_ids = ids - found_ids
81
+ klass.all.raise_record_not_found_exception!(ids, records.size, ids.size, primary_key, not_found_ids)
82
+ else
83
+ replace(records)
84
+ end
85
+ end
86
+
87
+ def reset
88
+ super
89
+ @target = []
90
+ @replaced_or_added_targets = Set.new.compare_by_identity
91
+ @association_ids = nil
92
+ end
93
+
94
+ def find(*args)
95
+ if options[:inverse_of] && loaded?
96
+ args_flatten = args.flatten
97
+ model = scope.model
98
+
99
+ if args_flatten.blank?
100
+ error_message = "Couldn't find #{model.name} without an ID"
101
+ raise RecordNotFound.new(error_message, model.name, model.primary_key, args)
102
+ end
103
+
104
+ result = find_by_scan(*args)
105
+
106
+ result_size = Array(result).size
107
+ if !result || result_size != args_flatten.size
108
+ scope.raise_record_not_found_exception!(args_flatten, result_size, args_flatten.size)
109
+ else
110
+ result
111
+ end
112
+ else
113
+ scope.find(*args)
114
+ end
115
+ end
116
+
117
+ def build(attributes = nil, &block)
118
+ if attributes.is_a?(Array)
119
+ attributes.collect { |attr| build(attr, &block) }
120
+ else
121
+ add_to_target(build_record(attributes, &block), replace: true)
122
+ end
123
+ end
124
+
125
+ # Add +records+ to this association. Since +<<+ flattens its argument list
126
+ # and inserts each record, +push+ and +concat+ behave identically.
127
+ def concat(*records)
128
+ records = records.flatten
129
+ if owner.new_record?
130
+ skip_strict_loading { load_target }
131
+ concat_records(records)
132
+ else
133
+ transaction { concat_records(records) }
134
+ end
135
+ end
136
+
137
+ # Removes all records from the association without calling callbacks
138
+ # on the associated records. It honors the +:dependent+ option. However
139
+ # if the +:dependent+ value is +:destroy+ then in that case the +:delete_all+
140
+ # deletion strategy for the association is applied.
141
+ #
142
+ # You can force a particular deletion strategy by passing a parameter.
143
+ #
144
+ # Example:
145
+ #
146
+ # @author.books.delete_all(:nullify)
147
+ # @author.books.delete_all(:delete_all)
148
+ #
149
+ # See delete for more info.
150
+ def delete_all(dependent = nil)
151
+ if dependent && ![:nullify, :delete_all].include?(dependent)
152
+ raise ArgumentError, "Valid values are :nullify or :delete_all"
153
+ end
154
+
155
+ dependent = if dependent
156
+ dependent
157
+ elsif options[:dependent] == :destroy
158
+ :delete_all
159
+ else
160
+ options[:dependent]
161
+ end
162
+
163
+ delete_or_nullify_all_records(dependent).tap do
164
+ reset
165
+ loaded!
166
+ end
167
+ end
168
+
169
+ # Destroy all the records from this association.
170
+ #
171
+ # See destroy for more info.
172
+ def destroy_all
173
+ destroy(load_target).tap do
174
+ reset
175
+ loaded!
176
+ end
177
+ end
178
+
179
+ # Removes +records+ from this association calling +before_remove+ and
180
+ # +after_remove+ callbacks.
181
+ #
182
+ # This method is abstract in the sense that +delete_records+ has to be
183
+ # provided by descendants. Note this method does not imply the records
184
+ # are actually removed from the database, that depends precisely on
185
+ # +delete_records+. They are in any case removed from the collection.
186
+ def delete(*records)
187
+ delete_or_destroy(records, options[:dependent])
188
+ end
189
+
190
+ # Deletes the +records+ and removes them from this association calling
191
+ # +before_remove+, +after_remove+, +before_destroy+ and +after_destroy+ callbacks.
192
+ #
193
+ # Note that this method removes records from the database ignoring the
194
+ # +:dependent+ option.
195
+ def destroy(*records)
196
+ delete_or_destroy(records, :destroy)
197
+ end
198
+
199
+ # Returns the size of the collection by executing a SELECT COUNT(*)
200
+ # query if the collection hasn't been loaded, and calling
201
+ # <tt>collection.size</tt> if it has.
202
+ #
203
+ # If the collection has been already loaded +size+ and +length+ are
204
+ # equivalent. If not and you are going to need the records anyway
205
+ # +length+ will take one less query. Otherwise +size+ is more efficient.
206
+ #
207
+ # This method is abstract in the sense that it relies on
208
+ # +count_records+, which is a method descendants have to provide.
209
+ def size
210
+ if !find_target? || loaded?
211
+ target.size
212
+ elsif @association_ids
213
+ @association_ids.size
214
+ elsif !association_scope.group_values.empty?
215
+ load_target.size
216
+ elsif !association_scope.distinct_value && !target.empty?
217
+ unsaved_records = target.select(&:new_record?)
218
+ unsaved_records.size + count_records
219
+ else
220
+ count_records
221
+ end
222
+ end
223
+
224
+ # Returns true if the collection is empty.
225
+ #
226
+ # If the collection has been loaded
227
+ # it is equivalent to <tt>collection.size.zero?</tt>. If the
228
+ # collection has not been loaded, it is equivalent to
229
+ # <tt>!collection.exists?</tt>. If the collection has not already been
230
+ # loaded and you are going to fetch the records anyway it is better to
231
+ # check <tt>collection.length.zero?</tt>.
232
+ def empty?
233
+ if loaded? || @association_ids || reflection.has_active_cached_counter?
234
+ size.zero?
235
+ else
236
+ target.empty? && !scope.exists?
237
+ end
238
+ end
239
+
240
+ # Replace this collection with +other_array+. This will perform a diff
241
+ # and delete/add only records that have changed.
242
+ def replace(other_array)
243
+ other_array.each { |val| raise_on_type_mismatch!(val) }
244
+ original_target = skip_strict_loading { load_target }.dup
245
+
246
+ if owner.new_record?
247
+ replace_records(other_array, original_target)
248
+ else
249
+ replace_common_records_in_memory(other_array, original_target)
250
+ if other_array != original_target
251
+ transaction { replace_records(other_array, original_target) }
252
+ else
253
+ other_array
254
+ end
255
+ end
256
+ end
257
+
258
+ def include?(record)
259
+ klass = reflection.klass
260
+ return false unless record.is_a?(klass)
261
+
262
+ if record.new_record?
263
+ include_in_memory?(record)
264
+ elsif loaded?
265
+ target.include?(record)
266
+ else
267
+ record_id = klass.composite_primary_key? ? klass.primary_key.zip(record.id).to_h : record.id
268
+ scope.exists?(record_id)
269
+ end
270
+ end
271
+
272
+ def load_target
273
+ if find_target?
274
+ @target = merge_target_lists(find_target, target)
275
+ end
276
+
277
+ loaded!
278
+ target
279
+ end
280
+
281
+ def add_to_target(record, skip_callbacks: false, replace: false, &block)
282
+ replace_on_target(record, skip_callbacks, replace: replace || association_scope.distinct_value, &block)
283
+ end
284
+
285
+ def target=(record)
286
+ return super unless reflection.klass.has_many_inversing
287
+
288
+ case record
289
+ when nil
290
+ # It's not possible to remove the record from the inverse association.
291
+ when Array
292
+ super
293
+ else
294
+ replace_on_target(record, true, replace: true, inversing: true)
295
+ end
296
+ end
297
+
298
+ def scope
299
+ scope = super
300
+ scope.none! if null_scope?
301
+ scope
302
+ end
303
+
304
+ def null_scope?
305
+ owner.new_record? && !foreign_key_present?
306
+ end
307
+
308
+ def find_from_target?
309
+ loaded? ||
310
+ (owner.strict_loading? && owner.strict_loading_all?) ||
311
+ reflection.strict_loading? ||
312
+ owner.new_record? ||
313
+ target.any? { |record| record.new_record? || record.changed? }
314
+ end
315
+
316
+ def collection?
317
+ true
318
+ end
319
+
320
+ private
321
+ def transaction(&block)
322
+ reflection.klass.transaction(&block)
323
+ end
324
+
325
+ # We have some records loaded from the database (persisted) and some that are
326
+ # in-memory (memory). The same record may be represented in the persisted array
327
+ # and in the memory array.
328
+ #
329
+ # So the task of this method is to merge them according to the following rules:
330
+ #
331
+ # * The final array must not have duplicates
332
+ # * The order of the persisted array is to be preserved
333
+ # * Any changes made to attributes on objects in the memory array are to be preserved
334
+ # * Otherwise, attributes should have the value found in the database
335
+ def merge_target_lists(persisted, memory)
336
+ return persisted if memory.empty?
337
+
338
+ persisted.map! do |record|
339
+ if mem_record = memory.delete(record)
340
+
341
+ ((record.attribute_names & mem_record.attribute_names) - mem_record.changed_attribute_names_to_save - mem_record.class._attr_readonly).each do |name|
342
+ mem_record._write_attribute(name, record[name])
343
+ end
344
+
345
+ mem_record
346
+ else
347
+ record
348
+ end
349
+ end
350
+
351
+ persisted + memory.reject(&:persisted?)
352
+ end
353
+
354
+ def _create_record(attributes, raise = false, &block)
355
+ unless owner.persisted?
356
+ raise ActiveRecord::RecordNotSaved.new("You cannot call create unless the parent is saved", owner)
357
+ end
358
+
359
+ if attributes.is_a?(Array)
360
+ attributes.collect { |attr| _create_record(attr, raise, &block) }
361
+ else
362
+ record = build_record(attributes, &block)
363
+ transaction do
364
+ result = nil
365
+ add_to_target(record) do
366
+ result = insert_record(record, true, raise) {
367
+ @_was_loaded = loaded?
368
+ }
369
+ end
370
+ raise ActiveRecord::Rollback unless result
371
+ end
372
+ record
373
+ end
374
+ end
375
+
376
+ # Do the relevant stuff to insert the given record into the association collection.
377
+ def insert_record(record, validate = true, raise = false, &block)
378
+ if raise
379
+ record.save!(validate: validate, &block)
380
+ else
381
+ record.save(validate: validate, &block)
382
+ end
383
+ end
384
+
385
+ def delete_or_destroy(records, method)
386
+ return if records.empty?
387
+ records = find(records) if records.any? { |record| record.kind_of?(Integer) || record.kind_of?(String) }
388
+ records = records.flatten
389
+ records.each { |record| raise_on_type_mismatch!(record) }
390
+ existing_records = records.reject(&:new_record?)
391
+
392
+ if existing_records.empty?
393
+ remove_records(existing_records, records, method)
394
+ else
395
+ transaction { remove_records(existing_records, records, method) }
396
+ end
397
+ end
398
+
399
+ def remove_records(existing_records, records, method)
400
+ catch(:abort) do
401
+ records.each { |record| callback(:before_remove, record) }
402
+ end || return
403
+
404
+ delete_records(existing_records, method) if existing_records.any?
405
+ @target -= records
406
+ @association_ids = nil
407
+
408
+ records.each { |record| callback(:after_remove, record) }
409
+ end
410
+
411
+ # Delete the given records from the association,
412
+ # using one of the methods +:destroy+, +:delete_all+
413
+ # or +:nullify+ (or +nil+, in which case a default is used).
414
+ def delete_records(records, method)
415
+ raise NotImplementedError
416
+ end
417
+
418
+ def replace_records(new_target, original_target)
419
+ delete(difference(target, new_target))
420
+
421
+ unless concat(difference(new_target, target))
422
+ @target = original_target
423
+ raise RecordNotSaved, "Failed to replace #{reflection.name} because one or more of the " \
424
+ "new records could not be saved."
425
+ end
426
+
427
+ target
428
+ end
429
+
430
+ def replace_common_records_in_memory(new_target, original_target)
431
+ common_records = intersection(new_target, original_target)
432
+ common_records.each do |record|
433
+ skip_callbacks = true
434
+ replace_on_target(record, skip_callbacks, replace: true)
435
+ end
436
+ end
437
+
438
+ def concat_records(records, raise = false)
439
+ result = true
440
+
441
+ records.each do |record|
442
+ raise_on_type_mismatch!(record)
443
+ add_to_target(record) do
444
+ unless owner.new_record?
445
+ result &&= insert_record(record, true, raise) {
446
+ @_was_loaded = loaded?
447
+ }
448
+ end
449
+ end
450
+ end
451
+
452
+ raise ActiveRecord::Rollback unless result
453
+
454
+ records
455
+ end
456
+
457
+ def replace_on_target(record, skip_callbacks, replace:, inversing: false)
458
+ if replace && (!record.new_record? || @replaced_or_added_targets.include?(record))
459
+ index = @target.index(record)
460
+ end
461
+
462
+ catch(:abort) do
463
+ callback(:before_add, record)
464
+ end || return unless skip_callbacks
465
+
466
+ set_inverse_instance(record)
467
+
468
+ @_was_loaded = true
469
+
470
+ yield(record) if block_given?
471
+
472
+ if !index && @replaced_or_added_targets.include?(record)
473
+ index = @target.index(record)
474
+ end
475
+
476
+ @replaced_or_added_targets << record if inversing || index || record.new_record?
477
+
478
+ if index
479
+ target[index] = record
480
+ elsif @_was_loaded || !loaded?
481
+ @association_ids = nil
482
+ target << record
483
+ end
484
+
485
+ callback(:after_add, record) unless skip_callbacks
486
+
487
+ record
488
+ ensure
489
+ @_was_loaded = nil
490
+ end
491
+
492
+ def callback(method, record)
493
+ callbacks_for(method).each do |callback|
494
+ callback.call(method, owner, record)
495
+ end
496
+ end
497
+
498
+ def callbacks_for(callback_name)
499
+ full_callback_name = "#{callback_name}_for_#{reflection.name}"
500
+ if owner.class.respond_to?(full_callback_name)
501
+ owner.class.send(full_callback_name)
502
+ else
503
+ []
504
+ end
505
+ end
506
+
507
+ def include_in_memory?(record)
508
+ if reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
509
+ assoc = owner.association(reflection.through_reflection.name)
510
+ assoc.reader.any? { |source|
511
+ target_reflection = source.send(reflection.source_reflection.name)
512
+ target_reflection.respond_to?(:include?) ? target_reflection.include?(record) : target_reflection == record
513
+ } || target.include?(record)
514
+ else
515
+ target.include?(record)
516
+ end
517
+ end
518
+
519
+ # If the :inverse_of option has been
520
+ # specified, then #find scans the entire collection.
521
+ def find_by_scan(*args)
522
+ expects_array = args.first.kind_of?(Array)
523
+ ids = args.flatten.compact.map(&:to_s).uniq
524
+
525
+ if ids.size == 1
526
+ id = ids.first
527
+ record = load_target.detect { |r| id == r.id.to_s }
528
+ expects_array ? [ record ] : record
529
+ else
530
+ load_target.select { |r| ids.include?(r.id.to_s) }
531
+ end
532
+ end
533
+ end
534
+ end
535
+ end