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,836 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/enumerable"
4
+ require "active_support/core_ext/module/delegation"
5
+ require "active_support/parameter_filter"
6
+ require "concurrent/map"
7
+
8
+ module ActiveRecord
9
+ # = Active Record \Core
10
+ module Core
11
+ extend ActiveSupport::Concern
12
+ include ActiveModel::Access
13
+
14
+ included do
15
+ ##
16
+ # :singleton-method:
17
+ #
18
+ # Accepts a logger conforming to the interface of Log4r or the default
19
+ # Ruby +Logger+ class, which is then passed on to any new database
20
+ # connections made. You can retrieve this logger by calling +logger+ on
21
+ # either an Active Record model class or an Active Record model instance.
22
+ class_attribute :logger, instance_writer: false
23
+
24
+ class_attribute :_destroy_association_async_job, instance_accessor: false, default: "ActiveRecord::DestroyAssociationAsyncJob"
25
+
26
+ # The job class used to destroy associations in the background.
27
+ def self.destroy_association_async_job
28
+ if _destroy_association_async_job.is_a?(String)
29
+ self._destroy_association_async_job = _destroy_association_async_job.constantize
30
+ end
31
+ _destroy_association_async_job
32
+ rescue NameError => error
33
+ raise NameError, "Unable to load destroy_association_async_job: #{error.message}"
34
+ end
35
+
36
+ singleton_class.alias_method :destroy_association_async_job=, :_destroy_association_async_job=
37
+ delegate :destroy_association_async_job, to: :class
38
+
39
+ ##
40
+ # :singleton-method:
41
+ #
42
+ # Specifies the maximum number of records that will be destroyed in a
43
+ # single background job by the <tt>dependent: :destroy_async</tt>
44
+ # association option. When +nil+ (default), all dependent records will be
45
+ # destroyed in a single background job. If specified, the records to be
46
+ # destroyed will be split into multiple background jobs.
47
+ class_attribute :destroy_association_async_batch_size, instance_writer: false, instance_predicate: false, default: nil
48
+
49
+ ##
50
+ # Contains the database configuration - as is typically stored in config/database.yml -
51
+ # as an ActiveRecord::DatabaseConfigurations object.
52
+ #
53
+ # For example, the following database.yml...
54
+ #
55
+ # development:
56
+ # adapter: sqlite3
57
+ # database: storage/development.sqlite3
58
+ #
59
+ # production:
60
+ # adapter: sqlite3
61
+ # database: storage/production.sqlite3
62
+ #
63
+ # ...would result in ActiveRecord::Base.configurations to look like this:
64
+ #
65
+ # #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
66
+ # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
67
+ # @name="primary", @config={adapter: "sqlite3", database: "storage/development.sqlite3"}>,
68
+ # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
69
+ # @name="primary", @config={adapter: "sqlite3", database: "storage/production.sqlite3"}>
70
+ # ]>
71
+ def self.configurations=(config)
72
+ @@configurations = ActiveRecord::DatabaseConfigurations.new(config)
73
+ end
74
+ self.configurations = {}
75
+
76
+ # Returns a fully resolved ActiveRecord::DatabaseConfigurations object.
77
+ def self.configurations
78
+ @@configurations
79
+ end
80
+
81
+ ##
82
+ # :singleton-method:
83
+ # Force enumeration of all columns in SELECT statements.
84
+ # e.g. <tt>SELECT first_name, last_name FROM ...</tt> instead of <tt>SELECT * FROM ...</tt>
85
+ # This avoids +PreparedStatementCacheExpired+ errors when a column is added
86
+ # to the database while the app is running.
87
+ class_attribute :enumerate_columns_in_select_statements, instance_accessor: false, default: false
88
+
89
+ class_attribute :belongs_to_required_by_default, instance_accessor: false
90
+
91
+ class_attribute :strict_loading_by_default, instance_accessor: false, default: false
92
+ class_attribute :strict_loading_mode, instance_accessor: false, default: :all
93
+
94
+ class_attribute :has_many_inversing, instance_accessor: false, default: false
95
+
96
+ class_attribute :run_commit_callbacks_on_first_saved_instances_in_transaction, instance_accessor: false, default: true
97
+
98
+ class_attribute :default_connection_handler, instance_writer: false
99
+
100
+ class_attribute :default_role, instance_writer: false
101
+
102
+ class_attribute :default_shard, instance_writer: false
103
+
104
+ class_attribute :shard_selector, instance_accessor: false, default: nil
105
+
106
+ # Specifies the attributes that will be included in the output of the #inspect method
107
+ class_attribute :attributes_for_inspect, instance_accessor: false, default: :all
108
+
109
+ def self.application_record_class? # :nodoc:
110
+ if ActiveRecord.application_record_class
111
+ self == ActiveRecord.application_record_class
112
+ else
113
+ if defined?(ApplicationRecord) && self == ApplicationRecord
114
+ true
115
+ end
116
+ end
117
+ end
118
+
119
+ self.filter_attributes = []
120
+
121
+ def self.connection_handler
122
+ ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] || default_connection_handler
123
+ end
124
+
125
+ def self.connection_handler=(handler)
126
+ ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler
127
+ end
128
+
129
+ def self.asynchronous_queries_session # :nodoc:
130
+ asynchronous_queries_tracker.current_session
131
+ end
132
+
133
+ def self.asynchronous_queries_tracker # :nodoc:
134
+ ActiveSupport::IsolatedExecutionState[:active_record_asynchronous_queries_tracker] ||= \
135
+ AsynchronousQueriesTracker.new
136
+ end
137
+
138
+ # Returns the symbol representing the current connected role.
139
+ #
140
+ # ActiveRecord::Base.connected_to(role: :writing) do
141
+ # ActiveRecord::Base.current_role #=> :writing
142
+ # end
143
+ #
144
+ # ActiveRecord::Base.connected_to(role: :reading) do
145
+ # ActiveRecord::Base.current_role #=> :reading
146
+ # end
147
+ def self.current_role
148
+ connected_to_stack.reverse_each do |hash|
149
+ return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
150
+ return hash[:role] if hash[:role] && hash[:klasses].include?(connection_class_for_self)
151
+ end
152
+
153
+ default_role
154
+ end
155
+
156
+ # Returns the symbol representing the current connected shard.
157
+ #
158
+ # ActiveRecord::Base.connected_to(role: :reading) do
159
+ # ActiveRecord::Base.current_shard #=> :default
160
+ # end
161
+ #
162
+ # ActiveRecord::Base.connected_to(role: :writing, shard: :one) do
163
+ # ActiveRecord::Base.current_shard #=> :one
164
+ # end
165
+ def self.current_shard
166
+ connected_to_stack.reverse_each do |hash|
167
+ return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
168
+ return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_class_for_self)
169
+ end
170
+
171
+ default_shard
172
+ end
173
+
174
+ # Returns the symbol representing the current setting for
175
+ # preventing writes.
176
+ #
177
+ # ActiveRecord::Base.connected_to(role: :reading) do
178
+ # ActiveRecord::Base.current_preventing_writes #=> true
179
+ # end
180
+ #
181
+ # ActiveRecord::Base.connected_to(role: :writing) do
182
+ # ActiveRecord::Base.current_preventing_writes #=> false
183
+ # end
184
+ def self.current_preventing_writes
185
+ connected_to_stack.reverse_each do |hash|
186
+ return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
187
+ return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_class_for_self)
188
+ end
189
+
190
+ false
191
+ end
192
+
193
+ def self.connected_to_stack # :nodoc:
194
+ if connected_to_stack = ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack]
195
+ connected_to_stack
196
+ else
197
+ connected_to_stack = Concurrent::Array.new
198
+ ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack] = connected_to_stack
199
+ connected_to_stack
200
+ end
201
+ end
202
+
203
+ def self.connection_class=(b) # :nodoc:
204
+ @connection_class = b
205
+ end
206
+
207
+ def self.connection_class # :nodoc:
208
+ @connection_class ||= false
209
+ end
210
+
211
+ def self.connection_class? # :nodoc:
212
+ self.connection_class
213
+ end
214
+
215
+ def self.connection_class_for_self # :nodoc:
216
+ klass = self
217
+
218
+ until klass == Base
219
+ break if klass.connection_class?
220
+ klass = klass.superclass
221
+ end
222
+
223
+ klass
224
+ end
225
+
226
+ self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
227
+ self.default_role = ActiveRecord.writing_role
228
+ self.default_shard = :default
229
+
230
+ def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
231
+ case ActiveRecord.action_on_strict_loading_violation
232
+ when :raise
233
+ message = reflection.strict_loading_violation_message(owner)
234
+ raise ActiveRecord::StrictLoadingViolationError.new(message)
235
+ when :log
236
+ name = "strict_loading_violation.active_record"
237
+ ActiveSupport::Notifications.instrument(name, owner: owner, reflection: reflection)
238
+ end
239
+ end
240
+ end
241
+
242
+ module ClassMethods
243
+ def initialize_find_by_cache # :nodoc:
244
+ @find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
245
+ end
246
+
247
+ def find(*ids) # :nodoc:
248
+ # We don't have cache keys for this stuff yet
249
+ return super unless ids.length == 1
250
+ return super if block_given? || primary_key.nil? || scope_attributes?
251
+
252
+ id = ids.first
253
+
254
+ return super if StatementCache.unsupported_value?(id)
255
+
256
+ cached_find_by([primary_key], [id]) ||
257
+ raise(RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}", name, primary_key, id))
258
+ end
259
+
260
+ def find_by(*args) # :nodoc:
261
+ return super if scope_attributes?
262
+
263
+ hash = args.first
264
+ return super unless Hash === hash
265
+
266
+ hash = hash.each_with_object({}) do |(key, value), h|
267
+ key = key.to_s
268
+ key = attribute_aliases[key] || key
269
+
270
+ return super if reflect_on_aggregation(key)
271
+
272
+ reflection = _reflect_on_association(key)
273
+
274
+ if !reflection
275
+ value = value.id if value.respond_to?(:id)
276
+ elsif reflection.belongs_to? && !reflection.polymorphic?
277
+ key = reflection.join_foreign_key
278
+ pkey = reflection.join_primary_key
279
+
280
+ if pkey.is_a?(Array)
281
+ if pkey.all? { |attribute| value.respond_to?(attribute) }
282
+ value = pkey.map do |attribute|
283
+ if attribute == "id"
284
+ value.id_value
285
+ else
286
+ value.public_send(attribute)
287
+ end
288
+ end
289
+ composite_primary_key = true
290
+ end
291
+ else
292
+ value = value.public_send(pkey) if value.respond_to?(pkey)
293
+ end
294
+ end
295
+
296
+ if !composite_primary_key &&
297
+ (!columns_hash.key?(key) || StatementCache.unsupported_value?(value))
298
+ return super
299
+ end
300
+
301
+ h[key] = value
302
+ end
303
+
304
+ cached_find_by(hash.keys, hash.values)
305
+ end
306
+
307
+ def find_by!(*args) # :nodoc:
308
+ find_by(*args) || where(*args).raise_record_not_found_exception!
309
+ end
310
+
311
+ def initialize_generated_modules # :nodoc:
312
+ generated_association_methods
313
+ end
314
+
315
+ def generated_association_methods # :nodoc:
316
+ @generated_association_methods ||= begin
317
+ mod = const_set(:GeneratedAssociationMethods, Module.new)
318
+ private_constant :GeneratedAssociationMethods
319
+ include mod
320
+
321
+ mod
322
+ end
323
+ end
324
+
325
+ # Returns columns which shouldn't be exposed while calling +#inspect+.
326
+ def filter_attributes
327
+ if @filter_attributes.nil?
328
+ superclass.filter_attributes
329
+ else
330
+ @filter_attributes
331
+ end
332
+ end
333
+
334
+ # Specifies columns which shouldn't be exposed while calling +#inspect+.
335
+ def filter_attributes=(filter_attributes)
336
+ @inspection_filter = nil
337
+ @filter_attributes = filter_attributes
338
+ end
339
+
340
+ def inspection_filter # :nodoc:
341
+ if @filter_attributes.nil?
342
+ superclass.inspection_filter
343
+ else
344
+ @inspection_filter ||= begin
345
+ mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
346
+ ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
347
+ end
348
+ end
349
+ end
350
+
351
+ # Returns a string like 'Post(id:integer, title:string, body:text)'
352
+ def inspect # :nodoc:
353
+ if self == Base
354
+ super
355
+ elsif abstract_class?
356
+ "#{super}(abstract)"
357
+ elsif !schema_loaded? && !connected?
358
+ "#{super} (call '#{super}.load_schema' to load schema informations)"
359
+ elsif table_exists?
360
+ attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
361
+ "#{super}(#{attr_list})"
362
+ else
363
+ "#{super}(Table doesn't exist)"
364
+ end
365
+ end
366
+
367
+ # Returns an instance of +Arel::Table+ loaded with the current table name.
368
+ def arel_table # :nodoc:
369
+ @arel_table ||= Arel::Table.new(table_name, klass: self)
370
+ end
371
+
372
+ def predicate_builder # :nodoc:
373
+ @predicate_builder ||= PredicateBuilder.new(table_metadata)
374
+ end
375
+
376
+ def type_caster # :nodoc:
377
+ TypeCaster::Map.new(self)
378
+ end
379
+
380
+ def cached_find_by_statement(connection, key, &block) # :nodoc:
381
+ cache = @find_by_statement_cache[connection.prepared_statements]
382
+ cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
383
+ end
384
+
385
+ private
386
+ def inherited(subclass)
387
+ super
388
+
389
+ # initialize cache at class definition for thread safety
390
+ subclass.initialize_find_by_cache
391
+ unless subclass.base_class?
392
+ klass = self
393
+ until klass.base_class?
394
+ klass.initialize_find_by_cache
395
+ klass = klass.superclass
396
+ end
397
+ end
398
+
399
+ subclass.class_eval do
400
+ @arel_table = nil
401
+ @predicate_builder = nil
402
+ @inspection_filter = nil
403
+ @filter_attributes ||= nil
404
+ @generated_association_methods ||= nil
405
+ end
406
+ end
407
+
408
+ def relation
409
+ relation = Relation.create(self)
410
+
411
+ if finder_needs_type_condition? && !ignore_default_scope?
412
+ relation.where!(type_condition)
413
+ else
414
+ relation
415
+ end
416
+ end
417
+
418
+ def table_metadata
419
+ TableMetadata.new(self, arel_table)
420
+ end
421
+
422
+ def cached_find_by(keys, values)
423
+ with_connection do |connection|
424
+ statement = cached_find_by_statement(connection, keys) { |params|
425
+ wheres = keys.index_with do |key|
426
+ if key.is_a?(Array)
427
+ [key.map { params.bind }]
428
+ else
429
+ params.bind
430
+ end
431
+ end
432
+ where(wheres).limit(1)
433
+ }
434
+
435
+ statement.execute(values.flatten, connection, allow_retry: true).then do |r|
436
+ r.first
437
+ rescue TypeError
438
+ raise ActiveRecord::StatementInvalid
439
+ end
440
+ end
441
+ end
442
+ end
443
+
444
+ # New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
445
+ # attributes but not yet saved (pass a hash with key names matching the associated table column names).
446
+ # In both instances, valid attribute keys are determined by the column names of the associated table --
447
+ # hence you can't have attributes that aren't part of the table columns.
448
+ #
449
+ # ==== Example
450
+ # # Instantiates a single new object
451
+ # User.new(first_name: 'Jamie')
452
+ def initialize(attributes = nil)
453
+ @new_record = true
454
+ @attributes = self.class._default_attributes.deep_dup
455
+
456
+ init_internals
457
+ initialize_internals_callback
458
+
459
+ super
460
+
461
+ yield self if block_given?
462
+ _run_initialize_callbacks
463
+ end
464
+
465
+ # Initialize an empty model object from +coder+. +coder+ should be
466
+ # the result of previously encoding an Active Record model, using
467
+ # #encode_with.
468
+ #
469
+ # class Post < ActiveRecord::Base
470
+ # end
471
+ #
472
+ # old_post = Post.new(title: "hello world")
473
+ # coder = {}
474
+ # old_post.encode_with(coder)
475
+ #
476
+ # post = Post.allocate
477
+ # post.init_with(coder)
478
+ # post.title # => 'hello world'
479
+ def init_with(coder, &block)
480
+ coder = LegacyYamlAdapter.convert(coder)
481
+ attributes = self.class.yaml_encoder.decode(coder)
482
+ init_with_attributes(attributes, coder["new_record"], &block)
483
+ end
484
+
485
+ ##
486
+ # Initialize an empty model object from +attributes+.
487
+ # +attributes+ should be an attributes object, and unlike the
488
+ # `initialize` method, no assignment calls are made per attribute.
489
+ def init_with_attributes(attributes, new_record = false) # :nodoc:
490
+ @new_record = new_record
491
+ @attributes = attributes
492
+
493
+ init_internals
494
+
495
+ yield self if block_given?
496
+
497
+ _run_find_callbacks
498
+ _run_initialize_callbacks
499
+
500
+ self
501
+ end
502
+
503
+ ##
504
+ # :method: clone
505
+ # Identical to Ruby's clone method. This is a "shallow" copy. Be warned that your attributes are not copied.
506
+ # That means that modifying attributes of the clone will modify the original, since they will both point to the
507
+ # same attributes hash. If you need a copy of your attributes hash, please use the #dup method.
508
+ #
509
+ # user = User.first
510
+ # new_user = user.clone
511
+ # user.name # => "Bob"
512
+ # new_user.name = "Joe"
513
+ # user.name # => "Joe"
514
+ #
515
+ # user.object_id == new_user.object_id # => false
516
+ # user.name.object_id == new_user.name.object_id # => true
517
+ #
518
+ # user.name.object_id == user.dup.name.object_id # => false
519
+
520
+ ##
521
+ # :method: dup
522
+ # Duped objects have no id assigned and are treated as new records. Note
523
+ # that this is a "shallow" copy as it copies the object's attributes
524
+ # only, not its associations. The extent of a "deep" copy is application
525
+ # specific and is therefore left to the application to implement according
526
+ # to its need.
527
+ # The dup method does not preserve the timestamps (created|updated)_(at|on)
528
+ # and locking column.
529
+
530
+ ##
531
+ def initialize_dup(other) # :nodoc:
532
+ @attributes = @attributes.deep_dup
533
+ if self.class.composite_primary_key?
534
+ @primary_key.each { |key| @attributes.reset(key) }
535
+ else
536
+ @attributes.reset(@primary_key)
537
+ end
538
+
539
+ _run_initialize_callbacks
540
+
541
+ @new_record = true
542
+ @previously_new_record = false
543
+ @destroyed = false
544
+ @_start_transaction_state = nil
545
+
546
+ super
547
+ end
548
+
549
+ # Populate +coder+ with attributes about this record that should be
550
+ # serialized. The structure of +coder+ defined in this method is
551
+ # guaranteed to match the structure of +coder+ passed to the #init_with
552
+ # method.
553
+ #
554
+ # Example:
555
+ #
556
+ # class Post < ActiveRecord::Base
557
+ # end
558
+ # coder = {}
559
+ # Post.new.encode_with(coder)
560
+ # coder # => {"attributes" => {"id" => nil, ... }}
561
+ def encode_with(coder)
562
+ self.class.yaml_encoder.encode(@attributes, coder)
563
+ coder["new_record"] = new_record?
564
+ coder["active_record_yaml_version"] = 2
565
+ end
566
+
567
+ ##
568
+ # :method: slice
569
+ #
570
+ # :call-seq: slice(*methods)
571
+ #
572
+ # Returns a hash of the given methods with their names as keys and returned
573
+ # values as values.
574
+ #
575
+ # topic = Topic.new(title: "Budget", author_name: "Jason")
576
+ # topic.slice(:title, :author_name)
577
+ # => { "title" => "Budget", "author_name" => "Jason" }
578
+ #
579
+ #--
580
+ # Implemented by ActiveModel::Access#slice.
581
+
582
+ ##
583
+ # :method: values_at
584
+ #
585
+ # :call-seq: values_at(*methods)
586
+ #
587
+ # Returns an array of the values returned by the given methods.
588
+ #
589
+ # topic = Topic.new(title: "Budget", author_name: "Jason")
590
+ # topic.values_at(:title, :author_name)
591
+ # => ["Budget", "Jason"]
592
+ #
593
+ #--
594
+ # Implemented by ActiveModel::Access#values_at.
595
+
596
+ # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
597
+ # is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
598
+ #
599
+ # Note that new records are different from any other record by definition, unless the
600
+ # other record is the receiver itself. Besides, if you fetch existing records with
601
+ # +select+ and leave the ID out, you're on your own, this predicate will return false.
602
+ #
603
+ # Note also that destroying a record preserves its ID in the model instance, so deleted
604
+ # models are still comparable.
605
+ def ==(comparison_object)
606
+ super ||
607
+ comparison_object.instance_of?(self.class) &&
608
+ primary_key_values_present? &&
609
+ comparison_object.id == id
610
+ end
611
+ alias :eql? :==
612
+
613
+ # Delegates to id in order to allow two records of the same type and id to work with something like:
614
+ # [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
615
+ def hash
616
+ id = self.id
617
+
618
+ if primary_key_values_present?
619
+ self.class.hash ^ id.hash
620
+ else
621
+ super
622
+ end
623
+ end
624
+
625
+ # Clone and freeze the attributes hash such that associations are still
626
+ # accessible, even on destroyed records, but cloned models will not be
627
+ # frozen.
628
+ def freeze
629
+ @attributes = @attributes.clone.freeze
630
+ self
631
+ end
632
+
633
+ # Returns +true+ if the attributes hash has been frozen.
634
+ def frozen?
635
+ @attributes.frozen?
636
+ end
637
+
638
+ # Allows sort on objects
639
+ def <=>(other_object)
640
+ if other_object.is_a?(self.class)
641
+ to_key <=> other_object.to_key
642
+ else
643
+ super
644
+ end
645
+ end
646
+
647
+ def present? # :nodoc:
648
+ true
649
+ end
650
+
651
+ def blank? # :nodoc:
652
+ false
653
+ end
654
+
655
+ # Returns +true+ if the record is read only.
656
+ def readonly?
657
+ @readonly
658
+ end
659
+
660
+ # Returns +true+ if the record is in strict_loading mode.
661
+ def strict_loading?
662
+ @strict_loading
663
+ end
664
+
665
+ # Sets the record to strict_loading mode. This will raise an error
666
+ # if the record tries to lazily load an association.
667
+ #
668
+ # user = User.first
669
+ # user.strict_loading! # => true
670
+ # user.address.city
671
+ # => ActiveRecord::StrictLoadingViolationError
672
+ # user.comments.to_a
673
+ # => ActiveRecord::StrictLoadingViolationError
674
+ #
675
+ # ==== Parameters
676
+ #
677
+ # * +value+ - Boolean specifying whether to enable or disable strict loading.
678
+ # * <tt>:mode</tt> - Symbol specifying strict loading mode. Defaults to :all. Using
679
+ # :n_plus_one_only mode will only raise an error if an association that
680
+ # will lead to an n plus one query is lazily loaded.
681
+ #
682
+ # ==== Examples
683
+ #
684
+ # user = User.first
685
+ # user.strict_loading!(false) # => false
686
+ # user.address.city # => "Tatooine"
687
+ # user.comments.to_a # => [#<Comment:0x00...]
688
+ #
689
+ # user.strict_loading!(mode: :n_plus_one_only)
690
+ # user.address.city # => "Tatooine"
691
+ # user.comments.to_a # => [#<Comment:0x00...]
692
+ # user.comments.first.ratings.to_a
693
+ # => ActiveRecord::StrictLoadingViolationError
694
+ def strict_loading!(value = true, mode: :all)
695
+ unless [:all, :n_plus_one_only].include?(mode)
696
+ raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only] but #{mode.inspect} was provided."
697
+ end
698
+
699
+ @strict_loading_mode = mode
700
+ @strict_loading = value
701
+ end
702
+
703
+ attr_reader :strict_loading_mode
704
+
705
+ # Returns +true+ if the record uses strict_loading with +:n_plus_one_only+ mode enabled.
706
+ def strict_loading_n_plus_one_only?
707
+ @strict_loading_mode == :n_plus_one_only
708
+ end
709
+
710
+ # Returns +true+ if the record uses strict_loading with +:all+ mode enabled.
711
+ def strict_loading_all?
712
+ @strict_loading_mode == :all
713
+ end
714
+
715
+ # Marks this record as read only.
716
+ #
717
+ # customer = Customer.first
718
+ # customer.readonly!
719
+ # customer.save # Raises an ActiveRecord::ReadOnlyRecord
720
+ def readonly!
721
+ @readonly = true
722
+ end
723
+
724
+ def connection_handler
725
+ self.class.connection_handler
726
+ end
727
+
728
+ # Returns the attributes specified by <tt>.attributes_for_inspect</tt> as a nicely formatted string.
729
+ def inspect
730
+ inspect_with_attributes(attributes_for_inspect)
731
+ end
732
+
733
+ # Returns the full contents of the record as a nicely formatted string.
734
+ def full_inspect
735
+ inspect_with_attributes(all_attributes_for_inspect)
736
+ end
737
+
738
+ # Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
739
+ # when pp is required.
740
+ def pretty_print(pp)
741
+ return super if custom_inspect_method_defined?
742
+ pp.object_address_group(self) do
743
+ if @attributes
744
+ attr_names = attributes_for_inspect.select { |name| _has_attribute?(name.to_s) }
745
+ pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
746
+ attr_name = attr_name.to_s
747
+ pp.breakable " "
748
+ pp.group(1) do
749
+ pp.text attr_name
750
+ pp.text ":"
751
+ pp.breakable
752
+ value = attribute_for_inspect(attr_name)
753
+ pp.text value
754
+ end
755
+ end
756
+ else
757
+ pp.breakable " "
758
+ pp.text "not initialized"
759
+ end
760
+ end
761
+ end
762
+
763
+ private
764
+ # +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
765
+ # the array, and then rescues from the possible +NoMethodError+. If those elements are
766
+ # +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have,
767
+ # which significantly impacts upon performance.
768
+ #
769
+ # So we can avoid the +method_missing+ hit by explicitly defining +#to_ary+ as +nil+ here.
770
+ #
771
+ # See also https://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
772
+ def to_ary
773
+ nil
774
+ end
775
+
776
+ def init_internals
777
+ @readonly = false
778
+ @previously_new_record = false
779
+ @destroyed = false
780
+ @marked_for_destruction = false
781
+ @destroyed_by_association = nil
782
+ @_start_transaction_state = nil
783
+
784
+ klass = self.class
785
+
786
+ @primary_key = klass.primary_key
787
+ @strict_loading = klass.strict_loading_by_default
788
+ @strict_loading_mode = klass.strict_loading_mode
789
+
790
+ klass.define_attribute_methods
791
+ end
792
+
793
+ def initialize_internals_callback
794
+ end
795
+
796
+ def custom_inspect_method_defined?
797
+ self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
798
+ end
799
+
800
+ class InspectionMask < DelegateClass(::String)
801
+ def pretty_print(pp)
802
+ pp.text __getobj__
803
+ end
804
+ end
805
+ private_constant :InspectionMask
806
+
807
+ def inspection_filter
808
+ self.class.inspection_filter
809
+ end
810
+
811
+ def inspect_with_attributes(attributes_to_list)
812
+ inspection = if @attributes
813
+ attributes_to_list.filter_map do |name|
814
+ name = name.to_s
815
+ if _has_attribute?(name)
816
+ "#{name}: #{attribute_for_inspect(name)}"
817
+ end
818
+ end.join(", ")
819
+ else
820
+ "not initialized"
821
+ end
822
+
823
+ "#<#{self.class} #{inspection}>"
824
+ end
825
+
826
+ def attributes_for_inspect
827
+ self.class.attributes_for_inspect == :all ? all_attributes_for_inspect : self.class.attributes_for_inspect
828
+ end
829
+
830
+ def all_attributes_for_inspect
831
+ return [] unless @attributes
832
+
833
+ attribute_names
834
+ end
835
+ end
836
+ end