activerecord 6.0.0 → 7.2.3

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 (376) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +996 -594
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +34 -34
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +22 -20
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +41 -30
  9. data/lib/active_record/associations/association.rb +106 -41
  10. data/lib/active_record/associations/association_scope.rb +30 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +69 -14
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
  13. data/lib/active_record/associations/builder/association.rb +39 -6
  14. data/lib/active_record/associations/builder/belongs_to.rb +47 -17
  15. data/lib/active_record/associations/builder/collection_association.rb +14 -6
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
  17. data/lib/active_record/associations/builder/has_many.rb +7 -3
  18. data/lib/active_record/associations/builder/has_one.rb +13 -16
  19. data/lib/active_record/associations/builder/singular_association.rb +7 -3
  20. data/lib/active_record/associations/collection_association.rb +90 -53
  21. data/lib/active_record/associations/collection_proxy.rb +54 -19
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/errors.rb +265 -0
  24. data/lib/active_record/associations/foreign_association.rb +21 -1
  25. data/lib/active_record/associations/has_many_association.rb +41 -10
  26. data/lib/active_record/associations/has_many_through_association.rb +29 -12
  27. data/lib/active_record/associations/has_one_association.rb +33 -9
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
  30. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  31. data/lib/active_record/associations/join_dependency.rb +97 -54
  32. data/lib/active_record/associations/nested_error.rb +47 -0
  33. data/lib/active_record/associations/preloader/association.rb +237 -54
  34. data/lib/active_record/associations/preloader/batch.rb +48 -0
  35. data/lib/active_record/associations/preloader/branch.rb +153 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +51 -17
  37. data/lib/active_record/associations/preloader.rb +55 -121
  38. data/lib/active_record/associations/singular_association.rb +16 -4
  39. data/lib/active_record/associations/through_association.rb +26 -15
  40. data/lib/active_record/associations.rb +454 -440
  41. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  42. data/lib/active_record/attribute_assignment.rb +11 -14
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
  44. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  45. data/lib/active_record/attribute_methods/dirty.rb +75 -34
  46. data/lib/active_record/attribute_methods/primary_key.rb +53 -31
  47. data/lib/active_record/attribute_methods/query.rb +31 -22
  48. data/lib/active_record/attribute_methods/read.rb +16 -17
  49. data/lib/active_record/attribute_methods/serialization.rb +177 -35
  50. data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
  51. data/lib/active_record/attribute_methods/write.rb +16 -28
  52. data/lib/active_record/attribute_methods.rb +227 -100
  53. data/lib/active_record/attributes.rb +94 -56
  54. data/lib/active_record/autosave_association.rb +119 -73
  55. data/lib/active_record/base.rb +31 -21
  56. data/lib/active_record/callbacks.rb +168 -55
  57. data/lib/active_record/coders/column_serializer.rb +61 -0
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +70 -25
  60. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
  64. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
  65. data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
  66. data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
  67. data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
  68. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  69. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  70. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
  71. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
  72. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
  73. data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
  74. data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
  75. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
  76. data/lib/active_record/connection_adapters/column.rb +28 -1
  77. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  78. data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
  79. data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
  80. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  81. data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
  82. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
  83. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
  84. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
  85. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
  86. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  87. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  88. data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
  89. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  90. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  91. data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
  92. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
  95. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  97. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  101. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
  106. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  110. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
  111. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
  121. data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
  123. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  124. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
  131. data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
  132. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  133. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  134. data/lib/active_record/connection_adapters.rb +176 -0
  135. data/lib/active_record/connection_handling.rb +243 -115
  136. data/lib/active_record/core.rb +481 -199
  137. data/lib/active_record/counter_cache.rb +69 -32
  138. data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
  139. data/lib/active_record/database_configurations/database_config.rb +77 -10
  140. data/lib/active_record/database_configurations/hash_config.rb +148 -26
  141. data/lib/active_record/database_configurations/url_config.rb +44 -45
  142. data/lib/active_record/database_configurations.rb +190 -114
  143. data/lib/active_record/delegated_type.rb +279 -0
  144. data/lib/active_record/deprecator.rb +7 -0
  145. data/lib/active_record/destroy_association_async_job.rb +38 -0
  146. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  147. data/lib/active_record/dynamic_matchers.rb +5 -6
  148. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  149. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  150. data/lib/active_record/encryption/cipher.rb +53 -0
  151. data/lib/active_record/encryption/config.rb +68 -0
  152. data/lib/active_record/encryption/configurable.rb +60 -0
  153. data/lib/active_record/encryption/context.rb +42 -0
  154. data/lib/active_record/encryption/contexts.rb +76 -0
  155. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  156. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  157. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  158. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  159. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  160. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  161. data/lib/active_record/encryption/encryptor.rb +171 -0
  162. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  163. data/lib/active_record/encryption/errors.rb +15 -0
  164. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  165. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  166. data/lib/active_record/encryption/key.rb +28 -0
  167. data/lib/active_record/encryption/key_generator.rb +53 -0
  168. data/lib/active_record/encryption/key_provider.rb +46 -0
  169. data/lib/active_record/encryption/message.rb +33 -0
  170. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  171. data/lib/active_record/encryption/message_serializer.rb +96 -0
  172. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  173. data/lib/active_record/encryption/properties.rb +76 -0
  174. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  175. data/lib/active_record/encryption/scheme.rb +100 -0
  176. data/lib/active_record/encryption.rb +58 -0
  177. data/lib/active_record/enum.rb +224 -73
  178. data/lib/active_record/errors.rb +254 -36
  179. data/lib/active_record/explain.rb +30 -17
  180. data/lib/active_record/explain_registry.rb +11 -6
  181. data/lib/active_record/explain_subscriber.rb +2 -2
  182. data/lib/active_record/fixture_set/file.rb +22 -15
  183. data/lib/active_record/fixture_set/model_metadata.rb +15 -6
  184. data/lib/active_record/fixture_set/render_context.rb +3 -1
  185. data/lib/active_record/fixture_set/table_row.rb +88 -16
  186. data/lib/active_record/fixture_set/table_rows.rb +4 -5
  187. data/lib/active_record/fixtures.rb +229 -116
  188. data/lib/active_record/future_result.rb +178 -0
  189. data/lib/active_record/gem_version.rb +4 -4
  190. data/lib/active_record/inheritance.rb +121 -48
  191. data/lib/active_record/insert_all.rb +178 -29
  192. data/lib/active_record/integration.rb +16 -14
  193. data/lib/active_record/internal_metadata.rb +132 -21
  194. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  195. data/lib/active_record/locking/optimistic.rb +64 -33
  196. data/lib/active_record/locking/pessimistic.rb +21 -8
  197. data/lib/active_record/log_subscriber.rb +61 -30
  198. data/lib/active_record/marshalling.rb +59 -0
  199. data/lib/active_record/message_pack.rb +124 -0
  200. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  201. data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
  202. data/lib/active_record/middleware/database_selector.rb +25 -13
  203. data/lib/active_record/middleware/shard_selector.rb +62 -0
  204. data/lib/active_record/migration/command_recorder.rb +160 -55
  205. data/lib/active_record/migration/compatibility.rb +286 -43
  206. data/lib/active_record/migration/default_strategy.rb +22 -0
  207. data/lib/active_record/migration/execution_strategy.rb +19 -0
  208. data/lib/active_record/migration/join_table.rb +1 -2
  209. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  210. data/lib/active_record/migration.rb +421 -193
  211. data/lib/active_record/model_schema.rb +217 -125
  212. data/lib/active_record/nested_attributes.rb +62 -27
  213. data/lib/active_record/no_touching.rb +4 -4
  214. data/lib/active_record/normalization.rb +163 -0
  215. data/lib/active_record/persistence.rb +322 -319
  216. data/lib/active_record/promise.rb +84 -0
  217. data/lib/active_record/query_cache.rb +18 -15
  218. data/lib/active_record/query_logs.rb +193 -0
  219. data/lib/active_record/query_logs_formatter.rb +41 -0
  220. data/lib/active_record/querying.rb +54 -14
  221. data/lib/active_record/railtie.rb +250 -72
  222. data/lib/active_record/railties/console_sandbox.rb +2 -4
  223. data/lib/active_record/railties/controller_runtime.rb +25 -11
  224. data/lib/active_record/railties/databases.rake +312 -197
  225. data/lib/active_record/railties/job_runtime.rb +23 -0
  226. data/lib/active_record/readonly_attributes.rb +45 -3
  227. data/lib/active_record/reflection.rb +389 -146
  228. data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
  229. data/lib/active_record/relation/batches.rb +214 -73
  230. data/lib/active_record/relation/calculations.rb +379 -124
  231. data/lib/active_record/relation/delegation.rb +36 -23
  232. data/lib/active_record/relation/finder_methods.rb +159 -49
  233. data/lib/active_record/relation/from_clause.rb +5 -1
  234. data/lib/active_record/relation/merger.rb +41 -33
  235. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
  236. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
  237. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
  238. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  239. data/lib/active_record/relation/predicate_builder.rb +79 -53
  240. data/lib/active_record/relation/query_attribute.rb +30 -12
  241. data/lib/active_record/relation/query_methods.rb +1156 -279
  242. data/lib/active_record/relation/record_fetch_warning.rb +12 -11
  243. data/lib/active_record/relation/spawn_methods.rb +10 -9
  244. data/lib/active_record/relation/where_clause.rb +100 -66
  245. data/lib/active_record/relation.rb +829 -194
  246. data/lib/active_record/result.rb +76 -56
  247. data/lib/active_record/runtime_registry.rb +71 -13
  248. data/lib/active_record/sanitization.rb +86 -47
  249. data/lib/active_record/schema.rb +39 -23
  250. data/lib/active_record/schema_dumper.rb +140 -33
  251. data/lib/active_record/schema_migration.rb +74 -29
  252. data/lib/active_record/scoping/default.rb +73 -19
  253. data/lib/active_record/scoping/named.rb +10 -28
  254. data/lib/active_record/scoping.rb +65 -35
  255. data/lib/active_record/secure_password.rb +60 -0
  256. data/lib/active_record/secure_token.rb +34 -8
  257. data/lib/active_record/serialization.rb +11 -4
  258. data/lib/active_record/signed_id.rb +138 -0
  259. data/lib/active_record/statement_cache.rb +26 -10
  260. data/lib/active_record/store.rb +19 -14
  261. data/lib/active_record/suppressor.rb +15 -17
  262. data/lib/active_record/table_metadata.rb +46 -36
  263. data/lib/active_record/tasks/database_tasks.rb +371 -205
  264. data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
  265. data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
  266. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
  267. data/lib/active_record/test_databases.rb +5 -4
  268. data/lib/active_record/test_fixtures.rb +189 -104
  269. data/lib/active_record/testing/query_assertions.rb +121 -0
  270. data/lib/active_record/timestamp.rb +35 -25
  271. data/lib/active_record/token_for.rb +123 -0
  272. data/lib/active_record/touch_later.rb +31 -27
  273. data/lib/active_record/transaction.rb +132 -0
  274. data/lib/active_record/transactions.rb +131 -99
  275. data/lib/active_record/translation.rb +3 -5
  276. data/lib/active_record/type/adapter_specific_registry.rb +33 -18
  277. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  278. data/lib/active_record/type/internal/timezone.rb +7 -2
  279. data/lib/active_record/type/serialized.rb +11 -6
  280. data/lib/active_record/type/time.rb +14 -0
  281. data/lib/active_record/type/type_map.rb +17 -21
  282. data/lib/active_record/type/unsigned_integer.rb +0 -1
  283. data/lib/active_record/type.rb +7 -2
  284. data/lib/active_record/type_caster/connection.rb +4 -5
  285. data/lib/active_record/type_caster/map.rb +8 -5
  286. data/lib/active_record/validations/absence.rb +1 -1
  287. data/lib/active_record/validations/associated.rb +13 -8
  288. data/lib/active_record/validations/numericality.rb +36 -0
  289. data/lib/active_record/validations/presence.rb +5 -28
  290. data/lib/active_record/validations/uniqueness.rb +88 -18
  291. data/lib/active_record/validations.rb +15 -8
  292. data/lib/active_record/version.rb +1 -1
  293. data/lib/active_record.rb +446 -40
  294. data/lib/arel/alias_predication.rb +1 -1
  295. data/lib/arel/attributes/attribute.rb +4 -8
  296. data/lib/arel/collectors/bind.rb +8 -1
  297. data/lib/arel/collectors/composite.rb +15 -0
  298. data/lib/arel/collectors/sql_string.rb +7 -0
  299. data/lib/arel/collectors/substitute_binds.rb +7 -0
  300. data/lib/arel/crud.rb +30 -22
  301. data/lib/arel/delete_manager.rb +23 -4
  302. data/lib/arel/errors.rb +10 -0
  303. data/lib/arel/factory_methods.rb +4 -0
  304. data/lib/arel/filter_predications.rb +9 -0
  305. data/lib/arel/insert_manager.rb +2 -3
  306. data/lib/arel/nodes/binary.rb +82 -9
  307. data/lib/arel/nodes/bind_param.rb +8 -0
  308. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  309. data/lib/arel/nodes/casted.rb +22 -10
  310. data/lib/arel/nodes/cte.rb +36 -0
  311. data/lib/arel/nodes/delete_statement.rb +14 -13
  312. data/lib/arel/nodes/equality.rb +6 -9
  313. data/lib/arel/nodes/filter.rb +10 -0
  314. data/lib/arel/nodes/fragments.rb +35 -0
  315. data/lib/arel/nodes/function.rb +1 -0
  316. data/lib/arel/nodes/grouping.rb +3 -0
  317. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  318. data/lib/arel/nodes/in.rb +8 -1
  319. data/lib/arel/nodes/infix_operation.rb +13 -1
  320. data/lib/arel/nodes/insert_statement.rb +2 -2
  321. data/lib/arel/nodes/join_source.rb +1 -1
  322. data/lib/arel/nodes/leading_join.rb +8 -0
  323. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  324. data/lib/arel/nodes/node.rb +122 -11
  325. data/lib/arel/nodes/ordering.rb +27 -0
  326. data/lib/arel/nodes/select_core.rb +2 -2
  327. data/lib/arel/nodes/select_statement.rb +2 -2
  328. data/lib/arel/nodes/sql_literal.rb +16 -0
  329. data/lib/arel/nodes/table_alias.rb +11 -3
  330. data/lib/arel/nodes/unary.rb +0 -1
  331. data/lib/arel/nodes/update_statement.rb +11 -4
  332. data/lib/arel/nodes.rb +10 -3
  333. data/lib/arel/predications.rb +31 -28
  334. data/lib/arel/select_manager.rb +18 -9
  335. data/lib/arel/table.rb +21 -10
  336. data/lib/arel/tree_manager.rb +8 -15
  337. data/lib/arel/update_manager.rb +25 -5
  338. data/lib/arel/visitors/dot.rb +94 -90
  339. data/lib/arel/visitors/mysql.rb +34 -6
  340. data/lib/arel/visitors/postgresql.rb +5 -16
  341. data/lib/arel/visitors/sqlite.rb +25 -1
  342. data/lib/arel/visitors/to_sql.rb +227 -81
  343. data/lib/arel/visitors/visitor.rb +2 -3
  344. data/lib/arel/visitors.rb +0 -7
  345. data/lib/arel.rb +37 -15
  346. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  347. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  348. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  349. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  350. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
  351. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  352. data/lib/rails/generators/active_record/migration.rb +9 -3
  353. data/lib/rails/generators/active_record/model/USAGE +113 -0
  354. data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
  355. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  356. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  357. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  358. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  359. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  360. metadata +117 -30
  361. data/lib/active_record/attribute_decorators.rb +0 -90
  362. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  363. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  364. data/lib/active_record/define_callbacks.rb +0 -22
  365. data/lib/active_record/null_relation.rb +0 -68
  366. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  367. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  368. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  369. data/lib/arel/attributes.rb +0 -22
  370. data/lib/arel/visitors/depth_first.rb +0 -204
  371. data/lib/arel/visitors/ibm_db.rb +0 -34
  372. data/lib/arel/visitors/informix.rb +0 -62
  373. data/lib/arel/visitors/mssql.rb +0 -157
  374. data/lib/arel/visitors/oracle.rb +0 -159
  375. data/lib/arel/visitors/oracle12.rb +0 -66
  376. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class AsynchronousQueriesTracker # :nodoc:
5
+ module NullSession # :nodoc:
6
+ class << self
7
+ def active?
8
+ true
9
+ end
10
+
11
+ def finalize
12
+ end
13
+ end
14
+ end
15
+
16
+ class Session # :nodoc:
17
+ def initialize
18
+ @active = true
19
+ end
20
+
21
+ def active?
22
+ @active
23
+ end
24
+
25
+ def finalize
26
+ @active = false
27
+ end
28
+ end
29
+
30
+ class << self
31
+ def install_executor_hooks(executor = ActiveSupport::Executor)
32
+ executor.register_hook(self)
33
+ end
34
+
35
+ def run
36
+ ActiveRecord::Base.asynchronous_queries_tracker.start_session
37
+ end
38
+
39
+ def complete(asynchronous_queries_tracker)
40
+ asynchronous_queries_tracker.finalize_session
41
+ end
42
+ end
43
+
44
+ attr_reader :current_session
45
+
46
+ def initialize
47
+ @current_session = NullSession
48
+ end
49
+
50
+ def start_session
51
+ @current_session = Session.new
52
+ self
53
+ end
54
+
55
+ def finalize_session
56
+ @current_session.finalize
57
+ @current_session = NullSession
58
+ end
59
+ end
60
+ end
@@ -1,28 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_model/forbidden_attributes_protection"
4
-
5
3
  module ActiveRecord
6
4
  module AttributeAssignment
7
- include ActiveModel::AttributeAssignment
8
-
9
5
  private
10
-
11
6
  def _assign_attributes(attributes)
12
- multi_parameter_attributes = {}
13
- nested_parameter_attributes = {}
7
+ multi_parameter_attributes = nested_parameter_attributes = nil
14
8
 
15
9
  attributes.each do |k, v|
16
- if k.include?("(")
17
- multi_parameter_attributes[k] = attributes.delete(k)
10
+ key = k.to_s
11
+
12
+ if key.include?("(")
13
+ (multi_parameter_attributes ||= {})[key] = v
18
14
  elsif v.is_a?(Hash)
19
- nested_parameter_attributes[k] = attributes.delete(k)
15
+ (nested_parameter_attributes ||= {})[key] = v
16
+ else
17
+ _assign_attribute(key, v)
20
18
  end
21
19
  end
22
- super(attributes)
23
20
 
24
- assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
25
- assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
21
+ assign_nested_parameter_attributes(nested_parameter_attributes) if nested_parameter_attributes
22
+ assign_multiparameter_attributes(multi_parameter_attributes) if multi_parameter_attributes
26
23
  end
27
24
 
28
25
  # Assign any deferred nested attributes after the base attributes have been set.
@@ -45,7 +42,7 @@ module ActiveRecord
45
42
  def execute_callstack_for_multiparameter_attributes(callstack)
46
43
  errors = []
47
44
  callstack.each do |name, values_with_empty_parameters|
48
- if values_with_empty_parameters.each_value.all?(&:nil?)
45
+ if values_with_empty_parameters.each_value.all?(NilClass)
49
46
  values = nil
50
47
  else
51
48
  values = values_with_empty_parameters
@@ -29,8 +29,8 @@ module ActiveRecord
29
29
  extend ActiveSupport::Concern
30
30
 
31
31
  included do
32
- attribute_method_suffix "_before_type_cast"
33
- attribute_method_suffix "_came_from_user?"
32
+ attribute_method_suffix "_before_type_cast", "_for_database", parameters: false
33
+ attribute_method_suffix "_came_from_user?", parameters: false
34
34
  end
35
35
 
36
36
  # Returns the value of the attribute identified by +attr_name+ before
@@ -46,8 +46,27 @@ module ActiveRecord
46
46
  # task.read_attribute_before_type_cast('completed_on') # => "2012-10-21"
47
47
  # task.read_attribute_before_type_cast(:completed_on) # => "2012-10-21"
48
48
  def read_attribute_before_type_cast(attr_name)
49
- sync_with_transaction_state if @transaction_state&.finalized?
50
- @attributes[attr_name.to_s].value_before_type_cast
49
+ name = attr_name.to_s
50
+ name = self.class.attribute_aliases[name] || name
51
+
52
+ attribute_before_type_cast(name)
53
+ end
54
+
55
+ # Returns the value of the attribute identified by +attr_name+ after
56
+ # serialization.
57
+ #
58
+ # class Book < ActiveRecord::Base
59
+ # enum :status, { draft: 1, published: 2 }
60
+ # end
61
+ #
62
+ # book = Book.new(status: "published")
63
+ # book.read_attribute(:status) # => "published"
64
+ # book.read_attribute_for_database(:status) # => 2
65
+ def read_attribute_for_database(attr_name)
66
+ name = attr_name.to_s
67
+ name = self.class.attribute_aliases[name] || name
68
+
69
+ attribute_for_database(name)
51
70
  end
52
71
 
53
72
  # Returns a hash of attributes before typecasting and deserialization.
@@ -61,20 +80,26 @@ module ActiveRecord
61
80
  # task.attributes_before_type_cast
62
81
  # # => {"id"=>nil, "title"=>nil, "is_done"=>true, "completed_on"=>"2012-10-21", "created_at"=>nil, "updated_at"=>nil}
63
82
  def attributes_before_type_cast
64
- sync_with_transaction_state if @transaction_state&.finalized?
65
83
  @attributes.values_before_type_cast
66
84
  end
67
85
 
68
- private
86
+ # Returns a hash of attributes for assignment to the database.
87
+ def attributes_for_database
88
+ @attributes.values_for_database
89
+ end
69
90
 
91
+ private
70
92
  # Dispatch target for <tt>*_before_type_cast</tt> attribute methods.
71
- def attribute_before_type_cast(attribute_name)
72
- read_attribute_before_type_cast(attribute_name)
93
+ def attribute_before_type_cast(attr_name)
94
+ @attributes[attr_name].value_before_type_cast
95
+ end
96
+
97
+ def attribute_for_database(attr_name)
98
+ @attributes[attr_name].value_for_database
73
99
  end
74
100
 
75
- def attribute_came_from_user?(attribute_name)
76
- sync_with_transaction_state if @transaction_state&.finalized?
77
- @attributes[attribute_name].came_from_user?
101
+ def attribute_came_from_user?(attr_name)
102
+ @attributes[attr_name].came_from_user?
78
103
  end
79
104
  end
80
105
  end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module AttributeMethods
5
+ module CompositePrimaryKey # :nodoc:
6
+ # Returns the primary key column's value. If the primary key is composite,
7
+ # returns an array of the primary key column values.
8
+ def id
9
+ if self.class.composite_primary_key?
10
+ @primary_key.map { |pk| _read_attribute(pk) }
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ def primary_key_values_present? # :nodoc:
17
+ if self.class.composite_primary_key?
18
+ id.all?
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ # Sets the primary key column's value. If the primary key is composite,
25
+ # raises TypeError when the set value not enumerable.
26
+ def id=(value)
27
+ if self.class.composite_primary_key?
28
+ raise TypeError, "Expected value matching #{self.class.primary_key.inspect}, got #{value.inspect}." unless value.is_a?(Enumerable)
29
+ @primary_key.zip(value) { |attr, value| _write_attribute(attr, value) }
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ # Queries the primary key column's value. If the primary key is composite,
36
+ # all primary key column values must be queryable.
37
+ def id?
38
+ if self.class.composite_primary_key?
39
+ @primary_key.all? { |col| _query_attribute(col) }
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ # Returns the primary key column's value before type cast. If the primary key is composite,
46
+ # returns an array of primary key column values before type cast.
47
+ def id_before_type_cast
48
+ if self.class.composite_primary_key?
49
+ @primary_key.map { |col| attribute_before_type_cast(col) }
50
+ else
51
+ super
52
+ end
53
+ end
54
+
55
+ # Returns the primary key column's previous value. If the primary key is composite,
56
+ # returns an array of primary key column previous values.
57
+ def id_was
58
+ if self.class.composite_primary_key?
59
+ @primary_key.map { |col| attribute_was(col) }
60
+ else
61
+ super
62
+ end
63
+ end
64
+
65
+ # Returns the primary key column's value from the database. If the primary key is composite,
66
+ # returns an array of primary key column values from database.
67
+ def id_in_database
68
+ if self.class.composite_primary_key?
69
+ @primary_key.map { |col| attribute_in_database(col) }
70
+ else
71
+ super
72
+ end
73
+ end
74
+
75
+ def id_for_database # :nodoc:
76
+ if self.class.composite_primary_key?
77
+ @primary_key.map { |col| @attributes[col].value_for_database }
78
+ else
79
+ super
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -4,6 +4,38 @@ require "active_support/core_ext/module/attribute_accessors"
4
4
 
5
5
  module ActiveRecord
6
6
  module AttributeMethods
7
+ # = Active Record Attribute Methods \Dirty
8
+ #
9
+ # Provides a way to track changes in your Active Record models. It adds all
10
+ # methods from ActiveModel::Dirty and adds database-specific methods.
11
+ #
12
+ # A newly created +Person+ object is unchanged:
13
+ #
14
+ # class Person < ActiveRecord::Base
15
+ # end
16
+ #
17
+ # person = Person.create(name: "Allison")
18
+ # person.changed? # => false
19
+ #
20
+ # Change the name:
21
+ #
22
+ # person.name = 'Alice'
23
+ # person.name_in_database # => "Allison"
24
+ # person.will_save_change_to_name? # => true
25
+ # person.name_change_to_be_saved # => ["Allison", "Alice"]
26
+ # person.changes_to_save # => {"name"=>["Allison", "Alice"]}
27
+ #
28
+ # Save the changes:
29
+ #
30
+ # person.save
31
+ # person.name_in_database # => "Alice"
32
+ # person.saved_change_to_name? # => true
33
+ # person.saved_change_to_name # => ["Allison", "Alice"]
34
+ # person.name_before_last_save # => "Allison"
35
+ #
36
+ # Similar to ActiveModel::Dirty, methods can be invoked as
37
+ # +saved_change_to_name?+ or by passing an argument to the generic method
38
+ # <tt>saved_change_to_attribute?("name")</tt>.
7
39
  module Dirty
8
40
  extend ActiveSupport::Concern
9
41
 
@@ -14,16 +46,17 @@ module ActiveRecord
14
46
  raise "You cannot include Dirty after Timestamp"
15
47
  end
16
48
 
17
- class_attribute :partial_writes, instance_writer: false, default: true
49
+ class_attribute :partial_updates, instance_writer: false, default: true
50
+ class_attribute :partial_inserts, instance_writer: false, default: true
18
51
 
19
52
  # Attribute methods for "changed in last call to save?"
20
- attribute_method_affix(prefix: "saved_change_to_", suffix: "?")
21
- attribute_method_prefix("saved_change_to_")
22
- attribute_method_suffix("_before_last_save")
53
+ attribute_method_affix(prefix: "saved_change_to_", suffix: "?", parameters: "**options")
54
+ attribute_method_prefix("saved_change_to_", parameters: false)
55
+ attribute_method_suffix("_before_last_save", parameters: false)
23
56
 
24
57
  # Attribute methods for "will change if I call save?"
25
- attribute_method_affix(prefix: "will_save_change_to_", suffix: "?")
26
- attribute_method_suffix("_change_to_be_saved", "_in_database")
58
+ attribute_method_affix(prefix: "will_save_change_to_", suffix: "?", parameters: "**options")
59
+ attribute_method_suffix("_change_to_be_saved", "_in_database", parameters: false)
27
60
  end
28
61
 
29
62
  # <tt>reload</tt> the record and clears changed attributes.
@@ -43,13 +76,15 @@ module ActiveRecord
43
76
  #
44
77
  # ==== Options
45
78
  #
46
- # +from+ When passed, this method will return false unless the original
47
- # value is equal to the given option
79
+ # [+from+]
80
+ # When specified, this method will return false unless the original
81
+ # value is equal to the given value.
48
82
  #
49
- # +to+ When passed, this method will return false unless the value was
50
- # changed to the given value
83
+ # [+to+]
84
+ # When specified, this method will return false unless the value will be
85
+ # changed to the given value.
51
86
  def saved_change_to_attribute?(attr_name, **options)
52
- mutations_before_last_save.changed?(attr_name.to_s, options)
87
+ mutations_before_last_save.changed?(attr_name.to_s, **options)
53
88
  end
54
89
 
55
90
  # Returns the change to an attribute during the last save. If the
@@ -89,17 +124,19 @@ module ActiveRecord
89
124
  # This method is useful in validations and before callbacks to determine
90
125
  # if the next call to +save+ will change a particular attribute. It can be
91
126
  # invoked as +will_save_change_to_name?+ instead of
92
- # <tt>will_save_change_to_attribute("name")</tt>.
127
+ # <tt>will_save_change_to_attribute?("name")</tt>.
93
128
  #
94
129
  # ==== Options
95
130
  #
96
- # +from+ When passed, this method will return false unless the original
97
- # value is equal to the given option
131
+ # [+from+]
132
+ # When specified, this method will return false unless the original
133
+ # value is equal to the given value.
98
134
  #
99
- # +to+ When passed, this method will return false unless the value will be
100
- # changed to the given value
135
+ # [+to+]
136
+ # When specified, this method will return false unless the value will be
137
+ # changed to the given value.
101
138
  def will_save_change_to_attribute?(attr_name, **options)
102
- mutations_from_database.changed?(attr_name.to_s, options)
139
+ mutations_from_database.changed?(attr_name.to_s, **options)
103
140
  end
104
141
 
105
142
  # Returns the change to an attribute that will be persisted during the
@@ -156,20 +193,12 @@ module ActiveRecord
156
193
  end
157
194
 
158
195
  private
159
- def mutations_from_database
160
- sync_with_transaction_state if @transaction_state&.finalized?
196
+ def init_internals
161
197
  super
162
- end
163
-
164
- def mutations_before_last_save
165
- sync_with_transaction_state if @transaction_state&.finalized?
166
- super
167
- end
168
-
169
- def write_attribute_without_type_cast(attr_name, value)
170
- result = super
171
- clear_attribute_change(attr_name)
172
- result
198
+ @mutations_before_last_save = nil
199
+ @mutations_from_database = nil
200
+ @_touch_attr_names = nil
201
+ @_skip_dirty_tracking = nil
173
202
  end
174
203
 
175
204
  def _touch_row(attribute_names, time)
@@ -201,20 +230,32 @@ module ActiveRecord
201
230
  @_touch_attr_names, @_skip_dirty_tracking = nil, nil
202
231
  end
203
232
 
204
- def _update_record(attribute_names = attribute_names_for_partial_writes)
233
+ def _update_record(attribute_names = attribute_names_for_partial_updates)
205
234
  affected_rows = super
206
235
  changes_applied
207
236
  affected_rows
208
237
  end
209
238
 
210
- def _create_record(attribute_names = attribute_names_for_partial_writes)
239
+ def _create_record(attribute_names = attribute_names_for_partial_inserts)
211
240
  id = super
212
241
  changes_applied
213
242
  id
214
243
  end
215
244
 
216
- def attribute_names_for_partial_writes
217
- partial_writes? ? changed_attribute_names_to_save : attribute_names
245
+ def attribute_names_for_partial_updates
246
+ partial_updates? ? changed_attribute_names_to_save : attribute_names
247
+ end
248
+
249
+ def attribute_names_for_partial_inserts
250
+ if partial_inserts?
251
+ changed_attribute_names_to_save
252
+ else
253
+ attribute_names.reject do |attr_name|
254
+ if column_for_attribute(attr_name).auto_populated?
255
+ !attribute_changed?(attr_name)
256
+ end
257
+ end
258
+ end
218
259
  end
219
260
  end
220
261
  end
@@ -4,6 +4,7 @@ require "set"
4
4
 
5
5
  module ActiveRecord
6
6
  module AttributeMethods
7
+ # = Active Record Attribute Methods Primary Key
7
8
  module PrimaryKey
8
9
  extend ActiveSupport::Concern
9
10
 
@@ -11,47 +12,61 @@ module ActiveRecord
11
12
  # available.
12
13
  def to_key
13
14
  key = id
14
- [key] if key
15
+ Array(key) if key
15
16
  end
16
17
 
17
- # Returns the primary key column's value.
18
+ # Returns the primary key column's value. If the primary key is composite,
19
+ # returns an array of the primary key column values.
18
20
  def id
19
21
  _read_attribute(@primary_key)
20
22
  end
21
23
 
22
- # Sets the primary key column's value.
24
+ def primary_key_values_present? # :nodoc:
25
+ !!id
26
+ end
27
+
28
+ # Sets the primary key column's value. If the primary key is composite,
29
+ # raises TypeError when the set value not enumerable.
23
30
  def id=(value)
24
31
  _write_attribute(@primary_key, value)
25
32
  end
26
33
 
27
- # Queries the primary key column's value.
34
+ # Queries the primary key column's value. If the primary key is composite,
35
+ # all primary key column values must be queryable.
28
36
  def id?
29
- query_attribute(@primary_key)
37
+ _query_attribute(@primary_key)
30
38
  end
31
39
 
32
- # Returns the primary key column's value before type cast.
40
+ # Returns the primary key column's value before type cast. If the primary key is composite,
41
+ # returns an array of primary key column values before type cast.
33
42
  def id_before_type_cast
34
- read_attribute_before_type_cast(@primary_key)
43
+ attribute_before_type_cast(@primary_key)
35
44
  end
36
45
 
37
- # Returns the primary key column's previous value.
46
+ # Returns the primary key column's previous value. If the primary key is composite,
47
+ # returns an array of primary key column previous values.
38
48
  def id_was
39
49
  attribute_was(@primary_key)
40
50
  end
41
51
 
42
- # Returns the primary key column's value from the database.
52
+ # Returns the primary key column's value from the database. If the primary key is composite,
53
+ # returns an array of primary key column values from database.
43
54
  def id_in_database
44
55
  attribute_in_database(@primary_key)
45
56
  end
46
57
 
47
- private
58
+ def id_for_database # :nodoc:
59
+ @attributes[@primary_key].value_for_database
60
+ end
48
61
 
62
+ private
49
63
  def attribute_method?(attr_name)
50
64
  attr_name == "id" || super
51
65
  end
52
66
 
53
67
  module ClassMethods
54
- ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was id_in_database).to_set
68
+ ID_ATTRIBUTE_METHODS = %w(id id= id? id_before_type_cast id_was id_in_database id_for_database).to_set
69
+ PRIMARY_KEY_NOT_SET = BasicObject.new
55
70
 
56
71
  def instance_method_already_implemented?(method_name)
57
72
  super || primary_key && ID_ATTRIBUTE_METHODS.include?(method_name)
@@ -65,17 +80,22 @@ module ActiveRecord
65
80
  # Overwriting will negate any effect of the +primary_key_prefix_type+
66
81
  # setting, though.
67
82
  def primary_key
68
- @primary_key = reset_primary_key unless defined? @primary_key
83
+ reset_primary_key if PRIMARY_KEY_NOT_SET.equal?(@primary_key)
69
84
  @primary_key
70
85
  end
71
86
 
87
+ def composite_primary_key? # :nodoc:
88
+ reset_primary_key if PRIMARY_KEY_NOT_SET.equal?(@primary_key)
89
+ @composite_primary_key
90
+ end
91
+
72
92
  # Returns a quoted version of the primary key name, used to construct
73
93
  # SQL statements.
74
94
  def quoted_primary_key
75
- @quoted_primary_key ||= connection.quote_column_name(primary_key)
95
+ @quoted_primary_key ||= adapter_class.quote_column_name(primary_key)
76
96
  end
77
97
 
78
- def reset_primary_key #:nodoc:
98
+ def reset_primary_key # :nodoc:
79
99
  if base_class?
80
100
  self.primary_key = get_primary_key(base_class.name)
81
101
  else
@@ -83,18 +103,15 @@ module ActiveRecord
83
103
  end
84
104
  end
85
105
 
86
- def get_primary_key(base_name) #:nodoc:
106
+ def get_primary_key(base_name) # :nodoc:
87
107
  if base_name && primary_key_prefix_type == :table_name
88
108
  base_name.foreign_key(false)
89
109
  elsif base_name && primary_key_prefix_type == :table_name_with_underscore
90
110
  base_name.foreign_key
111
+ elsif ActiveRecord::Base != self && table_exists?
112
+ schema_cache.primary_keys(table_name)
91
113
  else
92
- if ActiveRecord::Base != self && table_exists?
93
- pk = connection.schema_cache.primary_keys(table_name)
94
- suppress_composite_primary_key(pk)
95
- else
96
- "id"
97
- end
114
+ "id"
98
115
  end
99
116
  end
100
117
 
@@ -114,21 +131,26 @@ module ActiveRecord
114
131
  #
115
132
  # Project.primary_key # => "foo_id"
116
133
  def primary_key=(value)
117
- @primary_key = value && -value.to_s
134
+ @primary_key = if value.is_a?(Array)
135
+ @composite_primary_key = true
136
+ include CompositePrimaryKey
137
+ @primary_key = value.map { |v| -v.to_s }.freeze
138
+ elsif value
139
+ -value.to_s
140
+ end
118
141
  @quoted_primary_key = nil
119
142
  @attributes_builder = nil
120
143
  end
121
144
 
122
145
  private
123
-
124
- def suppress_composite_primary_key(pk)
125
- return pk unless pk.is_a?(Array)
126
-
127
- warn <<~WARNING
128
- WARNING: Active Record does not support composite primary key.
129
-
130
- #{table_name} has composite primary key. Composite primary key is ignored.
131
- WARNING
146
+ def inherited(base)
147
+ super
148
+ base.class_eval do
149
+ @primary_key = PRIMARY_KEY_NOT_SET
150
+ @composite_primary_key = false
151
+ @quoted_primary_key = nil
152
+ @attributes_builder = nil
153
+ end
132
154
  end
133
155
  end
134
156
  end
@@ -2,40 +2,49 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module AttributeMethods
5
+ # = Active Record Attribute Methods \Query
5
6
  module Query
6
7
  extend ActiveSupport::Concern
7
8
 
8
9
  included do
9
- attribute_method_suffix "?"
10
+ attribute_method_suffix "?", parameters: false
10
11
  end
11
12
 
12
13
  def query_attribute(attr_name)
13
- value = self[attr_name]
14
-
15
- case value
16
- when true then true
17
- when false, nil then false
18
- else
19
- if !type_for_attribute(attr_name) { false }
20
- if Numeric === value || value !~ /[^0-9]/
21
- !value.to_i.zero?
14
+ value = self.public_send(attr_name)
15
+
16
+ query_cast_attribute(attr_name, value)
17
+ end
18
+
19
+ def _query_attribute(attr_name) # :nodoc:
20
+ value = self._read_attribute(attr_name.to_s)
21
+
22
+ query_cast_attribute(attr_name, value)
23
+ end
24
+
25
+ alias :attribute? :query_attribute
26
+ private :attribute?
27
+
28
+ private
29
+ def query_cast_attribute(attr_name, value)
30
+ case value
31
+ when true then true
32
+ when false, nil then false
33
+ else
34
+ if !type_for_attribute(attr_name) { false }
35
+ if Numeric === value || !value.match?(/[^0-9]/)
36
+ !value.to_i.zero?
37
+ else
38
+ return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value)
39
+ !value.blank?
40
+ end
41
+ elsif value.respond_to?(:zero?)
42
+ !value.zero?
22
43
  else
23
- return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value)
24
44
  !value.blank?
25
45
  end
26
- elsif value.respond_to?(:zero?)
27
- !value.zero?
28
- else
29
- !value.blank?
30
46
  end
31
47
  end
32
- end
33
-
34
- private
35
- # Dispatch target for <tt>*?</tt> attribute methods.
36
- def attribute?(attribute_name)
37
- query_attribute(attribute_name)
38
- end
39
48
  end
40
49
  end
41
50
  end