activerecord 7.0.8.7 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +781 -1777
- data/MIT-LICENSE +1 -1
- data/README.rdoc +30 -30
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +31 -23
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +40 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +35 -21
- data/lib/active_record/associations/collection_proxy.rb +29 -11
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +21 -14
- data/lib/active_record/associations/has_many_through_association.rb +17 -7
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +4 -3
- data/lib/active_record/associations/join_dependency.rb +10 -10
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +354 -485
- data/lib/active_record/attribute_assignment.rb +0 -4
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +131 -32
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +153 -33
- data/lib/active_record/attributes.rb +96 -71
- data/lib/active_record/autosave_association.rb +81 -39
- data/lib/active_record/base.rb +11 -7
- data/lib/active_record/callbacks.rb +11 -25
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +343 -91
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +229 -64
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +142 -12
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +310 -129
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +539 -111
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +289 -128
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
- data/lib/active_record/connection_adapters/mysql/quoting.rb +60 -55
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +108 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +371 -64
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +374 -203
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -45
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +51 -8
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +298 -113
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +124 -1
- data/lib/active_record/connection_handling.rb +101 -105
- data/lib/active_record/core.rb +273 -178
- data/lib/active_record/counter_cache.rb +69 -35
- data/lib/active_record/database_configurations/connection_url_resolver.rb +10 -3
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +56 -27
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +46 -22
- data/lib/active_record/encryption/encrypted_attribute_type.rb +48 -13
- data/lib/active_record/encryption/encryptor.rb +35 -19
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +22 -21
- data/lib/active_record/encryption.rb +3 -0
- data/lib/active_record/enum.rb +130 -28
- data/lib/active_record/errors.rb +154 -34
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +48 -10
- data/lib/active_record/fixtures.rb +167 -97
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +11 -8
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +18 -22
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +106 -8
- data/lib/active_record/migration/compatibility.rb +147 -5
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +236 -118
- data/lib/active_record/model_schema.rb +90 -102
- data/lib/active_record/nested_attributes.rb +48 -11
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +168 -339
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -25
- data/lib/active_record/query_logs.rb +96 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +35 -10
- data/lib/active_record/railtie.rb +131 -87
- data/lib/active_record/railties/controller_runtime.rb +22 -7
- data/lib/active_record/railties/databases.rake +147 -155
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +267 -69
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +270 -108
- data/lib/active_record/relation/delegation.rb +30 -19
- data/lib/active_record/relation/finder_methods.rb +97 -21
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +20 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +28 -16
- data/lib/active_record/relation/query_attribute.rb +3 -2
- data/lib/active_record/relation/query_methods.rb +585 -109
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +15 -21
- data/lib/active_record/relation.rb +592 -92
- data/lib/active_record/result.rb +49 -48
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +70 -25
- data/lib/active_record/schema.rb +8 -7
- data/lib/active_record/schema_dumper.rb +90 -23
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +3 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +33 -11
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +190 -118
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +23 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_fixtures.rb +170 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +108 -24
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +61 -11
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +247 -33
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +3 -1
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/crud.rb +2 -0
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +7 -3
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +7 -1
- data/lib/arel/visitors/dot.rb +3 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +114 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +56 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
data/CHANGELOG.md
CHANGED
|
@@ -1,2411 +1,1415 @@
|
|
|
1
|
-
## Rails 7.
|
|
2
|
-
|
|
3
|
-
* No changes.
|
|
1
|
+
## Rails 7.2.3 (October 28, 2025) ##
|
|
4
2
|
|
|
3
|
+
* Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
When altering a table in SQLite3 that is referenced by child tables with
|
|
6
|
+
`ON DELETE CASCADE` foreign keys, ActiveRecord would silently delete all
|
|
7
|
+
data from the child tables. This occurred because SQLite requires table
|
|
8
|
+
recreation for schema changes, and during this process the original table
|
|
9
|
+
is temporarily dropped, triggering CASCADE deletes on child tables.
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
The root cause was incorrect ordering of operations. The original code
|
|
12
|
+
wrapped `disable_referential_integrity` inside a transaction, but
|
|
13
|
+
`PRAGMA foreign_keys` cannot be modified inside a transaction in SQLite -
|
|
14
|
+
attempting to do so simply has no effect. This meant foreign keys remained
|
|
15
|
+
enabled during table recreation, causing CASCADE deletes to fire.
|
|
9
16
|
|
|
17
|
+
The fix reverses the order to follow the official SQLite 12-step ALTER TABLE
|
|
18
|
+
procedure: `disable_referential_integrity` now wraps the transaction instead
|
|
19
|
+
of being wrapped by it. This ensures foreign keys are properly disabled
|
|
20
|
+
before the transaction starts and re-enabled after it commits, preventing
|
|
21
|
+
CASCADE deletes while maintaining data integrity through atomic transactions.
|
|
10
22
|
|
|
11
|
-
|
|
23
|
+
*Ruy Rocha*
|
|
12
24
|
|
|
13
|
-
*
|
|
25
|
+
* Fix `belongs_to` associations not to clear the entire composite primary key.
|
|
14
26
|
|
|
27
|
+
When clearing a `belongs_to` association that references a model with composite primary key,
|
|
28
|
+
only the optional part of the key should be cleared.
|
|
15
29
|
|
|
16
|
-
|
|
30
|
+
*zzak*
|
|
17
31
|
|
|
18
|
-
*
|
|
32
|
+
* Fix invalid records being autosaved when distantly associated records are marked for deletion.
|
|
19
33
|
|
|
34
|
+
*Ian Terrell*, *axlekb AB*
|
|
20
35
|
|
|
21
|
-
|
|
36
|
+
* Prevent persisting invalid record.
|
|
22
37
|
|
|
23
|
-
*
|
|
38
|
+
*Edouard Chin*
|
|
24
39
|
|
|
40
|
+
* Fix count with group by qualified name on loaded relation.
|
|
25
41
|
|
|
26
|
-
|
|
42
|
+
*Ryuta Kamizono*
|
|
27
43
|
|
|
28
|
-
*
|
|
44
|
+
* Fix `sum` with qualified name on loaded relation.
|
|
29
45
|
|
|
46
|
+
*Chris Gunther*
|
|
30
47
|
|
|
31
|
-
|
|
48
|
+
* Fix prepared statements on mysql2 adapter.
|
|
32
49
|
|
|
33
|
-
*
|
|
50
|
+
*Jean Boussier*
|
|
34
51
|
|
|
52
|
+
* Fix query cache for pinned connections in multi threaded transactional tests.
|
|
35
53
|
|
|
36
|
-
|
|
54
|
+
When a pinned connection is used across separate threads, they now use a separate cache store
|
|
55
|
+
for each thread.
|
|
37
56
|
|
|
38
|
-
|
|
39
|
-
using 7.0+ Migrations and SQLite.
|
|
57
|
+
This improve accuracy of system tests, and any test using multiple threads.
|
|
40
58
|
|
|
41
|
-
*
|
|
59
|
+
*Heinrich Lee Yu*, *Jean Boussier*
|
|
42
60
|
|
|
43
|
-
*
|
|
61
|
+
* Don't add `id_value` attribute alias when attribute/column with that name already exists.
|
|
44
62
|
|
|
45
|
-
|
|
46
|
-
```ruby
|
|
47
|
-
Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts` WHERE `posts`.`id` >= 1 AND `posts`.`id` < 3"
|
|
63
|
+
*Rob Lewis*
|
|
48
64
|
|
|
49
|
-
|
|
65
|
+
* Fix false positive change detection involving STI and polymorhic has one relationships.
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts`"
|
|
54
|
-
```
|
|
67
|
+
Polymorphic `has_one` relationships would always be considered changed when defined in a STI child
|
|
68
|
+
class, causing nedless extra autosaves.
|
|
55
69
|
|
|
56
|
-
|
|
70
|
+
*David Fritsch*
|
|
57
71
|
|
|
58
|
-
|
|
72
|
+
* Fix stale associaton detection for polymophic `belong_to`.
|
|
59
73
|
|
|
60
|
-
*
|
|
74
|
+
*Florent Beaurain*, *Thomas Crambert*
|
|
61
75
|
|
|
62
|
-
|
|
63
|
-
class Product < ApplicationRecord
|
|
64
|
-
has_many :requests, as: :requestable, class_name: "ProductRequest", dependent: :destroy
|
|
65
|
-
end
|
|
76
|
+
* Fix removal of PostgreSQL version comments in `structure.sql` for latest PostgreSQL versions which include `\restrict`.
|
|
66
77
|
|
|
67
|
-
|
|
68
|
-
class Request < ApplicationRecord
|
|
69
|
-
belongs_to :requestable, polymorphic: true
|
|
78
|
+
*Brendan Weibrecht*
|
|
70
79
|
|
|
71
|
-
|
|
72
|
-
end
|
|
80
|
+
* Fix `#merge` with `#or` or `#and` and a mixture of attributes and SQL strings resulting in an incorrect query.
|
|
73
81
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
82
|
+
```ruby
|
|
83
|
+
base = Comment.joins(:post).where(user_id: 1).where("recent = 1")
|
|
84
|
+
puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
|
|
77
85
|
```
|
|
78
86
|
|
|
79
|
-
|
|
87
|
+
Before:
|
|
80
88
|
|
|
89
|
+
```SQL
|
|
90
|
+
SELECT "comments".* FROM "comments"
|
|
91
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
92
|
+
WHERE (recent = 1)
|
|
93
|
+
AND (
|
|
94
|
+
"comments"."user_id" = 1
|
|
95
|
+
AND (recent = 1)
|
|
96
|
+
AND "comments"."draft" = 1
|
|
97
|
+
OR "posts"."archived" = 1
|
|
98
|
+
)
|
|
81
99
|
```
|
|
82
|
-
table_metadata.rb:22:in `has_column?': undefined method `key?' for nil:NilClass (NoMethodError)
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
*Romain Filinto*
|
|
86
|
-
|
|
87
|
-
* Fix `change_table` setting datetime precision for 6.1 Migrations
|
|
88
|
-
|
|
89
|
-
*Hartley McGuire*
|
|
90
|
-
|
|
91
|
-
* Fix change_column setting datetime precision for 6.1 Migrations
|
|
92
|
-
|
|
93
|
-
*Hartley McGuire*
|
|
94
|
-
|
|
95
|
-
## Rails 7.0.7.2 (August 22, 2023) ##
|
|
96
|
-
|
|
97
|
-
* No changes.
|
|
98
100
|
|
|
101
|
+
After:
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
```SQL
|
|
104
|
+
SELECT "comments".* FROM "comments"
|
|
105
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
106
|
+
WHERE "comments"."user_id" = 1
|
|
107
|
+
AND (recent = 1)
|
|
108
|
+
AND (
|
|
109
|
+
"comments"."user_id" = 1
|
|
110
|
+
AND (recent = 1)
|
|
111
|
+
AND "comments"."draft" = 1
|
|
112
|
+
OR "posts"."archived" = 1
|
|
113
|
+
)
|
|
114
|
+
```
|
|
103
115
|
|
|
116
|
+
*Joshua Young*
|
|
104
117
|
|
|
105
|
-
|
|
118
|
+
* Fix inline `has_and_belongs_to_many` fixtures for tables with composite primary keys.
|
|
106
119
|
|
|
107
|
-
*
|
|
120
|
+
*fatkodima*
|
|
108
121
|
|
|
109
|
-
|
|
122
|
+
* Fix `annotate` comments to propagate to `update_all`/`delete_all`.
|
|
110
123
|
|
|
111
|
-
*
|
|
124
|
+
*fatkodima*
|
|
112
125
|
|
|
113
|
-
|
|
126
|
+
* Fix checking whether an unpersisted record is `include?`d in a strictly
|
|
127
|
+
loaded `has_and_belongs_to_many` association.
|
|
114
128
|
|
|
115
|
-
*
|
|
129
|
+
*Hartley McGuire*
|
|
116
130
|
|
|
117
|
-
|
|
131
|
+
* Fix inline has_and_belongs_to_many fixtures for tables with composite primary keys.
|
|
118
132
|
|
|
119
|
-
*
|
|
133
|
+
*fatkodima*
|
|
120
134
|
|
|
121
|
-
|
|
135
|
+
* `create_or_find_by` will now correctly rollback a transaction.
|
|
122
136
|
|
|
123
|
-
|
|
124
|
-
|
|
137
|
+
When using `create_or_find_by`, raising a ActiveRecord::Rollback error
|
|
138
|
+
in a `after_save` callback had no effect, the transaction was committed
|
|
139
|
+
and a record created.
|
|
125
140
|
|
|
126
|
-
|
|
127
|
-
with `nil` titles, the same as `Post.all.to_a.in_order_of(:title, [nil, "foo"])`.
|
|
141
|
+
*Edouard Chin*
|
|
128
142
|
|
|
129
|
-
|
|
143
|
+
* Gracefully handle `Timeout.timeout` firing during connection configuration.
|
|
130
144
|
|
|
131
|
-
|
|
145
|
+
Use of `Timeout.timeout` could result in improperly initialized database connection.
|
|
132
146
|
|
|
133
|
-
This
|
|
134
|
-
|
|
147
|
+
This could lead to a partially configured connection being used, resulting in various exceptions,
|
|
148
|
+
the most common being with the PostgreSQLAdapter raising `undefined method 'key?' for nil`
|
|
149
|
+
or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
|
|
135
150
|
|
|
136
|
-
*
|
|
151
|
+
*Jean Boussier*
|
|
137
152
|
|
|
138
|
-
*
|
|
153
|
+
* The SQLite3 adapter quotes non-finite Numeric values like "Infinity" and "NaN".
|
|
139
154
|
|
|
140
|
-
|
|
141
|
-
Now, any UPDATE or DELETE to a record is considered a change, and will result in `#previously_new_record?`
|
|
142
|
-
returning false.
|
|
155
|
+
*Mike Dalessio*
|
|
143
156
|
|
|
144
|
-
|
|
157
|
+
* Handle libpq returning a database version of 0 on no/bad connection in `PostgreSQLAdapter`.
|
|
145
158
|
|
|
146
|
-
|
|
159
|
+
Before, this version would be cached and an error would be raised during connection configuration when
|
|
160
|
+
comparing it with the minimum required version for the adapter. This meant that the connection could
|
|
161
|
+
never be successfully configured on subsequent reconnection attempts.
|
|
147
162
|
|
|
148
|
-
|
|
163
|
+
Now, this is treated as a connection failure consistent with libpq, raising a `ActiveRecord::ConnectionFailed`
|
|
164
|
+
and ensuring the version isn't cached, which allows the version to be retrieved on the next connection attempt.
|
|
149
165
|
|
|
150
|
-
*
|
|
166
|
+
*Joshua Young*, *Rian McGuire*
|
|
151
167
|
|
|
152
|
-
|
|
153
|
-
the query cache, but this had the adverse effect to clearing the primary key when
|
|
154
|
-
the query argument contained an `ActiveRecord::Base` instance.
|
|
168
|
+
* Fix error handling during connection configuration.
|
|
155
169
|
|
|
156
|
-
|
|
170
|
+
Active Record wasn't properly handling errors during the connection configuration phase.
|
|
171
|
+
This could lead to a partially configured connection being used, resulting in various exceptions,
|
|
172
|
+
the most common being with the PostgreSQLAdapter raising `undefined method `key?' for nil`
|
|
173
|
+
or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
|
|
157
174
|
|
|
158
175
|
*Jean Boussier*
|
|
159
176
|
|
|
177
|
+
* Fix a case where a non-retryable query could be marked retryable.
|
|
160
178
|
|
|
161
|
-
|
|
179
|
+
*Hartley McGuire*
|
|
162
180
|
|
|
163
|
-
*
|
|
181
|
+
* Handle circular references when autosaving associations.
|
|
164
182
|
|
|
165
|
-
*
|
|
183
|
+
*zzak*
|
|
166
184
|
|
|
167
|
-
*
|
|
185
|
+
* Prevent persisting invalid record.
|
|
168
186
|
|
|
169
|
-
*
|
|
187
|
+
*Edouard Chin*
|
|
170
188
|
|
|
171
|
-
*
|
|
189
|
+
* Fix support for PostgreSQL enum types with commas in their name.
|
|
172
190
|
|
|
173
|
-
*
|
|
191
|
+
*Arthur Hess*
|
|
174
192
|
|
|
175
|
-
* Fix
|
|
193
|
+
* Fix inserts on MySQL with no RETURNING support for a table with multiple auto populated columns.
|
|
176
194
|
|
|
177
|
-
*
|
|
195
|
+
*Nikita Vasilevsky*
|
|
178
196
|
|
|
179
|
-
* Fix
|
|
197
|
+
* Fix joining on a scoped association with string joins and bind parameters.
|
|
180
198
|
|
|
181
|
-
Before:
|
|
182
199
|
```ruby
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
200
|
+
class Instructor < ActiveRecord::Base
|
|
201
|
+
has_many :instructor_roles, -> { active }
|
|
202
|
+
end
|
|
186
203
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
204
|
+
class InstructorRole < ActiveRecord::Base
|
|
205
|
+
scope :active, -> {
|
|
206
|
+
joins("JOIN students ON instructor_roles.student_id = students.id")
|
|
207
|
+
.where(students { status: 1 })
|
|
208
|
+
}
|
|
209
|
+
end
|
|
192
210
|
|
|
193
|
-
|
|
211
|
+
Instructor.joins(:instructor_roles).first
|
|
212
|
+
```
|
|
194
213
|
|
|
195
|
-
|
|
214
|
+
The above example would result in `ActiveRecord::StatementInvalid` because the
|
|
215
|
+
`active` scope bind parameters would be lost.
|
|
196
216
|
|
|
197
|
-
*
|
|
217
|
+
*Jean Boussier*
|
|
198
218
|
|
|
199
|
-
*
|
|
219
|
+
* Fix a potential race condition with system tests and transactional fixtures.
|
|
200
220
|
|
|
201
|
-
*
|
|
221
|
+
*Sjoerd Lagarde*
|
|
202
222
|
|
|
203
|
-
*
|
|
223
|
+
* Fix count with group by qualified name on loaded relation.
|
|
204
224
|
|
|
205
|
-
*
|
|
225
|
+
*Ryuta Kamizono*
|
|
206
226
|
|
|
207
|
-
*
|
|
227
|
+
* Fix sum with qualified name on loaded relation.
|
|
208
228
|
|
|
209
|
-
*
|
|
229
|
+
*Chris Gunther*
|
|
210
230
|
|
|
211
|
-
* Fix
|
|
231
|
+
* Fix autosave associations to no longer validated unmodified associated records.
|
|
212
232
|
|
|
213
|
-
|
|
233
|
+
Active Record was incorrectly performing validation on associated record that
|
|
234
|
+
weren't created nor modified as part of the transaction:
|
|
214
235
|
|
|
236
|
+
```ruby
|
|
237
|
+
Post.create!(author: User.find(1)) # Fail if user is invalid
|
|
238
|
+
```
|
|
215
239
|
|
|
216
|
-
|
|
240
|
+
*Jean Boussier*
|
|
217
241
|
|
|
218
|
-
*
|
|
242
|
+
* Remember when a database connection has recently been verified (for
|
|
243
|
+
two seconds, by default), to avoid repeated reverifications during a
|
|
244
|
+
single request.
|
|
219
245
|
|
|
220
|
-
|
|
246
|
+
This should recreate a similar rate of verification as in Rails 7.1,
|
|
247
|
+
where connections are leased for the duration of a request, and thus
|
|
248
|
+
only verified once.
|
|
221
249
|
|
|
222
|
-
*
|
|
250
|
+
*Matthew Draper*
|
|
223
251
|
|
|
224
|
-
|
|
252
|
+
* Fix prepared statements on mysql2 adapter.
|
|
225
253
|
|
|
226
|
-
*
|
|
254
|
+
*Jean Boussier*
|
|
227
255
|
|
|
228
|
-
|
|
256
|
+
* Fix a race condition in `ActiveRecord::Base#method_missing` when lazily defining attributes.
|
|
229
257
|
|
|
230
|
-
|
|
258
|
+
If multiple thread were concurrently triggering attribute definition on the same model,
|
|
259
|
+
it could result in a `NoMethodError` being raised.
|
|
231
260
|
|
|
232
|
-
*
|
|
261
|
+
*Jean Boussier*
|
|
233
262
|
|
|
234
|
-
* Fix
|
|
263
|
+
* Fix MySQL default functions getting dropped when changing a column's nullability.
|
|
235
264
|
|
|
236
|
-
*
|
|
265
|
+
*Bastian Bartmann*
|
|
237
266
|
|
|
238
|
-
*
|
|
267
|
+
* Fix `add_unique_constraint`/`add_check_constraint`/`/`add_foreign_key` to be revertible when
|
|
268
|
+
given invalid options.
|
|
239
269
|
|
|
240
|
-
*
|
|
270
|
+
*fatkodima*
|
|
241
271
|
|
|
242
|
-
*
|
|
272
|
+
* Fix asynchronous destroying of polymorphic `belongs_to` associations.
|
|
243
273
|
|
|
244
274
|
*fatkodima*
|
|
245
275
|
|
|
246
|
-
*
|
|
276
|
+
* NOT VALID constraints should not dump in `create_table`.
|
|
247
277
|
|
|
248
|
-
*
|
|
278
|
+
*Ryuta Kamizono*
|
|
249
279
|
|
|
250
|
-
* Fix
|
|
280
|
+
* Fix finding by nil composite primary key association.
|
|
251
281
|
|
|
252
282
|
*fatkodima*
|
|
253
283
|
|
|
254
|
-
*
|
|
284
|
+
* Fix parsing of SQLite foreign key names when they contain non-ASCII characters
|
|
255
285
|
|
|
256
|
-
*
|
|
286
|
+
*Zacharias Knudsen*
|
|
257
287
|
|
|
258
|
-
* Fix
|
|
288
|
+
* Fix parsing of MySQL 8.0.16+ CHECK constraints when they contain new lines.
|
|
259
289
|
|
|
260
|
-
*
|
|
290
|
+
*Steve Hill*
|
|
261
291
|
|
|
262
|
-
*
|
|
292
|
+
* Ensure normalized attribute queries use `IS NULL` consistently for `nil` and normalized `nil` values.
|
|
263
293
|
|
|
264
294
|
*Joshua Young*
|
|
265
295
|
|
|
266
|
-
*
|
|
296
|
+
* Restore back the ability to pass only database name for `DATABASE_URL`.
|
|
267
297
|
|
|
268
298
|
*fatkodima*
|
|
269
299
|
|
|
270
|
-
* Fix
|
|
300
|
+
* Fix `order` with using association name as an alias.
|
|
271
301
|
|
|
272
|
-
*
|
|
302
|
+
*Ryuta Kamizono*
|
|
273
303
|
|
|
274
|
-
*
|
|
304
|
+
* Improve invalid argument error for with.
|
|
275
305
|
|
|
276
|
-
*
|
|
306
|
+
*Ryuta Kamizono*
|
|
277
307
|
|
|
278
|
-
*
|
|
308
|
+
* Deduplicate `with` CTE expressions.
|
|
279
309
|
|
|
280
310
|
*fatkodima*
|
|
281
311
|
|
|
282
|
-
* Fix schema cache dumping of virtual columns.
|
|
283
|
-
|
|
284
|
-
*fatkodima*
|
|
285
312
|
|
|
286
|
-
|
|
313
|
+
## Rails 7.2.2.2 (August 13, 2025) ##
|
|
287
314
|
|
|
288
|
-
|
|
315
|
+
* Call inspect on ids in RecordNotFound error
|
|
289
316
|
|
|
290
|
-
|
|
317
|
+
[CVE-2025-55193]
|
|
291
318
|
|
|
292
|
-
*
|
|
319
|
+
*Gannon McGibbon*, *John Hawthorn*
|
|
293
320
|
|
|
294
|
-
* Fix a bug where using groups and counts with long table names would return incorrect results.
|
|
295
321
|
|
|
296
|
-
|
|
322
|
+
## Rails 7.2.2.1 (December 10, 2024) ##
|
|
297
323
|
|
|
298
|
-
*
|
|
324
|
+
* No changes.
|
|
299
325
|
|
|
300
|
-
Prior to this change, virtual datetime columns did not have the same
|
|
301
|
-
default precision as regular datetime columns, resulting in the following
|
|
302
|
-
being erroneously equivalent:
|
|
303
326
|
|
|
304
|
-
|
|
305
|
-
t.virtual :name, type: datetime, precision: nil, as: "expression"
|
|
327
|
+
## Rails 7.2.2 (October 30, 2024) ##
|
|
306
328
|
|
|
307
|
-
|
|
308
|
-
datetime column default precisions match.
|
|
329
|
+
* Fix support for `query_cache: false` in `database.yml`.
|
|
309
330
|
|
|
310
|
-
|
|
331
|
+
`query_cache: false` would no longer entirely disable the Active Record query cache.
|
|
311
332
|
|
|
312
|
-
*
|
|
333
|
+
*zzak*
|
|
313
334
|
|
|
314
|
-
|
|
335
|
+
* Set `.attributes_for_inspect` to `:all` by default.
|
|
315
336
|
|
|
337
|
+
For new applications it is set to `[:id]` in config/environment/production.rb.
|
|
316
338
|
|
|
317
|
-
|
|
339
|
+
In the console all the attributes are always shown.
|
|
318
340
|
|
|
319
|
-
*
|
|
341
|
+
*Andrew Novoselac*
|
|
320
342
|
|
|
343
|
+
* `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
|
|
321
344
|
|
|
322
|
-
|
|
345
|
+
*Kazuma Watanabe*
|
|
323
346
|
|
|
324
|
-
*
|
|
347
|
+
* Fix marshalling of unsaved associated records in 7.1 format.
|
|
325
348
|
|
|
349
|
+
The 7.1 format would only marshal associated records if the association was loaded.
|
|
350
|
+
But associations that would only contain unsaved records would be skipped.
|
|
326
351
|
|
|
327
|
-
|
|
352
|
+
*Jean Boussier*
|
|
328
353
|
|
|
329
|
-
*
|
|
354
|
+
* Fix incorrect SQL query when passing an empty hash to `ActiveRecord::Base.insert`.
|
|
330
355
|
|
|
331
|
-
|
|
332
|
-
attempting sanitization. That sanitization could be bypassed with
|
|
333
|
-
carefully crafted input.
|
|
356
|
+
*David Stosik*
|
|
334
357
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
first pass to remove one surrounding comment to avoid compatibility
|
|
338
|
-
issues for users relying on the existing removal.
|
|
358
|
+
* Allow to save records with polymorphic join tables that have `inverse_of`
|
|
359
|
+
specified.
|
|
339
360
|
|
|
340
|
-
|
|
341
|
-
be provided user input.
|
|
361
|
+
*Markus Doits*
|
|
342
362
|
|
|
343
|
-
|
|
363
|
+
* Fix association scopes applying on the incorrect join when using a polymorphic `has_many through:`.
|
|
344
364
|
|
|
345
|
-
*
|
|
365
|
+
*Joshua Young*
|
|
346
366
|
|
|
347
|
-
|
|
348
|
-
PostgreSQL will treat the column type as numeric. Comparing
|
|
349
|
-
integer values against numeric values can result in a slow
|
|
350
|
-
sequential scan.
|
|
367
|
+
* Fix `dependent: :destroy` for bi-directional has one through association.
|
|
351
368
|
|
|
352
|
-
|
|
353
|
-
ActiveRecord::Base.raise_int_wider_than_64bit which defaults to true.
|
|
369
|
+
Fixes #50948.
|
|
354
370
|
|
|
355
|
-
|
|
371
|
+
```ruby
|
|
372
|
+
class Left < ActiveRecord::Base
|
|
373
|
+
has_one :middle, dependent: :destroy
|
|
374
|
+
has_one :right, through: :middle
|
|
375
|
+
end
|
|
356
376
|
|
|
377
|
+
class Middle < ActiveRecord::Base
|
|
378
|
+
belongs_to :left, dependent: :destroy
|
|
379
|
+
belongs_to :right, dependent: :destroy
|
|
380
|
+
end
|
|
357
381
|
|
|
358
|
-
|
|
382
|
+
class Right < ActiveRecord::Base
|
|
383
|
+
has_one :middle, dependent: :destroy
|
|
384
|
+
has_one :left, through: :middle
|
|
385
|
+
end
|
|
386
|
+
```
|
|
387
|
+
In the above example `left.destroy` wouldn't destroy its associated `Right`
|
|
388
|
+
record.
|
|
359
389
|
|
|
360
|
-
*
|
|
390
|
+
*Andy Stewart*
|
|
361
391
|
|
|
362
|
-
|
|
392
|
+
* Properly handle lazily pinned connection pools.
|
|
363
393
|
|
|
364
|
-
|
|
394
|
+
Fixes #53147.
|
|
365
395
|
|
|
366
|
-
|
|
367
|
-
|
|
396
|
+
When using transactional fixtures with system tests to similar tools
|
|
397
|
+
such as capybara, it could happen that a connection end up pinned by the
|
|
398
|
+
server thread rather than the test thread, causing
|
|
399
|
+
`"Cannot expire connection, it is owned by a different thread"` errors.
|
|
368
400
|
|
|
369
401
|
*Jean Boussier*
|
|
370
402
|
|
|
371
|
-
*
|
|
372
|
-
|
|
373
|
-
This is required for correctly parsing `timestamp with time zone` values in your database.
|
|
403
|
+
* Fix `ActiveRecord::Base.with` to accept more than two sub queries.
|
|
374
404
|
|
|
375
|
-
|
|
405
|
+
Fixes #53110.
|
|
376
406
|
|
|
377
407
|
```ruby
|
|
378
|
-
|
|
408
|
+
User.with(foo: [User.select(:id), User.select(:id), User.select(:id)]).to_sql
|
|
409
|
+
undefined method `union' for an instance of Arel::Nodes::UnionAll (NoMethodError)
|
|
379
410
|
```
|
|
380
411
|
|
|
381
|
-
|
|
412
|
+
The above now works as expected.
|
|
382
413
|
|
|
383
|
-
*
|
|
414
|
+
*fatkodima*
|
|
384
415
|
|
|
385
|
-
|
|
386
|
-
# In database migrations
|
|
387
|
-
add_column :shops, :open_hours, :tsrange, array: true
|
|
388
|
-
# In app config
|
|
389
|
-
ActiveRecord::Base.time_zone_aware_types += [:tsrange]
|
|
390
|
-
# In the code times are properly converted to app time zone
|
|
391
|
-
Shop.create!(open_hours: [Time.current..8.hour.from_now])
|
|
392
|
-
```
|
|
416
|
+
* Properly release pinned connections with non joinable connections.
|
|
393
417
|
|
|
394
|
-
|
|
418
|
+
Fixes #52973
|
|
395
419
|
|
|
396
|
-
|
|
420
|
+
When running system tests with transactional fixtures on, it could happen that
|
|
421
|
+
the connection leased by the Puma thread wouldn't be properly released back to the pool,
|
|
422
|
+
causing "Cannot expire connection, it is owned by a different thread" errors in later tests.
|
|
397
423
|
|
|
398
|
-
|
|
399
|
-
ivar. This led to a confusing situation where despite having the correct data the relation
|
|
400
|
-
still reported a stale cache_version.
|
|
424
|
+
*Jean Boussier*
|
|
401
425
|
|
|
402
|
-
|
|
426
|
+
* Make Float distinguish between `float4` and `float8` in PostgreSQL.
|
|
403
427
|
|
|
404
|
-
|
|
405
|
-
developers = Developer.all
|
|
406
|
-
developers.cache_version
|
|
428
|
+
Fixes #52742
|
|
407
429
|
|
|
408
|
-
|
|
430
|
+
*Ryota Kitazawa*, *Takayuki Nagatomi*
|
|
409
431
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
developers.cache_version # Returns the current correct cache_version
|
|
413
|
-
```
|
|
432
|
+
* Fix an issue where `.left_outer_joins` used with multiple associations that have
|
|
433
|
+
the same child association but different parents does not join all parents.
|
|
414
434
|
|
|
415
|
-
|
|
435
|
+
Previously, using `.left_outer_joins` with the same child association would only join one of the parents.
|
|
416
436
|
|
|
417
|
-
|
|
437
|
+
Now it will correctly join both parents.
|
|
418
438
|
|
|
419
|
-
|
|
439
|
+
Fixes #41498.
|
|
420
440
|
|
|
421
|
-
|
|
422
|
-
a query but never use it.
|
|
441
|
+
*Garrett Blehm*
|
|
423
442
|
|
|
424
|
-
|
|
425
|
-
comments = post.comments.load_async # schedule a query
|
|
426
|
-
comments.to_a # perform an entirely new sync query
|
|
427
|
-
```
|
|
443
|
+
* Ensure `ActiveRecord::Encryption.config` is always ready before access.
|
|
428
444
|
|
|
429
|
-
|
|
430
|
-
|
|
445
|
+
Previously, `ActiveRecord::Encryption` configuration was deferred until `ActiveRecord::Base`
|
|
446
|
+
was loaded. Therefore, accessing `ActiveRecord::Encryption.config` properties before
|
|
447
|
+
`ActiveRecord::Base` was loaded would give incorrect results.
|
|
431
448
|
|
|
432
|
-
|
|
449
|
+
`ActiveRecord::Encryption` now has its own loading hook so that its configuration is set as
|
|
450
|
+
soon as needed.
|
|
433
451
|
|
|
434
|
-
|
|
452
|
+
When `ActiveRecord::Base` is loaded, even lazily, it in turn triggers the loading of
|
|
453
|
+
`ActiveRecord::Encryption`, thus preserving the original behavior of having its config ready
|
|
454
|
+
before any use of `ActiveRecord::Base`.
|
|
435
455
|
|
|
436
|
-
*
|
|
456
|
+
*Maxime Réty*
|
|
437
457
|
|
|
438
|
-
* `
|
|
458
|
+
* Add `TimeZoneConverter#==` method, so objects will be properly compared by
|
|
459
|
+
their type, scale, limit & precision.
|
|
439
460
|
|
|
440
|
-
|
|
441
|
-
way to dump a schema to both SQL and Ruby formats. You can now do this with
|
|
442
|
-
an environment variable. For example:
|
|
461
|
+
Address #52699.
|
|
443
462
|
|
|
444
|
-
|
|
445
|
-
SCHEMA_FORMAT=sql rake db:schema:dump
|
|
446
|
-
```
|
|
463
|
+
*Ruy Rocha*
|
|
447
464
|
|
|
448
|
-
*Alex Ghiculescu*
|
|
449
465
|
|
|
450
|
-
|
|
466
|
+
## Rails 7.2.1.2 (October 23, 2024) ##
|
|
451
467
|
|
|
452
|
-
|
|
468
|
+
* No changes.
|
|
453
469
|
|
|
454
470
|
|
|
455
|
-
## Rails 7.
|
|
471
|
+
## Rails 7.2.1.1 (October 15, 2024) ##
|
|
456
472
|
|
|
457
|
-
*
|
|
473
|
+
* No changes.
|
|
458
474
|
|
|
459
|
-
This adds two new configuration options The configuration options are as
|
|
460
|
-
follows:
|
|
461
475
|
|
|
462
|
-
|
|
476
|
+
## Rails 7.2.1 (August 22, 2024) ##
|
|
463
477
|
|
|
464
|
-
|
|
465
|
-
"unsafe" YAML loading strategy, maintaining the existing behavior but leaving
|
|
466
|
-
the possible escalation vulnerability in place. Setting this option to true
|
|
467
|
-
is *not* recommended, but can aid in upgrading.
|
|
478
|
+
* Fix detection for `enum` columns with parallelized tests and PostgreSQL.
|
|
468
479
|
|
|
469
|
-
*
|
|
480
|
+
*Rafael Mendonça França*
|
|
470
481
|
|
|
471
|
-
|
|
472
|
-
by default. This option allows you to specify classes deemed "safe" in your
|
|
473
|
-
application. For example, if your application uses Symbol and Time in
|
|
474
|
-
serialized data, you can add Symbol and Time to the allowed list as follows:
|
|
482
|
+
* Allow to eager load nested nil associations.
|
|
475
483
|
|
|
476
|
-
|
|
477
|
-
config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time]
|
|
478
|
-
```
|
|
484
|
+
*fatkodima*
|
|
479
485
|
|
|
480
|
-
|
|
486
|
+
* Fix swallowing ignore order warning when batching using `BatchEnumerator`.
|
|
481
487
|
|
|
488
|
+
*fatkodima*
|
|
482
489
|
|
|
483
|
-
|
|
490
|
+
* Fix memory bloat on the connection pool when using the Fiber `IsolatedExecutionState`.
|
|
484
491
|
|
|
485
|
-
*
|
|
486
|
-
methods in class objects that referenced reloadable constants. See
|
|
487
|
-
[#44125](https://github.com/rails/rails/issues/44125) for details.
|
|
492
|
+
*Jean Boussier*
|
|
488
493
|
|
|
489
|
-
|
|
494
|
+
* Restore inferred association class with the same modularized name.
|
|
490
495
|
|
|
491
|
-
*
|
|
496
|
+
*Justin Ko*
|
|
492
497
|
|
|
493
|
-
|
|
494
|
-
if using `db:schema:load`. Further more the function name would be
|
|
495
|
-
added as string content when saving new records.
|
|
498
|
+
* Fix `ActiveRecord::Base.inspect` to properly explain how to load schema information.
|
|
496
499
|
|
|
497
|
-
*
|
|
500
|
+
*Jean Boussier*
|
|
498
501
|
|
|
499
|
-
*
|
|
502
|
+
* Check invalid `enum` options for the new syntax.
|
|
500
503
|
|
|
501
|
-
|
|
504
|
+
The options using `_` prefix in the old syntax are invalid in the new syntax.
|
|
502
505
|
|
|
503
|
-
*
|
|
506
|
+
*Rafael Mendonça França*
|
|
504
507
|
|
|
505
|
-
|
|
506
|
-
|
|
508
|
+
* Fix `ActiveRecord::Encryption::EncryptedAttributeType#type` to return
|
|
509
|
+
actual cast type.
|
|
507
510
|
|
|
508
|
-
|
|
509
|
-
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-comments']
|
|
510
|
-
```
|
|
511
|
+
*Vasiliy Ermolovich*
|
|
511
512
|
|
|
512
|
-
|
|
513
|
+
* Fix `create_table` with `:auto_increment` option for MySQL adapter.
|
|
513
514
|
|
|
514
|
-
*
|
|
515
|
+
*fatkodima*
|
|
515
516
|
|
|
516
|
-
For example, when encrypting `Person#name` it will add `person.name` as a filter
|
|
517
|
-
parameter, instead of just `name`. This prevents unintended filtering of parameters
|
|
518
|
-
with a matching name in other models.
|
|
519
517
|
|
|
520
|
-
|
|
518
|
+
## Rails 7.2.0 (August 09, 2024) ##
|
|
521
519
|
|
|
522
|
-
*
|
|
520
|
+
* Handle commas in Sqlite3 default function definitions.
|
|
523
521
|
|
|
524
|
-
*
|
|
522
|
+
*Stephen Margheim*
|
|
525
523
|
|
|
526
|
-
*
|
|
524
|
+
* Fixes `validates_associated` raising an exception when configured with a
|
|
525
|
+
singular association and having `index_nested_attribute_errors` enabled.
|
|
527
526
|
|
|
528
|
-
*
|
|
527
|
+
*Martin Spickermann*
|
|
529
528
|
|
|
530
|
-
|
|
529
|
+
* The constant `ActiveRecord::ImmutableRelation` has been deprecated because
|
|
530
|
+
we want to reserve that name for a stronger sense of "immutable relation".
|
|
531
|
+
Please use `ActiveRecord::UnmodifiableRelation` instead.
|
|
531
532
|
|
|
532
|
-
*
|
|
533
|
+
*Xavier Noria*
|
|
533
534
|
|
|
535
|
+
* Add condensed `#inspect` for `ConnectionPool`, `AbstractAdapter`, and
|
|
536
|
+
`DatabaseConfig`.
|
|
534
537
|
|
|
535
|
-
|
|
538
|
+
*Hartley McGuire*
|
|
536
539
|
|
|
537
|
-
*
|
|
540
|
+
* Fixed a memory performance issue in Active Record attribute methods definition.
|
|
538
541
|
|
|
542
|
+
*Jean Boussier*
|
|
539
543
|
|
|
540
|
-
|
|
544
|
+
* Define the new Active Support notification event `start_transaction.active_record`.
|
|
541
545
|
|
|
542
|
-
|
|
546
|
+
This event is fired when database transactions or savepoints start, and
|
|
547
|
+
complements `transaction.active_record`, which is emitted when they finish.
|
|
543
548
|
|
|
549
|
+
The payload has the transaction (`:transaction`) and the connection (`:connection`).
|
|
544
550
|
|
|
545
|
-
|
|
551
|
+
*Xavier Noria*
|
|
546
552
|
|
|
547
|
-
*
|
|
553
|
+
* Fix an issue where the IDs reader method did not return expected results
|
|
554
|
+
for preloaded associations in models using composite primary keys.
|
|
548
555
|
|
|
556
|
+
*Jay Ang*
|
|
549
557
|
|
|
550
|
-
|
|
558
|
+
* The payload of `sql.active_record` Active Support notifications now has the current transaction in the `:transaction` key.
|
|
551
559
|
|
|
552
|
-
*
|
|
560
|
+
*Xavier Noria*
|
|
553
561
|
|
|
554
|
-
|
|
562
|
+
* The payload of `transaction.active_record` Active Support notifications now has the transaction the event is related to in the `:transaction` key.
|
|
555
563
|
|
|
556
|
-
*
|
|
564
|
+
*Xavier Noria*
|
|
557
565
|
|
|
558
|
-
|
|
566
|
+
* Define `ActiveRecord::Transaction#uuid`, which returns a UUID for the database transaction. This may be helpful when tracing database activity. These UUIDs are generated only on demand.
|
|
559
567
|
|
|
560
|
-
*
|
|
568
|
+
*Xavier Noria*
|
|
561
569
|
|
|
562
|
-
|
|
570
|
+
* Fix inference of association model on nested models with the same demodularized name.
|
|
563
571
|
|
|
564
|
-
|
|
572
|
+
E.g. with the following setup:
|
|
565
573
|
|
|
566
|
-
|
|
574
|
+
```ruby
|
|
575
|
+
class Nested::Post < ApplicationRecord
|
|
576
|
+
has_one :post, through: :other
|
|
577
|
+
end
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
Before, `#post` would infer the model as `Nested::Post`, but now it correctly infers `Post`.
|
|
567
581
|
|
|
568
|
-
*
|
|
582
|
+
*Joshua Young*
|
|
569
583
|
|
|
570
|
-
|
|
571
|
-
with a default precision of 6. This means that users upgrading to Rails 7.0 from 6.1,
|
|
572
|
-
when loading the database schema, would get the new precision value, which would not match
|
|
573
|
-
the production schema.
|
|
584
|
+
* PostgreSQL `Cidr#change?` detects the address prefix change.
|
|
574
585
|
|
|
575
|
-
|
|
576
|
-
version and will look like this:
|
|
586
|
+
*Taketo Takashima*
|
|
577
587
|
|
|
578
|
-
|
|
579
|
-
ActiveRecord::Schema[7.0].define
|
|
580
|
-
```
|
|
588
|
+
* Change `BatchEnumerator#destroy_all` to return the total number of affected rows.
|
|
581
589
|
|
|
582
|
-
|
|
583
|
-
set the current schema version to 6.1.
|
|
590
|
+
Previously, it always returned `nil`.
|
|
584
591
|
|
|
585
|
-
*
|
|
592
|
+
*fatkodima*
|
|
593
|
+
|
|
594
|
+
* Support `touch_all` in batches.
|
|
586
595
|
|
|
587
|
-
|
|
596
|
+
```ruby
|
|
597
|
+
Post.in_batches.touch_all
|
|
598
|
+
```
|
|
588
599
|
|
|
589
600
|
*fatkodima*
|
|
590
601
|
|
|
591
|
-
*
|
|
592
|
-
when bulk-inserting fixtures that exceed `max_allowed_packet` configuration.
|
|
602
|
+
* Add support for `:if_not_exists` and `:force` options to `create_schema`.
|
|
593
603
|
|
|
594
|
-
*
|
|
604
|
+
*fatkodima*
|
|
595
605
|
|
|
596
|
-
* Fix
|
|
606
|
+
* Fix `index_errors` having incorrect index in association validation errors.
|
|
597
607
|
|
|
598
|
-
*
|
|
608
|
+
*lulalala*
|
|
599
609
|
|
|
600
|
-
*
|
|
610
|
+
* Add `index_errors: :nested_attributes_order` mode.
|
|
601
611
|
|
|
602
|
-
|
|
612
|
+
This indexes the association validation errors based on the order received by nested attributes setter, and respects the `reject_if` configuration. This enables API to provide enough information to the frontend to map the validation errors back to their respective form fields.
|
|
603
613
|
|
|
604
|
-
*
|
|
614
|
+
*lulalala*
|
|
605
615
|
|
|
606
|
-
|
|
616
|
+
* Add `Rails.application.config.active_record.postgresql_adapter_decode_dates` to opt out of decoding dates automatically with the postgresql adapter. Defaults to true.
|
|
607
617
|
|
|
608
|
-
*
|
|
618
|
+
*Joé Dupuis*
|
|
609
619
|
|
|
610
|
-
|
|
620
|
+
* Association option `query_constraints` is deprecated in favor of `foreign_key`.
|
|
611
621
|
|
|
612
622
|
*Nikita Vasilevsky*
|
|
613
623
|
|
|
614
|
-
*
|
|
624
|
+
* Add `ENV["SKIP_TEST_DATABASE_TRUNCATE"]` flag to speed up multi-process test runs on large DBs when all tests run within default transaction.
|
|
615
625
|
|
|
616
|
-
|
|
626
|
+
This cuts ~10s from the test run of HEY when run by 24 processes against the 178 tables, since ~4,000 table truncates can then be skipped.
|
|
617
627
|
|
|
628
|
+
*DHH*
|
|
618
629
|
|
|
619
|
-
|
|
630
|
+
* Added support for recursive common table expressions.
|
|
620
631
|
|
|
632
|
+
```ruby
|
|
633
|
+
Post.with_recursive(
|
|
634
|
+
post_and_replies: [
|
|
635
|
+
Post.where(id: 42),
|
|
636
|
+
Post.joins('JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id'),
|
|
637
|
+
]
|
|
638
|
+
)
|
|
639
|
+
```
|
|
621
640
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
`in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version.
|
|
641
|
+
Generates the following SQL:
|
|
625
642
|
|
|
626
|
-
|
|
643
|
+
```sql
|
|
644
|
+
WITH RECURSIVE "post_and_replies" AS (
|
|
645
|
+
(SELECT "posts".* FROM "posts" WHERE "posts"."id" = 42)
|
|
646
|
+
UNION ALL
|
|
647
|
+
(SELECT "posts".* FROM "posts" JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id)
|
|
648
|
+
)
|
|
649
|
+
SELECT "posts".* FROM "posts"
|
|
650
|
+
```
|
|
627
651
|
|
|
628
|
-
*
|
|
652
|
+
*ClearlyClaire*
|
|
629
653
|
|
|
630
|
-
|
|
654
|
+
* `validate_constraint` can be called in a `change_table` block.
|
|
631
655
|
|
|
656
|
+
ex:
|
|
632
657
|
```ruby
|
|
633
|
-
|
|
658
|
+
change_table :products do |t|
|
|
659
|
+
t.check_constraint "price > discounted_price", name: "price_check", validate: false
|
|
660
|
+
t.validate_check_constraint "price_check"
|
|
661
|
+
end
|
|
634
662
|
```
|
|
635
663
|
|
|
636
|
-
|
|
664
|
+
*Cody Cutrer*
|
|
665
|
+
|
|
666
|
+
* `PostgreSQLAdapter` now decodes columns of type date to `Date` instead of string.
|
|
667
|
+
|
|
668
|
+
Ex:
|
|
669
|
+
```ruby
|
|
670
|
+
ActiveRecord::Base.connection
|
|
671
|
+
.select_value("select '2024-01-01'::date").class #=> Date
|
|
672
|
+
```
|
|
637
673
|
|
|
638
|
-
*
|
|
674
|
+
*Joé Dupuis*
|
|
639
675
|
|
|
640
|
-
*
|
|
676
|
+
* Strict loading using `:n_plus_one_only` does not eagerly load child associations.
|
|
641
677
|
|
|
642
|
-
|
|
678
|
+
With this change, child associations are no longer eagerly loaded, to
|
|
679
|
+
match intended behavior and to prevent non-deterministic order issues caused
|
|
680
|
+
by calling methods like `first` or `last`. As `first` and `last` don't cause
|
|
681
|
+
an N+1 by themselves, calling child associations will no longer raise.
|
|
682
|
+
Fixes #49473.
|
|
643
683
|
|
|
644
|
-
|
|
684
|
+
Before:
|
|
645
685
|
|
|
646
|
-
|
|
686
|
+
```ruby
|
|
687
|
+
person = Person.find(1)
|
|
688
|
+
person.strict_loading!(mode: :n_plus_one_only)
|
|
689
|
+
person.posts.first
|
|
690
|
+
# SELECT * FROM posts WHERE person_id = 1; -- non-deterministic order
|
|
691
|
+
person.posts.first.firm # raises ActiveRecord::StrictLoadingViolationError
|
|
692
|
+
```
|
|
647
693
|
|
|
648
|
-
|
|
694
|
+
After:
|
|
649
695
|
|
|
650
|
-
|
|
696
|
+
```ruby
|
|
697
|
+
person = Person.find(1)
|
|
698
|
+
person.strict_loading!(mode: :n_plus_one_only)
|
|
699
|
+
person.posts.first # this is 1+1, not N+1
|
|
700
|
+
# SELECT * FROM posts WHERE person_id = 1 ORDER BY id LIMIT 1;
|
|
701
|
+
person.posts.first.firm # no longer raises
|
|
702
|
+
```
|
|
651
703
|
|
|
652
|
-
*
|
|
704
|
+
*Reid Lynch*
|
|
653
705
|
|
|
654
|
-
|
|
706
|
+
* Allow `Sqlite3Adapter` to use `sqlite3` gem version `2.x`.
|
|
655
707
|
|
|
656
|
-
*
|
|
708
|
+
*Mike Dalessio*
|
|
657
709
|
|
|
658
|
-
*
|
|
710
|
+
* Allow `ActiveRecord::Base#pluck` to accept hash values.
|
|
659
711
|
|
|
660
|
-
|
|
712
|
+
```ruby
|
|
713
|
+
# Before
|
|
714
|
+
Post.joins(:comments).pluck("posts.id", "comments.id", "comments.body")
|
|
661
715
|
|
|
662
|
-
|
|
716
|
+
# After
|
|
717
|
+
Post.joins(:comments).pluck(posts: [:id], comments: [:id, :body])
|
|
718
|
+
```
|
|
663
719
|
|
|
664
720
|
*fatkodima*
|
|
665
721
|
|
|
666
|
-
*
|
|
722
|
+
* Raise an `ActiveRecord::ActiveRecordError` error when the MySQL database returns an invalid version string.
|
|
667
723
|
|
|
668
|
-
*
|
|
724
|
+
*Kevin McPhillips*
|
|
669
725
|
|
|
670
|
-
*
|
|
726
|
+
* `ActiveRecord::Base.transaction` now yields an `ActiveRecord::Transaction` object.
|
|
671
727
|
|
|
672
|
-
|
|
673
|
-
bigint instead of integer for the SQLite Adapter.
|
|
728
|
+
This allows to register callbacks on it.
|
|
674
729
|
|
|
675
|
-
|
|
730
|
+
```ruby
|
|
731
|
+
Article.transaction do |transaction|
|
|
732
|
+
article.update(published: true)
|
|
733
|
+
transaction.after_commit do
|
|
734
|
+
PublishNotificationMailer.with(article: article).deliver_later
|
|
735
|
+
end
|
|
736
|
+
end
|
|
737
|
+
```
|
|
676
738
|
|
|
677
|
-
*
|
|
739
|
+
*Jean Boussier*
|
|
678
740
|
|
|
679
|
-
|
|
741
|
+
* Add `ActiveRecord::Base.current_transaction`.
|
|
680
742
|
|
|
681
|
-
|
|
743
|
+
Returns the current transaction, to allow registering callbacks on it.
|
|
682
744
|
|
|
683
745
|
```ruby
|
|
684
|
-
|
|
746
|
+
Article.current_transaction.after_commit do
|
|
747
|
+
PublishNotificationMailer.with(article: article).deliver_later
|
|
748
|
+
end
|
|
685
749
|
```
|
|
686
750
|
|
|
687
|
-
Also more explicitly set the column as secondary order, so that any other
|
|
688
|
-
value is still ordered.
|
|
689
|
-
|
|
690
751
|
*Jean Boussier*
|
|
691
752
|
|
|
692
|
-
*
|
|
753
|
+
* Add `ActiveRecord.after_all_transactions_commit` callback.
|
|
693
754
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
* Fix quoting of column aliases generated by calculation methods.
|
|
697
|
-
|
|
698
|
-
Since the alias is derived from the table name, we can't assume the result
|
|
699
|
-
is a valid identifier.
|
|
755
|
+
Useful for code that may run either inside or outside a transaction and needs
|
|
756
|
+
to perform work after the state changes have been properly persisted.
|
|
700
757
|
|
|
701
758
|
```ruby
|
|
702
|
-
|
|
703
|
-
|
|
759
|
+
def publish_article(article)
|
|
760
|
+
article.update(published: true)
|
|
761
|
+
ActiveRecord.after_all_transactions_commit do
|
|
762
|
+
PublishNotificationMailer.with(article: article).deliver_later
|
|
763
|
+
end
|
|
704
764
|
end
|
|
705
|
-
Test.group(:id).count
|
|
706
|
-
# syntax error at or near "1" (ActiveRecord::StatementInvalid)
|
|
707
|
-
# LINE 1: SELECT COUNT(*) AS count_all, "1abc"."id" AS 1abc_id FROM "1...
|
|
708
765
|
```
|
|
709
766
|
|
|
767
|
+
In the above example, the block is either executed immediately if called outside
|
|
768
|
+
of a transaction, or called after the open transaction is committed.
|
|
769
|
+
|
|
770
|
+
If the transaction is rolled back, the block isn't called.
|
|
771
|
+
|
|
710
772
|
*Jean Boussier*
|
|
711
773
|
|
|
774
|
+
* Add the ability to ignore counter cache columns until they are backfilled.
|
|
712
775
|
|
|
713
|
-
|
|
776
|
+
Starting to use counter caches on existing large tables can be troublesome, because the column
|
|
777
|
+
values must be backfilled separately of the column addition (to not lock the table for too long)
|
|
778
|
+
and before the use of `:counter_cache` (otherwise methods like `size`/`any?`/etc, which use
|
|
779
|
+
counter caches internally, can produce incorrect results). People usually use database triggers
|
|
780
|
+
or callbacks on child associations while backfilling before introducing a counter cache
|
|
781
|
+
configuration to the association.
|
|
714
782
|
|
|
715
|
-
|
|
783
|
+
Now, to safely backfill the column, while keeping the column updated with child records added/removed, use:
|
|
716
784
|
|
|
717
785
|
```ruby
|
|
718
|
-
|
|
786
|
+
class Comment < ApplicationRecord
|
|
787
|
+
belongs_to :post, counter_cache: { active: false }
|
|
788
|
+
end
|
|
719
789
|
```
|
|
720
790
|
|
|
721
|
-
|
|
722
|
-
|
|
791
|
+
While the counter cache is not "active", the methods like `size`/`any?`/etc will not use it,
|
|
792
|
+
but get the results directly from the database. After the counter cache column is backfilled, simply
|
|
793
|
+
remove the `{ active: false }` part from the counter cache definition, and it will now be used by the
|
|
794
|
+
mentioned methods.
|
|
723
795
|
|
|
724
|
-
|
|
725
|
-
not be able to handle it, but will either succeed or failed in a more correct way.
|
|
796
|
+
*fatkodima*
|
|
726
797
|
|
|
727
|
-
|
|
798
|
+
* Retry known idempotent SELECT queries on connection-related exceptions.
|
|
728
799
|
|
|
729
|
-
|
|
800
|
+
SELECT queries we construct by walking the Arel tree and / or with known model attributes
|
|
801
|
+
are idempotent and can safely be retried in the case of a connection error. Previously,
|
|
802
|
+
adapters such as `TrilogyAdapter` would raise `ActiveRecord::ConnectionFailed: Trilogy::EOFError`
|
|
803
|
+
when encountering a connection error mid-request.
|
|
730
804
|
|
|
731
|
-
|
|
805
|
+
*Adrianna Chang*
|
|
732
806
|
|
|
733
|
-
|
|
807
|
+
* Allow association's `foreign_key` to be composite.
|
|
734
808
|
|
|
809
|
+
`query_constraints` option was the only way to configure a composite foreign key by passing an `Array`.
|
|
810
|
+
Now it's possible to pass an Array value as `foreign_key` to achieve the same behavior of an association.
|
|
735
811
|
|
|
736
|
-
|
|
812
|
+
*Nikita Vasilevsky*
|
|
737
813
|
|
|
738
|
-
*
|
|
814
|
+
* Allow association's `primary_key` to be composite.
|
|
739
815
|
|
|
816
|
+
Association's `primary_key` can be composite when derived from associated model `primary_key` or `query_constraints`.
|
|
817
|
+
Now it's possible to explicitly set it as composite on the association.
|
|
740
818
|
|
|
741
|
-
|
|
819
|
+
*Nikita Vasilevsky*
|
|
742
820
|
|
|
743
|
-
*
|
|
821
|
+
* Add `config.active_record.permanent_connection_checkout` setting.
|
|
744
822
|
|
|
823
|
+
Controls whether `ActiveRecord::Base.connection` raises an error, emits a deprecation warning, or neither.
|
|
745
824
|
|
|
746
|
-
|
|
825
|
+
`ActiveRecord::Base.connection` checkouts a database connection from the pool and keeps it leased until the end of
|
|
826
|
+
the request or job. This behavior can be undesirable in environments that use many more threads or fibers than there
|
|
827
|
+
is available connections.
|
|
747
828
|
|
|
748
|
-
|
|
829
|
+
This configuration can be used to track down and eliminate code that calls `ActiveRecord::Base.connection` and
|
|
830
|
+
migrate it to use `ActiveRecord::Base.with_connection` instead.
|
|
749
831
|
|
|
750
|
-
|
|
832
|
+
The default behavior remains unchanged, and there is currently no plans to change the default.
|
|
751
833
|
|
|
752
|
-
*
|
|
834
|
+
*Jean Boussier*
|
|
753
835
|
|
|
754
|
-
|
|
836
|
+
* Add dirties option to uncached.
|
|
755
837
|
|
|
756
|
-
|
|
838
|
+
This adds a `dirties` option to `ActiveRecord::Base.uncached` and
|
|
839
|
+
`ActiveRecord::ConnectionAdapters::ConnectionPool#uncached`.
|
|
757
840
|
|
|
758
|
-
|
|
841
|
+
When set to `true` (the default), writes will clear all query caches belonging to the current thread.
|
|
842
|
+
When set to `false`, writes to the affected connection pool will not clear any query cache.
|
|
759
843
|
|
|
760
|
-
|
|
844
|
+
This is needed by Solid Cache so that cache writes do not clear query caches.
|
|
761
845
|
|
|
762
|
-
*
|
|
846
|
+
*Donal McBreen*
|
|
763
847
|
|
|
764
|
-
*
|
|
848
|
+
* Deprecate `ActiveRecord::Base.connection` in favor of `.lease_connection`.
|
|
765
849
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
the value of these fields was not parsed and remained `nil`
|
|
850
|
+
The method has been renamed as `lease_connection` to better reflect that the returned
|
|
851
|
+
connection will be held for the duration of the request or job.
|
|
769
852
|
|
|
770
|
-
|
|
853
|
+
This deprecation is a soft deprecation, no warnings will be issued and there is no
|
|
854
|
+
current plan to remove the method.
|
|
771
855
|
|
|
772
|
-
*
|
|
856
|
+
*Jean Boussier*
|
|
773
857
|
|
|
774
|
-
|
|
858
|
+
* Deprecate `ActiveRecord::ConnectionAdapters::ConnectionPool#connection`.
|
|
775
859
|
|
|
776
|
-
|
|
860
|
+
The method has been renamed as `lease_connection` to better reflect that the returned
|
|
861
|
+
connection will be held for the duration of the request or job.
|
|
777
862
|
|
|
778
|
-
|
|
863
|
+
*Jean Boussier*
|
|
779
864
|
|
|
780
|
-
|
|
865
|
+
* Expose a generic fixture accessor for fixture names that may conflict with Minitest.
|
|
781
866
|
|
|
782
867
|
```ruby
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
end
|
|
786
|
-
|
|
787
|
-
Book.in_order_of(:status, %w[written published proposed])
|
|
868
|
+
assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
|
|
869
|
+
assert_equal "Ruby on Rails", fixture(:web_sites, :rubyonrails).name
|
|
788
870
|
```
|
|
789
871
|
|
|
790
|
-
*
|
|
872
|
+
*Jean Boussier*
|
|
791
873
|
|
|
792
|
-
*
|
|
874
|
+
* Using `Model.query_constraints` with a single non-primary-key column used to raise as expected, but with an
|
|
875
|
+
incorrect error message.
|
|
793
876
|
|
|
794
|
-
|
|
877
|
+
This has been fixed to raise with a more appropriate error message.
|
|
795
878
|
|
|
796
|
-
*
|
|
879
|
+
*Joshua Young*
|
|
797
880
|
|
|
798
|
-
|
|
881
|
+
* Fix `has_one` association autosave setting the foreign key attribute when it is unchanged.
|
|
799
882
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
[
|
|
803
|
-
{ id: 2, name: "Copper", price: 4.84 },
|
|
804
|
-
{ id: 4, name: "Gold", price: 1380.87 },
|
|
805
|
-
{ id: 6, name: "Aluminium", price: 0.35 }
|
|
806
|
-
],
|
|
807
|
-
update_only: [:price] # Only prices will be updated
|
|
808
|
-
)
|
|
809
|
-
```
|
|
883
|
+
This behavior is also inconsistent with autosaving `belongs_to` and can have unintended side effects like raising
|
|
884
|
+
an `ActiveRecord::ReadonlyAttributeError` when the foreign key attribute is marked as read-only.
|
|
810
885
|
|
|
811
|
-
*
|
|
886
|
+
*Joshua Young*
|
|
812
887
|
|
|
813
|
-
* Remove deprecated `
|
|
888
|
+
* Remove deprecated behavior that would rollback a transaction block when exited using `return`, `break` or `throw`.
|
|
814
889
|
|
|
815
890
|
*Rafael Mendonça França*
|
|
816
891
|
|
|
817
|
-
*
|
|
892
|
+
* Deprecate `Rails.application.config.active_record.commit_transaction_on_non_local_return`.
|
|
818
893
|
|
|
819
894
|
*Rafael Mendonça França*
|
|
820
895
|
|
|
821
|
-
* Remove deprecated `ActiveRecord::
|
|
896
|
+
* Remove deprecated support to pass `rewhere` to `ActiveRecord::Relation#merge`.
|
|
822
897
|
|
|
823
898
|
*Rafael Mendonça França*
|
|
824
899
|
|
|
825
|
-
* Remove deprecated `
|
|
900
|
+
* Remove deprecated support to pass `deferrable: true` to `add_foreign_key`.
|
|
826
901
|
|
|
827
902
|
*Rafael Mendonça França*
|
|
828
903
|
|
|
829
|
-
* Remove deprecated `
|
|
904
|
+
* Remove deprecated support to quote `ActiveSupport::Duration`.
|
|
830
905
|
|
|
831
906
|
*Rafael Mendonça França*
|
|
832
907
|
|
|
833
|
-
*
|
|
908
|
+
* Remove deprecated `#quote_bound_value`.
|
|
834
909
|
|
|
835
|
-
|
|
910
|
+
*Rafael Mendonça França*
|
|
836
911
|
|
|
837
|
-
|
|
912
|
+
* Remove deprecated `ActiveRecord::ConnectionAdapters::ConnectionPool#connection_klass`.
|
|
838
913
|
|
|
839
|
-
|
|
840
|
-
# Before:
|
|
841
|
-
Foo Load (0.2ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "hello"], ["LIMIT", 1]]
|
|
914
|
+
*Rafael Mendonça França*
|
|
842
915
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
916
|
+
* Remove deprecated support to apply `#connection_pool_list`, `#active_connections?`, `#clear_active_connections!`,
|
|
917
|
+
`#clear_reloadable_connections!`, `#clear_all_connections!` and `#flush_idle_connections!` to the connections pools
|
|
918
|
+
for the current role when the `role` argument isn't provided.
|
|
846
919
|
|
|
847
|
-
*
|
|
920
|
+
*Rafael Mendonça França*
|
|
848
921
|
|
|
849
|
-
* Remove deprecated
|
|
922
|
+
* Remove deprecated `#all_connection_pools`.
|
|
850
923
|
|
|
851
924
|
*Rafael Mendonça França*
|
|
852
925
|
|
|
853
|
-
* Remove deprecated `
|
|
926
|
+
* Remove deprecated `ActiveRecord::ConnectionAdapters::SchemaCache#data_sources`.
|
|
854
927
|
|
|
855
928
|
*Rafael Mendonça França*
|
|
856
929
|
|
|
857
|
-
*
|
|
930
|
+
* Remove deprecated `ActiveRecord::ConnectionAdapters::SchemaCache.load_from`.
|
|
858
931
|
|
|
859
932
|
*Rafael Mendonça França*
|
|
860
933
|
|
|
861
|
-
* Remove deprecated
|
|
934
|
+
* Remove deprecated `#all_foreign_keys_valid?` from database adapters.
|
|
862
935
|
|
|
863
936
|
*Rafael Mendonça França*
|
|
864
937
|
|
|
865
|
-
* Remove deprecated `
|
|
938
|
+
* Remove deprecated support to passing coder and class as second argument to `serialize`.
|
|
866
939
|
|
|
867
940
|
*Rafael Mendonça França*
|
|
868
941
|
|
|
869
|
-
* Remove deprecated
|
|
942
|
+
* Remove deprecated support to `ActiveRecord::Base#read_attribute(:id)` to return the custom primary key value.
|
|
870
943
|
|
|
871
944
|
*Rafael Mendonça França*
|
|
872
945
|
|
|
873
|
-
*
|
|
874
|
-
and will be consistently replaced by the latter condition.
|
|
875
|
-
|
|
876
|
-
```ruby
|
|
877
|
-
# Rails 6.1 (IN clause is replaced by merger side equality condition)
|
|
878
|
-
Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
|
|
879
|
-
# Rails 6.1 (both conflict conditions exists, deprecated)
|
|
880
|
-
Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []
|
|
881
|
-
# Rails 6.1 with rewhere to migrate to Rails 7.0's behavior
|
|
882
|
-
Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]
|
|
883
|
-
# Rails 7.0 (same behavior with IN clause, mergee side condition is consistently replaced)
|
|
884
|
-
Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
|
|
885
|
-
Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]
|
|
946
|
+
* Remove deprecated `TestFixtures.fixture_path`.
|
|
886
947
|
|
|
887
948
|
*Rafael Mendonça França*
|
|
888
949
|
|
|
889
|
-
* Remove deprecated
|
|
950
|
+
* Remove deprecated behavior to support referring to a singular association by its plural name.
|
|
890
951
|
|
|
891
952
|
*Rafael Mendonça França*
|
|
892
953
|
|
|
893
|
-
*
|
|
894
|
-
|
|
895
|
-
* `db:schema:load_if_ruby`
|
|
896
|
-
* `db:structure:dump`
|
|
897
|
-
* `db:structure:load`
|
|
898
|
-
* `db:structure:load_if_sql`
|
|
899
|
-
* `db:structure:dump:#{name}`
|
|
900
|
-
* `db:structure:load:#{name}`
|
|
901
|
-
* `db:test:load_structure`
|
|
902
|
-
* `db:test:load_structure:#{name}`
|
|
954
|
+
* Deprecate `Rails.application.config.active_record.allow_deprecated_singular_associations_name`.
|
|
903
955
|
|
|
904
956
|
*Rafael Mendonça França*
|
|
905
957
|
|
|
906
|
-
* Remove deprecated `
|
|
958
|
+
* Remove deprecated support to passing `SchemaMigration` and `InternalMetadata` classes as arguments to
|
|
959
|
+
`ActiveRecord::MigrationContext`.
|
|
907
960
|
|
|
908
961
|
*Rafael Mendonça França*
|
|
909
962
|
|
|
910
|
-
*
|
|
963
|
+
* Remove deprecated `ActiveRecord::Migration.check_pending!` method.
|
|
911
964
|
|
|
912
|
-
|
|
965
|
+
*Rafael Mendonça França*
|
|
913
966
|
|
|
914
|
-
|
|
915
|
-
to be committed, so in order to avoid this mistake, the transaction block is rolled back.
|
|
967
|
+
* Remove deprecated `ActiveRecord::LogSubscriber.runtime` method.
|
|
916
968
|
|
|
917
969
|
*Rafael Mendonça França*
|
|
918
970
|
|
|
919
|
-
*
|
|
920
|
-
|
|
921
|
-
Provides a basic middleware to perform automatic shard swapping. Applications will provide a resolver which will determine for an individual request which shard should be used. Example:
|
|
971
|
+
* Remove deprecated `ActiveRecord::LogSubscriber.runtime=` method.
|
|
922
972
|
|
|
923
|
-
|
|
924
|
-
config.active_record.shard_resolver = ->(request) {
|
|
925
|
-
subdomain = request.subdomain
|
|
926
|
-
tenant = Tenant.find_by_subdomain!(subdomain)
|
|
927
|
-
tenant.shard
|
|
928
|
-
}
|
|
929
|
-
```
|
|
973
|
+
*Rafael Mendonça França*
|
|
930
974
|
|
|
931
|
-
|
|
975
|
+
* Remove deprecated `ActiveRecord::LogSubscriber.reset_runtime` method.
|
|
932
976
|
|
|
933
|
-
*
|
|
977
|
+
*Rafael Mendonça França*
|
|
934
978
|
|
|
935
|
-
* Remove deprecated support to
|
|
979
|
+
* Remove deprecated support to define `explain` in the connection adapter with 2 arguments.
|
|
936
980
|
|
|
937
981
|
*Rafael Mendonça França*
|
|
938
982
|
|
|
939
|
-
* Remove deprecated
|
|
983
|
+
* Remove deprecated `ActiveRecord::ActiveJobRequiredError`.
|
|
940
984
|
|
|
941
985
|
*Rafael Mendonça França*
|
|
942
986
|
|
|
943
|
-
* Remove deprecated
|
|
987
|
+
* Remove deprecated `ActiveRecord::Base.clear_active_connections!`.
|
|
944
988
|
|
|
945
989
|
*Rafael Mendonça França*
|
|
946
990
|
|
|
947
|
-
* Remove
|
|
991
|
+
* Remove deprecated `ActiveRecord::Base.clear_reloadable_connections!`.
|
|
948
992
|
|
|
949
993
|
*Rafael Mendonça França*
|
|
950
994
|
|
|
951
|
-
* Remove
|
|
995
|
+
* Remove deprecated `ActiveRecord::Base.clear_all_connections!`.
|
|
952
996
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
To keep the old behavior, you can add this line to your model:
|
|
997
|
+
*Rafael Mendonça França*
|
|
956
998
|
|
|
957
|
-
|
|
958
|
-
attribute :column, :string
|
|
959
|
-
```
|
|
999
|
+
* Remove deprecated `ActiveRecord::Base.flush_idle_connections!`.
|
|
960
1000
|
|
|
961
1001
|
*Rafael Mendonça França*
|
|
962
1002
|
|
|
963
|
-
* Remove deprecated
|
|
1003
|
+
* Remove deprecated `name` argument from `ActiveRecord::Base.remove_connection`.
|
|
964
1004
|
|
|
965
1005
|
*Rafael Mendonça França*
|
|
966
1006
|
|
|
967
|
-
* Remove deprecated
|
|
1007
|
+
* Remove deprecated support to call `alias_attribute` with non-existent attribute names.
|
|
968
1008
|
|
|
969
1009
|
*Rafael Mendonça França*
|
|
970
1010
|
|
|
971
|
-
* Remove deprecated
|
|
1011
|
+
* Remove deprecated `Rails.application.config.active_record.suppress_multiple_database_warning`.
|
|
972
1012
|
|
|
973
1013
|
*Rafael Mendonça França*
|
|
974
1014
|
|
|
975
|
-
*
|
|
1015
|
+
* Add `ActiveRecord::Encryption::MessagePackMessageSerializer`.
|
|
976
1016
|
|
|
977
|
-
|
|
1017
|
+
Serialize data to the MessagePack format, for efficient storage in binary columns.
|
|
978
1018
|
|
|
979
|
-
|
|
1019
|
+
The binary encoding requires around 30% less space than the base64 encoding
|
|
1020
|
+
used by the default serializer.
|
|
980
1021
|
|
|
981
|
-
*
|
|
1022
|
+
*Donal McBreen*
|
|
982
1023
|
|
|
983
|
-
|
|
1024
|
+
* Add support for encrypting binary columns.
|
|
984
1025
|
|
|
985
|
-
|
|
1026
|
+
Ensure encryption and decryption pass `Type::Binary::Data` around for binary data.
|
|
986
1027
|
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
delegated_type :entryable, types: %w[ Message Comment ]
|
|
990
|
-
accepts_nested_attributes_for :entryable
|
|
991
|
-
end
|
|
1028
|
+
Previously encrypting binary columns with the `ActiveRecord::Encryption::MessageSerializer`
|
|
1029
|
+
incidentally worked for MySQL and SQLite, but not PostgreSQL.
|
|
992
1030
|
|
|
993
|
-
|
|
994
|
-
# => #<Entry:0x00>
|
|
995
|
-
# id: 1
|
|
996
|
-
# entryable_id: 1,
|
|
997
|
-
# entryable_type: 'Message'
|
|
998
|
-
# ...>
|
|
999
|
-
|
|
1000
|
-
entry.entryable
|
|
1001
|
-
# => #<Message:0x01>
|
|
1002
|
-
# id: 1
|
|
1003
|
-
# content: 'Hello world'
|
|
1004
|
-
# ...>
|
|
1005
|
-
```
|
|
1031
|
+
*Donal McBreen*
|
|
1006
1032
|
|
|
1007
|
-
|
|
1033
|
+
* Deprecated `ENV["SCHEMA_CACHE"]` in favor of `schema_cache_path` in the database configuration.
|
|
1008
1034
|
|
|
1009
|
-
|
|
1010
|
-
Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })
|
|
1011
|
-
# ArgumentError: Cannot build association `entryable'. Are you trying to build a polymorphic one-to-one association?
|
|
1012
|
-
```
|
|
1035
|
+
*Rafael Mendonça França*
|
|
1013
1036
|
|
|
1014
|
-
|
|
1037
|
+
* Add `ActiveRecord::Base.with_connection` as a shortcut for leasing a connection for a short duration.
|
|
1015
1038
|
|
|
1016
|
-
|
|
1039
|
+
The leased connection is yielded, and for the duration of the block, any call to `ActiveRecord::Base.connection`
|
|
1040
|
+
will yield that same connection.
|
|
1017
1041
|
|
|
1018
|
-
|
|
1042
|
+
This is useful to perform a few database operations without causing a connection to be leased for the
|
|
1043
|
+
entire duration of the request or job.
|
|
1019
1044
|
|
|
1020
|
-
|
|
1045
|
+
*Jean Boussier*
|
|
1021
1046
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" GROUP BY "posts"."id" HAVING (count(comments.id) >= 2))
|
|
1025
|
-
) [["flagged", "t"]]
|
|
1026
|
-
```
|
|
1047
|
+
* Deprecate `config.active_record.warn_on_records_fetched_greater_than` now that `sql.active_record`
|
|
1048
|
+
notification includes `:row_count` field.
|
|
1027
1049
|
|
|
1028
|
-
*
|
|
1050
|
+
*Jason Nochlin*
|
|
1029
1051
|
|
|
1030
|
-
*
|
|
1052
|
+
* Fix an issue with `where.associated` losing the current join type scope.
|
|
1031
1053
|
|
|
1032
|
-
|
|
1054
|
+
Example:
|
|
1033
1055
|
|
|
1034
|
-
```
|
|
1035
|
-
|
|
1036
|
-
SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
|
|
1037
|
-
) [["flagged", "t"]]
|
|
1056
|
+
```ruby
|
|
1057
|
+
Post.left_joins(:author).where.associated(:author)
|
|
1038
1058
|
```
|
|
1039
1059
|
|
|
1040
|
-
|
|
1060
|
+
Previously, the `LEFT OUTER JOIN` would be lost and converted to an `INNER JOIN`.
|
|
1041
1061
|
|
|
1042
|
-
|
|
1043
|
-
UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
|
|
1044
|
-
SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
|
|
1045
|
-
GROUP BY posts.id HAVING (count(comments.id) >= 2)
|
|
1046
|
-
) [["flagged", "t"]]
|
|
1047
|
-
```
|
|
1062
|
+
*Saleh Alhaddad*
|
|
1048
1063
|
|
|
1049
|
-
|
|
1064
|
+
* Fix an issue where `ActiveRecord::Encryption` configurations are not ready before the loading
|
|
1065
|
+
of Active Record models, when an application is eager loaded. As a result, encrypted attributes
|
|
1066
|
+
could be misconfigured in some cases.
|
|
1050
1067
|
|
|
1051
|
-
*
|
|
1068
|
+
*Maxime Réty*
|
|
1052
1069
|
|
|
1053
|
-
|
|
1070
|
+
* Deprecate defining an `enum` with keyword arguments.
|
|
1054
1071
|
|
|
1055
|
-
```
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1072
|
+
```ruby
|
|
1073
|
+
class Function > ApplicationRecord
|
|
1074
|
+
# BAD
|
|
1075
|
+
enum color: [:red, :blue],
|
|
1076
|
+
type: [:instance, :class]
|
|
1077
|
+
|
|
1078
|
+
# GOOD
|
|
1079
|
+
enum :color, [:red, :blue]
|
|
1080
|
+
enum :type, [:instance, :class]
|
|
1081
|
+
end
|
|
1063
1082
|
```
|
|
1064
1083
|
|
|
1065
|
-
|
|
1084
|
+
*Hartley McGuire*
|
|
1066
1085
|
|
|
1067
|
-
|
|
1086
|
+
* Add `config.active_record.validate_migration_timestamps` option for validating migration timestamps.
|
|
1068
1087
|
|
|
1069
|
-
|
|
1088
|
+
When set, validates that the timestamp prefix for a migration is no more than a day ahead of
|
|
1089
|
+
the timestamp associated with the current time. This is designed to prevent migrations prefixes
|
|
1090
|
+
from being hand-edited to future timestamps, which impacts migration generation and other
|
|
1091
|
+
migration commands.
|
|
1070
1092
|
|
|
1071
|
-
*
|
|
1072
|
-
|
|
1073
|
-
* Filter unchanged attributes with default function from insert query when `partial_inserts` is disabled.
|
|
1074
|
-
|
|
1075
|
-
*Akshay Birajdar*, *Jacopo Beschi*
|
|
1076
|
-
|
|
1077
|
-
* Add support for FILTER clause (SQL:2003) to Arel.
|
|
1078
|
-
|
|
1079
|
-
Currently supported by PostgreSQL 9.4+ and SQLite 3.30+.
|
|
1080
|
-
|
|
1081
|
-
*Andrey Novikov*
|
|
1082
|
-
|
|
1083
|
-
* Automatically set timestamps on record creation during bulk insert/upsert
|
|
1084
|
-
|
|
1085
|
-
Prior to this change, only updates during an upsert operation (e.g. `upsert_all`) would touch timestamps (`updated_{at,on}`). Now, record creations also touch timestamp columns (`{created,updated}_{at,on}`).
|
|
1086
|
-
|
|
1087
|
-
This behaviour is controlled by the `<model>.record_timestamps` config, matching the behaviour of `create`, `update`, etc. It can also be overridden by using the `record_timestamps:` keyword argument.
|
|
1088
|
-
|
|
1089
|
-
Note that this means `upsert_all` on models with `record_timestamps = false` will no longer touch `updated_{at,on}` automatically.
|
|
1090
|
-
|
|
1091
|
-
*Sam Bostock*
|
|
1092
|
-
|
|
1093
|
-
* Don't require `role` when passing `shard` to `connected_to`.
|
|
1094
|
-
|
|
1095
|
-
`connected_to` can now be called with a `shard` only. Note that `role` is still inherited if `connected_to` calls are nested.
|
|
1096
|
-
|
|
1097
|
-
*Eileen M. Uchitelle*
|
|
1098
|
-
|
|
1099
|
-
* Add option to lazily load the schema cache on the connection.
|
|
1100
|
-
|
|
1101
|
-
Previously, the only way to load the schema cache in Active Record was through the Railtie on boot. This option provides the ability to load the schema cache on the connection after it's been established. Loading the cache lazily on the connection can be beneficial for Rails applications that use multiple databases because it will load the cache at the time the connection is established. Currently Railties doesn't have access to the connections before boot.
|
|
1102
|
-
|
|
1103
|
-
To use the cache, set `config.active_record.lazily_load_schema_cache = true` in your application configuration. In addition a `schema_cache_path` should be set in your database configuration if you don't want to use the default "db/schema_cache.yml" path.
|
|
1104
|
-
|
|
1105
|
-
*Eileen M. Uchitelle*
|
|
1106
|
-
|
|
1107
|
-
* Allow automatic `inverse_of` detection for associations with scopes.
|
|
1108
|
-
|
|
1109
|
-
Automatic `inverse_of` detection now works for associations with scopes. For
|
|
1110
|
-
example, the `comments` association here now automatically detects
|
|
1111
|
-
`inverse_of: :post`, so we don't need to pass that option:
|
|
1112
|
-
|
|
1113
|
-
```ruby
|
|
1114
|
-
class Post < ActiveRecord::Base
|
|
1115
|
-
has_many :comments, -> { visible }
|
|
1116
|
-
end
|
|
1117
|
-
|
|
1118
|
-
class Comment < ActiveRecord::Base
|
|
1119
|
-
belongs_to :post
|
|
1120
|
-
end
|
|
1121
|
-
```
|
|
1122
|
-
|
|
1123
|
-
Note that the automatic detection still won't work if the inverse
|
|
1124
|
-
association has a scope. In this example a scope on the `post` association
|
|
1125
|
-
would still prevent Rails from finding the inverse for the `comments`
|
|
1126
|
-
association.
|
|
1127
|
-
|
|
1128
|
-
This will be the default for new apps in Rails 7. To opt in:
|
|
1129
|
-
|
|
1130
|
-
```ruby
|
|
1131
|
-
config.active_record.automatic_scope_inversing = true
|
|
1132
|
-
```
|
|
1133
|
-
|
|
1134
|
-
*Daniel Colson*, *Chris Bloom*
|
|
1135
|
-
|
|
1136
|
-
* Accept optional transaction args to `ActiveRecord::Locking::Pessimistic#with_lock`
|
|
1137
|
-
|
|
1138
|
-
`#with_lock` now accepts transaction options like `requires_new:`,
|
|
1139
|
-
`isolation:`, and `joinable:`
|
|
1140
|
-
|
|
1141
|
-
*John Mileham*
|
|
1142
|
-
|
|
1143
|
-
* Adds support for deferrable foreign key constraints in PostgreSQL.
|
|
1144
|
-
|
|
1145
|
-
By default, foreign key constraints in PostgreSQL are checked after each statement. This works for most use cases,
|
|
1146
|
-
but becomes a major limitation when creating related records before the parent record is inserted into the database.
|
|
1147
|
-
One example of this is looking up / creating a person via one or more unique alias.
|
|
1148
|
-
|
|
1149
|
-
```ruby
|
|
1150
|
-
Person.transaction do
|
|
1151
|
-
alias = Alias
|
|
1152
|
-
.create_with(user_id: SecureRandom.uuid)
|
|
1153
|
-
.create_or_find_by(name: "DHH")
|
|
1154
|
-
|
|
1155
|
-
person = Person
|
|
1156
|
-
.create_with(name: "David Heinemeier Hansson")
|
|
1157
|
-
.create_or_find_by(id: alias.user_id)
|
|
1158
|
-
end
|
|
1159
|
-
```
|
|
1160
|
-
|
|
1161
|
-
Using the default behavior, the transaction would fail when executing the first `INSERT` statement.
|
|
1162
|
-
|
|
1163
|
-
By passing the `:deferrable` option to the `add_foreign_key` statement in migrations, it's possible to defer this
|
|
1164
|
-
check.
|
|
1093
|
+
*Adrianna Chang*
|
|
1165
1094
|
|
|
1166
|
-
|
|
1167
|
-
add_foreign_key :aliases, :person, deferrable: true
|
|
1168
|
-
```
|
|
1095
|
+
* Properly synchronize `Mysql2Adapter#active?` and `TrilogyAdapter#active?`.
|
|
1169
1096
|
|
|
1170
|
-
|
|
1171
|
-
`SET CONSTRAINTS ALL DEFERRED` within a transaction. This will cause the foreign keys to be checked after the
|
|
1172
|
-
transaction.
|
|
1097
|
+
As well as `disconnect!` and `verify!`.
|
|
1173
1098
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1099
|
+
This generally isn't a big problem as connections must not be shared between
|
|
1100
|
+
threads, but is required when running transactional tests or system tests
|
|
1101
|
+
and could lead to a SEGV.
|
|
1176
1102
|
|
|
1177
|
-
|
|
1178
|
-
add_foreign_key :aliases, :person, deferrable: :deferred
|
|
1179
|
-
```
|
|
1180
|
-
|
|
1181
|
-
*Benedikt Deicke*
|
|
1103
|
+
*Jean Boussier*
|
|
1182
1104
|
|
|
1183
|
-
*
|
|
1105
|
+
* Support `:source_location` tag option for query log tags.
|
|
1184
1106
|
|
|
1185
|
-
For example:
|
|
1186
1107
|
```ruby
|
|
1187
|
-
|
|
1188
|
-
:production, :production, 'postgres:///?user=user&password=secret&dbname=app', {}
|
|
1189
|
-
).configuration_hash
|
|
1108
|
+
config.active_record.query_log_tags << :source_location
|
|
1190
1109
|
```
|
|
1191
1110
|
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
{ :user=>"user", :password=>"secret", :dbname=>"app", :adapter=>"postgresql" }
|
|
1196
|
-
```
|
|
1111
|
+
Calculating the caller location is a costly operation and should be used primarily in development
|
|
1112
|
+
(note, there is also a `config.active_record.verbose_query_logs` that serves the same purpose)
|
|
1113
|
+
or occasionally on production for debugging purposes.
|
|
1197
1114
|
|
|
1198
|
-
*
|
|
1115
|
+
*fatkodima*
|
|
1199
1116
|
|
|
1200
|
-
*
|
|
1117
|
+
* Add an option to `ActiveRecord::Encryption::Encryptor` to disable compression.
|
|
1201
1118
|
|
|
1202
|
-
|
|
1119
|
+
Allow compression to be disabled by setting `compress: false`
|
|
1203
1120
|
|
|
1204
1121
|
```ruby
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
change_table :cats do |t|
|
|
1209
|
-
t.enum :current_mood, enum_type: "mood", default: "happy", null: false
|
|
1122
|
+
class User
|
|
1123
|
+
encrypts :name, encryptor: ActiveRecord::Encryption::Encryptor.new(compress: false)
|
|
1210
1124
|
end
|
|
1211
|
-
end
|
|
1212
1125
|
```
|
|
1213
1126
|
|
|
1214
|
-
|
|
1215
|
-
the PostgreSQL adapter.
|
|
1216
|
-
|
|
1217
|
-
*Alex Ghiculescu*
|
|
1218
|
-
|
|
1219
|
-
* Avoid COMMENT statements in PostgreSQL structure dumps
|
|
1220
|
-
|
|
1221
|
-
COMMENT statements are now omitted from the output of `db:structure:dump` when using PostgreSQL >= 11.
|
|
1222
|
-
This allows loading the dump without a pgsql superuser account.
|
|
1127
|
+
*Donal McBreen*
|
|
1223
1128
|
|
|
1224
|
-
|
|
1129
|
+
* Deprecate passing strings to `ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename`.
|
|
1225
1130
|
|
|
1226
|
-
|
|
1131
|
+
A `ActiveRecord::DatabaseConfigurations::DatabaseConfig` object should be passed instead.
|
|
1227
1132
|
|
|
1228
|
-
*
|
|
1229
|
-
|
|
1230
|
-
Generated columns are supported since version 12.0 of PostgreSQL. This adds
|
|
1231
|
-
support of those to the PostgreSQL adapter.
|
|
1133
|
+
*Rafael Mendonça França*
|
|
1232
1134
|
|
|
1233
|
-
|
|
1234
|
-
create_table :users do |t|
|
|
1235
|
-
t.string :name
|
|
1236
|
-
t.virtual :name_upcased, type: :string, as: 'upper(name)', stored: true
|
|
1237
|
-
end
|
|
1238
|
-
```
|
|
1135
|
+
* Add `row_count` field to `sql.active_record` notification.
|
|
1239
1136
|
|
|
1240
|
-
|
|
1137
|
+
This field returns the amount of rows returned by the query that emitted the notification.
|
|
1241
1138
|
|
|
1139
|
+
This metric is useful in cases where one wants to detect queries with big result sets.
|
|
1242
1140
|
|
|
1243
|
-
|
|
1141
|
+
*Marvin Bitterlich*
|
|
1244
1142
|
|
|
1245
|
-
*
|
|
1143
|
+
* Consistently raise an `ArgumentError` when passing an invalid argument to a nested attributes association writer.
|
|
1246
1144
|
|
|
1145
|
+
Previously, this would only raise on collection associations and produce a generic error on singular associations.
|
|
1247
1146
|
|
|
1248
|
-
|
|
1147
|
+
Now, it will raise on both collection and singular associations.
|
|
1249
1148
|
|
|
1250
|
-
*
|
|
1149
|
+
*Joshua Young*
|
|
1251
1150
|
|
|
1252
|
-
|
|
1151
|
+
* Fix single quote escapes on default generated MySQL columns.
|
|
1253
1152
|
|
|
1254
|
-
|
|
1255
|
-
Creating scope :my_scope_name. Overwriting existing method "MyClass.my_scope_name" when overwriting existing scopes
|
|
1256
|
-
```
|
|
1153
|
+
MySQL 5.7.5+ supports generated columns, which can be used to create a column that is computed from an expression.
|
|
1257
1154
|
|
|
1258
|
-
|
|
1155
|
+
Previously, the schema dump would output a string with double escapes for generated columns with single quotes in the default expression.
|
|
1259
1156
|
|
|
1260
|
-
|
|
1157
|
+
This would result in issues when importing the schema on a fresh instance of a MySQL database.
|
|
1261
1158
|
|
|
1262
|
-
|
|
1263
|
-
and not all databases support explicitly specifying additional precision.
|
|
1159
|
+
Now, the string will not be escaped and will be valid Ruby upon importing of the schema.
|
|
1264
1160
|
|
|
1265
|
-
|
|
1266
|
-
for the SQL to produce a high precision timestamp on the current database.
|
|
1161
|
+
*Yash Kapadia*
|
|
1267
1162
|
|
|
1268
|
-
|
|
1163
|
+
* Fix Migrations with versions older than 7.1 validating options given to
|
|
1164
|
+
`add_reference` and `t.references`.
|
|
1269
1165
|
|
|
1270
|
-
*
|
|
1166
|
+
*Hartley McGuire*
|
|
1271
1167
|
|
|
1272
|
-
* Add
|
|
1168
|
+
* Add `<role>_types` class method to `ActiveRecord::DelegatedType` so that the delegated types can be introspected.
|
|
1273
1169
|
|
|
1274
|
-
|
|
1275
|
-
when running postgresql database tasks.
|
|
1170
|
+
*JP Rosevear*
|
|
1276
1171
|
|
|
1277
|
-
|
|
1278
|
-
# config/database.yml
|
|
1172
|
+
* Make `schema_dump`, `query_cache`, `replica` and `database_tasks` configurable via `DATABASE_URL`.
|
|
1279
1173
|
|
|
1280
|
-
|
|
1281
|
-
sslmode: verify-full
|
|
1282
|
-
sslcert: client.crt
|
|
1283
|
-
sslkey: client.key
|
|
1284
|
-
sslrootcert: ca.crt
|
|
1285
|
-
```
|
|
1174
|
+
This wouldn't always work previously because boolean values would be interpreted as strings.
|
|
1286
1175
|
|
|
1287
|
-
|
|
1176
|
+
e.g. `DATABASE_URL=postgres://localhost/foo?schema_dump=false` now properly disable dumping the schema
|
|
1177
|
+
cache.
|
|
1288
1178
|
|
|
1289
|
-
|
|
1290
|
-
PGSSLMODE=verify-full
|
|
1291
|
-
PGSSLCERT=client.crt
|
|
1292
|
-
PGSSLKEY=client.key
|
|
1293
|
-
PGSSLROOTCERT=ca.crt
|
|
1294
|
-
```
|
|
1179
|
+
*Mike Coutermarsh*, *Jean Boussier*
|
|
1295
1180
|
|
|
1296
|
-
|
|
1181
|
+
* Introduce `ActiveRecord::Transactions::ClassMethods#set_callback`.
|
|
1297
1182
|
|
|
1298
|
-
|
|
1183
|
+
It is identical to `ActiveSupport::Callbacks::ClassMethods#set_callback`
|
|
1184
|
+
but with support for `after_commit` and `after_rollback` callback options.
|
|
1299
1185
|
|
|
1300
|
-
*
|
|
1186
|
+
*Joshua Young*
|
|
1301
1187
|
|
|
1302
|
-
|
|
1303
|
-
and not also to the callbacks from the update itself.
|
|
1188
|
+
* Make `ActiveRecord::Encryption::Encryptor` agnostic of the serialization format used for encrypted data.
|
|
1304
1189
|
|
|
1305
|
-
|
|
1190
|
+
Previously, the encryptor instance only allowed an encrypted value serialized as a `String` to be passed to the message serializer.
|
|
1306
1191
|
|
|
1307
|
-
|
|
1308
|
-
using `String#constantize` instead of the model's `polymorphic_class_for`.
|
|
1192
|
+
Now, the encryptor lets the configured `message_serializer` decide which types of serialized encrypted values are supported. A custom serialiser is therefore allowed to serialize `ActiveRecord::Encryption::Message` objects using a type other than `String`.
|
|
1309
1193
|
|
|
1310
|
-
|
|
1311
|
-
1. `touch`ing the previously associated record
|
|
1312
|
-
2. updating the previously associated record's `counter_cache`
|
|
1194
|
+
The default `ActiveRecord::Encryption::MessageSerializer` already ensures that only `String` objects are passed for deserialization.
|
|
1313
1195
|
|
|
1314
|
-
*
|
|
1196
|
+
*Maxime Réty*
|
|
1315
1197
|
|
|
1316
|
-
*
|
|
1198
|
+
* Fix `encrypted_attribute?` to take into account context properties passed to `encrypts`.
|
|
1317
1199
|
|
|
1318
|
-
|
|
1200
|
+
*Maxime Réty*
|
|
1319
1201
|
|
|
1320
|
-
|
|
1202
|
+
* The object returned by `explain` now responds to `pluck`, `first`,
|
|
1203
|
+
`last`, `average`, `count`, `maximum`, `minimum`, and `sum`. Those
|
|
1204
|
+
new methods run `EXPLAIN` on the corresponding queries:
|
|
1321
1205
|
|
|
1322
1206
|
```ruby
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
Or a regex:
|
|
1207
|
+
User.all.explain.count
|
|
1208
|
+
# EXPLAIN SELECT COUNT(*) FROM `users`
|
|
1209
|
+
# ...
|
|
1327
1210
|
|
|
1328
|
-
|
|
1329
|
-
|
|
1211
|
+
User.all.explain.maximum(:id)
|
|
1212
|
+
# EXPLAIN SELECT MAX(`users`.`id`) FROM `users`
|
|
1213
|
+
# ...
|
|
1330
1214
|
```
|
|
1331
1215
|
|
|
1332
|
-
*
|
|
1333
|
-
|
|
1334
|
-
* Make schema cache methods return consistent results.
|
|
1335
|
-
|
|
1336
|
-
Previously the schema cache methods `primary_keys`, `columns`, `columns_hash`, and `indexes`
|
|
1337
|
-
would behave differently than one another when a table didn't exist and differently across
|
|
1338
|
-
database adapters. This change unifies the behavior so each method behaves the same regardless
|
|
1339
|
-
of adapter.
|
|
1340
|
-
|
|
1341
|
-
The behavior now is:
|
|
1342
|
-
|
|
1343
|
-
`columns`: (unchanged) raises a db error if the table does not exist.
|
|
1344
|
-
`columns_hash`: (unchanged) raises a db error if the table does not exist.
|
|
1345
|
-
`primary_keys`: (unchanged) returns `nil` if the table does not exist.
|
|
1346
|
-
`indexes`: (changed for mysql2) returns `[]` if the table does not exist.
|
|
1347
|
-
|
|
1348
|
-
*Eileen M. Uchitelle*
|
|
1349
|
-
|
|
1350
|
-
* Reestablish connection to previous database after after running `db:schema:load:name`
|
|
1216
|
+
*Petrik de Heus*
|
|
1351
1217
|
|
|
1352
|
-
|
|
1218
|
+
* Fixes an issue where `validates_associated` `:on` option wasn't respected
|
|
1219
|
+
when validating associated records.
|
|
1353
1220
|
|
|
1354
|
-
*
|
|
1221
|
+
*Austen Madden*, *Alex Ghiculescu*, *Rafał Brize*
|
|
1355
1222
|
|
|
1356
|
-
*
|
|
1223
|
+
* Allow overriding SQLite defaults from `database.yml`.
|
|
1357
1224
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1225
|
+
Any PRAGMA configuration set under the `pragmas` key in the configuration
|
|
1226
|
+
file takes precedence over Rails' defaults, and additional PRAGMAs can be
|
|
1227
|
+
set as well.
|
|
1361
1228
|
|
|
1362
1229
|
```yaml
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
adapter: mysql2
|
|
1369
|
-
animals:
|
|
1370
|
-
database: my_animals_database
|
|
1371
|
-
adapter: mysql2
|
|
1372
|
-
database_tasks: false
|
|
1230
|
+
database: storage/development.sqlite3
|
|
1231
|
+
timeout: 5000
|
|
1232
|
+
pragmas:
|
|
1233
|
+
journal_mode: off
|
|
1234
|
+
temp_store: memory
|
|
1373
1235
|
```
|
|
1374
1236
|
|
|
1375
|
-
*
|
|
1237
|
+
*Stephen Margheim*
|
|
1376
1238
|
|
|
1377
|
-
*
|
|
1239
|
+
* Remove warning message when running SQLite in production, but leave it unconfigured.
|
|
1378
1240
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1241
|
+
There are valid use cases for running SQLite in production. However, it must be done
|
|
1242
|
+
with care, so instead of a warning most users won't see anyway, it's preferable to
|
|
1243
|
+
leave the configuration commented out to force them to think about having the database
|
|
1244
|
+
on a persistent volume etc.
|
|
1381
1245
|
|
|
1382
|
-
|
|
1246
|
+
*Jacopo Beschi*, *Jean Boussier*
|
|
1383
1247
|
|
|
1384
|
-
* Add
|
|
1248
|
+
* Add support for generated columns to the SQLite3 adapter.
|
|
1385
1249
|
|
|
1386
|
-
|
|
1250
|
+
Generated columns (both stored and dynamic) are supported since version 3.31.0 of SQLite.
|
|
1251
|
+
This adds support for those to the SQLite3 adapter.
|
|
1387
1252
|
|
|
1388
1253
|
```ruby
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
end
|
|
1394
|
-
end
|
|
1395
|
-
```
|
|
1396
|
-
|
|
1397
|
-
By default the application, controller and action details are added to the query tags:
|
|
1398
|
-
|
|
1399
|
-
```ruby
|
|
1400
|
-
class BooksController < ApplicationController
|
|
1401
|
-
def index
|
|
1402
|
-
@books = Book.all
|
|
1403
|
-
end
|
|
1254
|
+
create_table :users do |t|
|
|
1255
|
+
t.string :name
|
|
1256
|
+
t.virtual :name_upper, type: :string, as: 'UPPER(name)'
|
|
1257
|
+
t.virtual :name_lower, type: :string, as: 'LOWER(name)', stored: true
|
|
1404
1258
|
end
|
|
1405
1259
|
```
|
|
1406
1260
|
|
|
1407
|
-
|
|
1408
|
-
GET /books
|
|
1409
|
-
# SELECT * FROM books /*application:MyApp;controller:books;action:index*/
|
|
1410
|
-
```
|
|
1411
|
-
|
|
1412
|
-
Custom tags containing static values and Procs can be defined in the application configuration:
|
|
1413
|
-
|
|
1414
|
-
```ruby
|
|
1415
|
-
config.active_record.query_log_tags = [
|
|
1416
|
-
:application,
|
|
1417
|
-
:controller,
|
|
1418
|
-
:action,
|
|
1419
|
-
{
|
|
1420
|
-
custom_static: "foo",
|
|
1421
|
-
custom_dynamic: -> { Time.now }
|
|
1422
|
-
}
|
|
1423
|
-
]
|
|
1424
|
-
```
|
|
1425
|
-
|
|
1426
|
-
*Keeran Raj Hawoldar*, *Eileen M. Uchitelle*, *Kasper Timm Hansen*
|
|
1427
|
-
|
|
1428
|
-
* Added support for multiple databases to `rails db:setup` and `rails db:reset`.
|
|
1429
|
-
|
|
1430
|
-
*Ryan Hall*
|
|
1431
|
-
|
|
1432
|
-
* Add `ActiveRecord::Relation#structurally_compatible?`.
|
|
1433
|
-
|
|
1434
|
-
Adds a query method by which a user can tell if the relation that they're
|
|
1435
|
-
about to use for `#or` or `#and` is structurally compatible with the
|
|
1436
|
-
receiver.
|
|
1437
|
-
|
|
1438
|
-
*Kevin Newton*
|
|
1439
|
-
|
|
1440
|
-
* Add `ActiveRecord::QueryMethods#in_order_of`.
|
|
1441
|
-
|
|
1442
|
-
This allows you to specify an explicit order that you'd like records
|
|
1443
|
-
returned in based on a SQL expression. By default, this will be accomplished
|
|
1444
|
-
using a case statement, as in:
|
|
1445
|
-
|
|
1446
|
-
```ruby
|
|
1447
|
-
Post.in_order_of(:id, [3, 5, 1])
|
|
1448
|
-
```
|
|
1449
|
-
|
|
1450
|
-
will generate the SQL:
|
|
1451
|
-
|
|
1452
|
-
```sql
|
|
1453
|
-
SELECT "posts".* FROM "posts" ORDER BY CASE "posts"."id" WHEN 3 THEN 1 WHEN 5 THEN 2 WHEN 1 THEN 3 ELSE 4 END ASC
|
|
1454
|
-
```
|
|
1455
|
-
|
|
1456
|
-
However, because this functionality is built into MySQL in the form of the
|
|
1457
|
-
`FIELD` function, that connection adapter will generate the following SQL
|
|
1458
|
-
instead:
|
|
1459
|
-
|
|
1460
|
-
```sql
|
|
1461
|
-
SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC
|
|
1462
|
-
```
|
|
1463
|
-
|
|
1464
|
-
*Kevin Newton*
|
|
1465
|
-
|
|
1466
|
-
* Fix `eager_loading?` when ordering with `Symbol`.
|
|
1467
|
-
|
|
1468
|
-
`eager_loading?` is triggered correctly when using `order` with symbols.
|
|
1469
|
-
|
|
1470
|
-
```ruby
|
|
1471
|
-
scope = Post.includes(:comments).order(:"comments.label")
|
|
1472
|
-
=> true
|
|
1473
|
-
```
|
|
1474
|
-
|
|
1475
|
-
*Jacopo Beschi*
|
|
1476
|
-
|
|
1477
|
-
* Two change tracking methods are added for `belongs_to` associations.
|
|
1478
|
-
|
|
1479
|
-
The `association_changed?` method (assuming an association named `:association`) returns true
|
|
1480
|
-
if a different associated object has been assigned and the foreign key will be updated in the
|
|
1481
|
-
next save.
|
|
1482
|
-
|
|
1483
|
-
The `association_previously_changed?` method returns true if the previous save updated the
|
|
1484
|
-
association to reference a different associated object.
|
|
1485
|
-
|
|
1486
|
-
*George Claghorn*
|
|
1261
|
+
*Stephen Margheim*
|
|
1487
1262
|
|
|
1488
|
-
*
|
|
1263
|
+
* TrilogyAdapter: ignore `host` if `socket` parameter is set.
|
|
1489
1264
|
|
|
1490
|
-
|
|
1491
|
-
specific database, use the `schema_dump` option:
|
|
1265
|
+
This allows to configure a connection on a UNIX socket via `DATABASE_URL`:
|
|
1492
1266
|
|
|
1493
|
-
```yaml
|
|
1494
|
-
# config/database.yml
|
|
1495
|
-
|
|
1496
|
-
production:
|
|
1497
|
-
schema_dump: false
|
|
1498
1267
|
```
|
|
1499
|
-
|
|
1500
|
-
*Luis Vasconcellos*, *Eileen M. Uchitelle*
|
|
1501
|
-
|
|
1502
|
-
* Fix `eager_loading?` when ordering with `Hash` syntax.
|
|
1503
|
-
|
|
1504
|
-
`eager_loading?` is triggered correctly when using `order` with hash syntax
|
|
1505
|
-
on an outer table.
|
|
1506
|
-
|
|
1507
|
-
```ruby
|
|
1508
|
-
Post.includes(:comments).order({ "comments.label": :ASC }).eager_loading?
|
|
1509
|
-
# => true
|
|
1268
|
+
DATABASE_URL=trilogy://does-not-matter/my_db_production?socket=/var/run/mysql.sock
|
|
1510
1269
|
```
|
|
1511
1270
|
|
|
1512
|
-
*Jacopo Beschi*
|
|
1513
|
-
|
|
1514
|
-
* Move the forcing of clear text encoding to the `ActiveRecord::Encryption::Encryptor`.
|
|
1515
|
-
|
|
1516
|
-
Fixes #42699.
|
|
1517
|
-
|
|
1518
|
-
*J Smith*
|
|
1519
|
-
|
|
1520
|
-
* `partial_inserts` is now disabled by default in new apps.
|
|
1521
|
-
|
|
1522
|
-
This will be the default for new apps in Rails 7. To opt in:
|
|
1523
|
-
|
|
1524
|
-
```ruby
|
|
1525
|
-
config.active_record.partial_inserts = true
|
|
1526
|
-
```
|
|
1527
|
-
|
|
1528
|
-
If a migration removes the default value of a column, this option
|
|
1529
|
-
would cause old processes to no longer be able to create new records.
|
|
1530
|
-
|
|
1531
|
-
If you need to remove a column, you should first use `ignored_columns`
|
|
1532
|
-
to stop using it.
|
|
1533
|
-
|
|
1534
1271
|
*Jean Boussier*
|
|
1535
1272
|
|
|
1536
|
-
*
|
|
1537
|
-
|
|
1538
|
-
This will be the default for new apps in Rails 7. To opt in:
|
|
1539
|
-
|
|
1540
|
-
```ruby
|
|
1541
|
-
config.active_record.verify_foreign_keys_for_fixtures = true
|
|
1542
|
-
```
|
|
1543
|
-
|
|
1544
|
-
Tests will not run if there is a foreign key constraint violation in your fixture data.
|
|
1273
|
+
* Make `assert_queries_count`, `assert_no_queries`, `assert_queries_match`, and
|
|
1274
|
+
`assert_no_queries_match` assertions public.
|
|
1545
1275
|
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
* Clear cached `has_one` association after setting `belongs_to` association to `nil`.
|
|
1551
|
-
|
|
1552
|
-
After setting a `belongs_to` relation to `nil` and updating an unrelated attribute on the owner,
|
|
1553
|
-
the owner should still return `nil` on the `has_one` relation.
|
|
1554
|
-
|
|
1555
|
-
Fixes #42597.
|
|
1556
|
-
|
|
1557
|
-
*Michiel de Mare*
|
|
1558
|
-
|
|
1559
|
-
* OpenSSL constants are now used for Digest computations.
|
|
1560
|
-
|
|
1561
|
-
*Dirkjan Bussink*
|
|
1562
|
-
|
|
1563
|
-
* Adds support for `if_not_exists` to `add_foreign_key` and `if_exists` to `remove_foreign_key`.
|
|
1564
|
-
|
|
1565
|
-
Applications can set their migrations to ignore exceptions raised when adding a foreign key
|
|
1566
|
-
that already exists or when removing a foreign key that does not exist.
|
|
1567
|
-
|
|
1568
|
-
Example Usage:
|
|
1276
|
+
To assert the expected number of queries are made, Rails internally uses `assert_queries_count` and
|
|
1277
|
+
`assert_no_queries`. To assert that specific SQL queries are made, `assert_queries_match` and
|
|
1278
|
+
`assert_no_queries_match` are used. These assertions can now be used in applications as well.
|
|
1569
1279
|
|
|
1570
1280
|
```ruby
|
|
1571
|
-
class
|
|
1572
|
-
|
|
1573
|
-
|
|
1281
|
+
class ArticleTest < ActiveSupport::TestCase
|
|
1282
|
+
test "queries are made" do
|
|
1283
|
+
assert_queries_count(1) { Article.first }
|
|
1574
1284
|
end
|
|
1575
|
-
end
|
|
1576
|
-
```
|
|
1577
1285
|
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1286
|
+
test "creates a foreign key" do
|
|
1287
|
+
assert_queries_match(/ADD FOREIGN KEY/i, include_schema: true) do
|
|
1288
|
+
@connection.add_foreign_key(:comments, :posts)
|
|
1289
|
+
end
|
|
1582
1290
|
end
|
|
1583
1291
|
end
|
|
1584
1292
|
```
|
|
1585
1293
|
|
|
1586
|
-
*
|
|
1587
|
-
|
|
1588
|
-
* Prevent polluting ENV during postgresql structure dump/load.
|
|
1589
|
-
|
|
1590
|
-
Some configuration parameters were provided to pg_dump / psql via
|
|
1591
|
-
environment variables which persisted beyond the command being run, and may
|
|
1592
|
-
have caused subsequent commands and connections to fail. Tasks running
|
|
1593
|
-
across multiple postgresql databases like `rails db:test:prepare` may have
|
|
1594
|
-
been affected.
|
|
1595
|
-
|
|
1596
|
-
*Samuel Cochran*
|
|
1597
|
-
|
|
1598
|
-
* Set precision 6 by default for `datetime` columns.
|
|
1599
|
-
|
|
1600
|
-
By default, datetime columns will have microseconds precision instead of seconds precision.
|
|
1601
|
-
|
|
1602
|
-
*Roberto Miranda*
|
|
1603
|
-
|
|
1604
|
-
* Allow preloading of associations with instance dependent scopes.
|
|
1605
|
-
|
|
1606
|
-
*John Hawthorn*, *John Crepezzi*, *Adam Hess*, *Eileen M. Uchitelle*, *Dinah Shi*
|
|
1607
|
-
|
|
1608
|
-
* Do not try to rollback transactions that failed due to a `ActiveRecord::TransactionRollbackError`.
|
|
1609
|
-
|
|
1610
|
-
*Jamie McCarthy*
|
|
1611
|
-
|
|
1612
|
-
* Active Record Encryption will now encode values as UTF-8 when using deterministic
|
|
1613
|
-
encryption. The encoding is part of the encrypted payload, so different encodings for
|
|
1614
|
-
different values result in different ciphertexts. This can break unique constraints and
|
|
1615
|
-
queries.
|
|
1616
|
-
|
|
1617
|
-
The new behavior is configurable via `active_record.encryption.forced_encoding_for_deterministic_encryption`
|
|
1618
|
-
that is `Encoding::UTF_8` by default. It can be disabled by setting it to `nil`.
|
|
1619
|
-
|
|
1620
|
-
*Jorge Manrubia*
|
|
1621
|
-
|
|
1622
|
-
* The MySQL adapter now cast numbers and booleans bind parameters to string for safety reasons.
|
|
1623
|
-
|
|
1624
|
-
When comparing a string and a number in a query, MySQL converts the string to a number. So for
|
|
1625
|
-
instance `"foo" = 0`, will implicitly cast `"foo"` to `0` and will evaluate to `TRUE` which can
|
|
1626
|
-
lead to security vulnerabilities.
|
|
1627
|
-
|
|
1628
|
-
Active Record already protect against that vulnerability when it knows the type of the column
|
|
1629
|
-
being compared, however until now it was still vulnerable when using bind parameters:
|
|
1630
|
-
|
|
1631
|
-
```ruby
|
|
1632
|
-
User.where("login_token = ?", 0).first
|
|
1633
|
-
```
|
|
1634
|
-
|
|
1635
|
-
Would perform:
|
|
1636
|
-
|
|
1637
|
-
```sql
|
|
1638
|
-
SELECT * FROM `users` WHERE `login_token` = 0 LIMIT 1;
|
|
1639
|
-
```
|
|
1640
|
-
|
|
1641
|
-
Now it will perform:
|
|
1642
|
-
|
|
1643
|
-
```sql
|
|
1644
|
-
SELECT * FROM `users` WHERE `login_token` = '0' LIMIT 1;
|
|
1645
|
-
```
|
|
1646
|
-
|
|
1647
|
-
*Jean Boussier*
|
|
1648
|
-
|
|
1649
|
-
* Fixture configurations (`_fixture`) are now strictly validated.
|
|
1650
|
-
|
|
1651
|
-
If an error will be raised if that entry contains unknown keys while previously it
|
|
1652
|
-
would silently have no effects.
|
|
1653
|
-
|
|
1654
|
-
*Jean Boussier*
|
|
1655
|
-
|
|
1656
|
-
* Add `ActiveRecord::Base.update!` that works like `ActiveRecord::Base.update` but raises exceptions.
|
|
1657
|
-
|
|
1658
|
-
This allows for the same behavior as the instance method `#update!` at a class level.
|
|
1659
|
-
|
|
1660
|
-
```ruby
|
|
1661
|
-
Person.update!(:all, state: "confirmed")
|
|
1662
|
-
```
|
|
1663
|
-
|
|
1664
|
-
*Dorian Marié*
|
|
1665
|
-
|
|
1666
|
-
* Add `ActiveRecord::Base#attributes_for_database`.
|
|
1667
|
-
|
|
1668
|
-
Returns attributes with values for assignment to the database.
|
|
1669
|
-
|
|
1670
|
-
*Chris Salzberg*
|
|
1671
|
-
|
|
1672
|
-
* Use an empty query to check if the PostgreSQL connection is still active.
|
|
1673
|
-
|
|
1674
|
-
An empty query is faster than `SELECT 1`.
|
|
1675
|
-
|
|
1676
|
-
*Heinrich Lee Yu*
|
|
1677
|
-
|
|
1678
|
-
* Add `ActiveRecord::Base#previously_persisted?`.
|
|
1679
|
-
|
|
1680
|
-
Returns `true` if the object has been previously persisted but now it has been deleted.
|
|
1681
|
-
|
|
1682
|
-
* Deprecate `partial_writes` in favor of `partial_inserts` and `partial_updates`.
|
|
1683
|
-
|
|
1684
|
-
This allows to have a different behavior on update and create.
|
|
1294
|
+
*Petrik de Heus*, *fatkodima*
|
|
1685
1295
|
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
* Fix compatibility with `psych >= 4`.
|
|
1689
|
-
|
|
1690
|
-
Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility,
|
|
1691
|
-
Active Record's schema cache loader and `YAMLColumn` now uses `YAML.unsafe_load` if available.
|
|
1692
|
-
|
|
1693
|
-
*Jean Boussier*
|
|
1694
|
-
|
|
1695
|
-
* `ActiveRecord::Base.logger` is now a `class_attribute`.
|
|
1696
|
-
|
|
1697
|
-
This means it can no longer be accessed directly through `@@logger`, and that setting `logger =`
|
|
1698
|
-
on a subclass won't change the parent's logger.
|
|
1699
|
-
|
|
1700
|
-
*Jean Boussier*
|
|
1701
|
-
|
|
1702
|
-
* Add `.asc.nulls_first` for all databases. Unfortunately MySQL still doesn't like `nulls_last`.
|
|
1703
|
-
|
|
1704
|
-
*Keenan Brock*
|
|
1705
|
-
|
|
1706
|
-
* Improve performance of `one?` and `many?` by limiting the generated count query to 2 results.
|
|
1707
|
-
|
|
1708
|
-
*Gonzalo Riestra*
|
|
1709
|
-
|
|
1710
|
-
* Don't check type when using `if_not_exists` on `add_column`.
|
|
1711
|
-
|
|
1712
|
-
Previously, if a migration called `add_column` with the `if_not_exists` option set to true
|
|
1713
|
-
the `column_exists?` check would look for a column with the same name and type as the migration.
|
|
1714
|
-
|
|
1715
|
-
Recently it was discovered that the type passed to the migration is not always the same type
|
|
1716
|
-
as the column after migration. For example a column set to `:mediumblob` in the migration will
|
|
1717
|
-
be casted to `binary` when calling `column.type`. Since there is no straightforward way to cast
|
|
1718
|
-
the type to the database type without running the migration, we opted to drop the type check from
|
|
1719
|
-
`add_column`. This means that migrations adding a duplicate column with a different type will no
|
|
1720
|
-
longer raise an error.
|
|
1296
|
+
* Fix `has_secure_token` calls the setter method on initialize.
|
|
1721
1297
|
|
|
1722
|
-
*
|
|
1723
|
-
|
|
1724
|
-
* Log a warning message when running SQLite in production.
|
|
1725
|
-
|
|
1726
|
-
Using SQLite in production ENV is generally discouraged. SQLite is also the default adapter
|
|
1727
|
-
in a new Rails application.
|
|
1728
|
-
For the above reasons log a warning message when running SQLite in production.
|
|
1729
|
-
|
|
1730
|
-
The warning can be disabled by setting `config.active_record.sqlite3_production_warning=false`.
|
|
1731
|
-
|
|
1732
|
-
*Jacopo Beschi*
|
|
1733
|
-
|
|
1734
|
-
* Add option to disable joins for `has_one` associations.
|
|
1735
|
-
|
|
1736
|
-
In a multiple database application, associations can't join across
|
|
1737
|
-
databases. When set, this option instructs Rails to generate 2 or
|
|
1738
|
-
more queries rather than generating joins for `has_one` associations.
|
|
1739
|
-
|
|
1740
|
-
Set the option on a has one through association:
|
|
1741
|
-
|
|
1742
|
-
```ruby
|
|
1743
|
-
class Person
|
|
1744
|
-
has_one :dog
|
|
1745
|
-
has_one :veterinarian, through: :dog, disable_joins: true
|
|
1746
|
-
end
|
|
1747
|
-
```
|
|
1748
|
-
|
|
1749
|
-
Then instead of generating join SQL, two queries are used for `@person.veterinarian`:
|
|
1750
|
-
|
|
1751
|
-
```
|
|
1752
|
-
SELECT "dogs"."id" FROM "dogs" WHERE "dogs"."person_id" = ? [["person_id", 1]]
|
|
1753
|
-
SELECT "veterinarians".* FROM "veterinarians" WHERE "veterinarians"."dog_id" = ? [["dog_id", 1]]
|
|
1754
|
-
```
|
|
1755
|
-
|
|
1756
|
-
*Sarah Vessels*, *Eileen M. Uchitelle*
|
|
1757
|
-
|
|
1758
|
-
* `Arel::Visitors::Dot` now renders a complete set of properties when visiting
|
|
1759
|
-
`Arel::Nodes::SelectCore`, `SelectStatement`, `InsertStatement`, `UpdateStatement`, and
|
|
1760
|
-
`DeleteStatement`, which fixes #42026. Previously, some properties were omitted.
|
|
1761
|
-
|
|
1762
|
-
*Mike Dalessio*
|
|
1763
|
-
|
|
1764
|
-
* `Arel::Visitors::Dot` now supports `Arel::Nodes::Bin`, `Case`, `CurrentRow`, `Distinct`,
|
|
1765
|
-
`DistinctOn`, `Else`, `Except`, `InfixOperation`, `Intersect`, `Lock`, `NotRegexp`, `Quoted`,
|
|
1766
|
-
`Regexp`, `UnaryOperation`, `Union`, `UnionAll`, `When`, and `With`. Previously, these node
|
|
1767
|
-
types caused an exception to be raised by `Arel::Visitors::Dot#accept`.
|
|
1768
|
-
|
|
1769
|
-
*Mike Dalessio*
|
|
1770
|
-
|
|
1771
|
-
* Optimize `remove_columns` to use a single SQL statement.
|
|
1772
|
-
|
|
1773
|
-
```ruby
|
|
1774
|
-
remove_columns :my_table, :col_one, :col_two
|
|
1775
|
-
```
|
|
1776
|
-
|
|
1777
|
-
Now results in the following SQL:
|
|
1778
|
-
|
|
1779
|
-
```sql
|
|
1780
|
-
ALTER TABLE "my_table" DROP COLUMN "col_one", DROP COLUMN "col_two"
|
|
1781
|
-
```
|
|
1782
|
-
|
|
1783
|
-
*Jon Dufresne*
|
|
1784
|
-
|
|
1785
|
-
* Ensure `has_one` autosave association callbacks get called once.
|
|
1786
|
-
|
|
1787
|
-
Change the `has_one` autosave callback to be non cyclic as well.
|
|
1788
|
-
By doing this the autosave callback are made more consistent for
|
|
1789
|
-
all 3 cases: `has_many`, `has_one`, and `belongs_to`.
|
|
1790
|
-
|
|
1791
|
-
*Petrik de Heus*
|
|
1792
|
-
|
|
1793
|
-
* Add option to disable joins for associations.
|
|
1794
|
-
|
|
1795
|
-
In a multiple database application, associations can't join across
|
|
1796
|
-
databases. When set, this option instructs Rails to generate 2 or
|
|
1797
|
-
more queries rather than generating joins for associations.
|
|
1798
|
-
|
|
1799
|
-
Set the option on a has many through association:
|
|
1800
|
-
|
|
1801
|
-
```ruby
|
|
1802
|
-
class Dog
|
|
1803
|
-
has_many :treats, through: :humans, disable_joins: true
|
|
1804
|
-
has_many :humans
|
|
1805
|
-
end
|
|
1806
|
-
```
|
|
1807
|
-
|
|
1808
|
-
Then instead of generating join SQL, two queries are used for `@dog.treats`:
|
|
1809
|
-
|
|
1810
|
-
```
|
|
1811
|
-
SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ? [["dog_id", 1]]
|
|
1812
|
-
SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?) [["human_id", 1], ["human_id", 2], ["human_id", 3]]
|
|
1813
|
-
```
|
|
1814
|
-
|
|
1815
|
-
*Eileen M. Uchitelle*, *Aaron Patterson*, *Lee Quarella*
|
|
1816
|
-
|
|
1817
|
-
* Add setting for enumerating column names in SELECT statements.
|
|
1818
|
-
|
|
1819
|
-
Adding a column to a PostgreSQL database, for example, while the application is running can
|
|
1820
|
-
change the result of wildcard `SELECT *` queries, which invalidates the result
|
|
1821
|
-
of cached prepared statements and raises a `PreparedStatementCacheExpired` error.
|
|
1822
|
-
|
|
1823
|
-
When enabled, Active Record will avoid wildcards and always include column names
|
|
1824
|
-
in `SELECT` queries, which will return consistent results and avoid prepared
|
|
1825
|
-
statement errors.
|
|
1826
|
-
|
|
1827
|
-
Before:
|
|
1828
|
-
|
|
1829
|
-
```ruby
|
|
1830
|
-
Book.limit(5)
|
|
1831
|
-
# SELECT * FROM books LIMIT 5
|
|
1832
|
-
```
|
|
1833
|
-
|
|
1834
|
-
After:
|
|
1835
|
-
|
|
1836
|
-
```ruby
|
|
1837
|
-
# config/application.rb
|
|
1838
|
-
module MyApp
|
|
1839
|
-
class Application < Rails::Application
|
|
1840
|
-
config.active_record.enumerate_columns_in_select_statements = true
|
|
1841
|
-
end
|
|
1842
|
-
end
|
|
1843
|
-
|
|
1844
|
-
# or, configure per-model
|
|
1845
|
-
class Book < ApplicationRecord
|
|
1846
|
-
self.enumerate_columns_in_select_statements = true
|
|
1847
|
-
end
|
|
1848
|
-
```
|
|
1849
|
-
|
|
1850
|
-
```ruby
|
|
1851
|
-
Book.limit(5)
|
|
1852
|
-
# SELECT id, author_id, name, format, status, language, etc FROM books LIMIT 5
|
|
1853
|
-
```
|
|
1854
|
-
|
|
1855
|
-
*Matt Duszynski*
|
|
1856
|
-
|
|
1857
|
-
* Allow passing SQL as `on_duplicate` value to `#upsert_all` to make it possible to use raw SQL to update columns on conflict:
|
|
1858
|
-
|
|
1859
|
-
```ruby
|
|
1860
|
-
Book.upsert_all(
|
|
1861
|
-
[{ id: 1, status: 1 }, { id: 2, status: 1 }],
|
|
1862
|
-
on_duplicate: Arel.sql("status = GREATEST(books.status, EXCLUDED.status)")
|
|
1863
|
-
)
|
|
1864
|
-
```
|
|
1865
|
-
|
|
1866
|
-
*Vladimir Dementyev*
|
|
1867
|
-
|
|
1868
|
-
* Allow passing SQL as `returning` statement to `#upsert_all`:
|
|
1869
|
-
|
|
1870
|
-
```ruby
|
|
1871
|
-
Article.insert_all(
|
|
1872
|
-
[
|
|
1873
|
-
{ title: "Article 1", slug: "article-1", published: false },
|
|
1874
|
-
{ title: "Article 2", slug: "article-2", published: false }
|
|
1875
|
-
],
|
|
1876
|
-
returning: Arel.sql("id, (xmax = '0') as inserted, name as new_name")
|
|
1877
|
-
)
|
|
1878
|
-
```
|
|
1879
|
-
|
|
1880
|
-
*Vladimir Dementyev*
|
|
1881
|
-
|
|
1882
|
-
* Deprecate `legacy_connection_handling`.
|
|
1883
|
-
|
|
1884
|
-
*Eileen M. Uchitelle*
|
|
1885
|
-
|
|
1886
|
-
* Add attribute encryption support.
|
|
1887
|
-
|
|
1888
|
-
Encrypted attributes are declared at the model level. These
|
|
1889
|
-
are regular Active Record attributes backed by a column with
|
|
1890
|
-
the same name. The system will transparently encrypt these
|
|
1891
|
-
attributes before saving them into the database and will
|
|
1892
|
-
decrypt them when retrieving their values.
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
```ruby
|
|
1896
|
-
class Person < ApplicationRecord
|
|
1897
|
-
encrypts :name
|
|
1898
|
-
encrypts :email_address, deterministic: true
|
|
1899
|
-
end
|
|
1900
|
-
```
|
|
1901
|
-
|
|
1902
|
-
You can learn more in the [Active Record Encryption
|
|
1903
|
-
guide](https://edgeguides.rubyonrails.org/active_record_encryption.html).
|
|
1904
|
-
|
|
1905
|
-
*Jorge Manrubia*
|
|
1906
|
-
|
|
1907
|
-
* Changed Arel predications `contains` and `overlaps` to use
|
|
1908
|
-
`quoted_node` so that PostgreSQL arrays are quoted properly.
|
|
1909
|
-
|
|
1910
|
-
*Bradley Priest*
|
|
1911
|
-
|
|
1912
|
-
* Add mode argument to record level `strict_loading!`.
|
|
1913
|
-
|
|
1914
|
-
This argument can be used when enabling strict loading for a single record
|
|
1915
|
-
to specify that we only want to raise on n plus one queries.
|
|
1916
|
-
|
|
1917
|
-
```ruby
|
|
1918
|
-
developer.strict_loading!(mode: :n_plus_one_only)
|
|
1919
|
-
|
|
1920
|
-
developer.projects.to_a # Does not raise
|
|
1921
|
-
developer.projects.first.client # Raises StrictLoadingViolationError
|
|
1922
|
-
```
|
|
1923
|
-
|
|
1924
|
-
Previously, enabling strict loading would cause any lazily loaded
|
|
1925
|
-
association to raise an error. Using `n_plus_one_only` mode allows us to
|
|
1926
|
-
lazily load belongs_to, has_many, and other associations that are fetched
|
|
1927
|
-
through a single query.
|
|
1928
|
-
|
|
1929
|
-
*Dinah Shi*
|
|
1930
|
-
|
|
1931
|
-
* Fix Float::INFINITY assignment to datetime column with postgresql adapter.
|
|
1932
|
-
|
|
1933
|
-
Before:
|
|
1934
|
-
|
|
1935
|
-
```ruby
|
|
1936
|
-
# With this config
|
|
1937
|
-
ActiveRecord::Base.time_zone_aware_attributes = true
|
|
1938
|
-
|
|
1939
|
-
# and the following schema:
|
|
1940
|
-
create_table "postgresql_infinities" do |t|
|
|
1941
|
-
t.datetime "datetime"
|
|
1942
|
-
end
|
|
1943
|
-
|
|
1944
|
-
# This test fails
|
|
1945
|
-
record = PostgresqlInfinity.create!(datetime: Float::INFINITY)
|
|
1946
|
-
assert_equal Float::INFINITY, record.datetime # record.datetime gets nil
|
|
1947
|
-
```
|
|
1948
|
-
|
|
1949
|
-
After this commit, `record.datetime` gets `Float::INFINITY` as expected.
|
|
1950
|
-
|
|
1951
|
-
*Shunichi Ikegami*
|
|
1952
|
-
|
|
1953
|
-
* Type cast enum values by the original attribute type.
|
|
1954
|
-
|
|
1955
|
-
The notable thing about this change is that unknown labels will no longer match 0 on MySQL.
|
|
1956
|
-
|
|
1957
|
-
```ruby
|
|
1958
|
-
class Book < ActiveRecord::Base
|
|
1959
|
-
enum :status, { proposed: 0, written: 1, published: 2 }
|
|
1960
|
-
end
|
|
1961
|
-
```
|
|
1962
|
-
|
|
1963
|
-
Before:
|
|
1964
|
-
|
|
1965
|
-
```ruby
|
|
1966
|
-
# SELECT `books`.* FROM `books` WHERE `books`.`status` = 'prohibited' LIMIT 1
|
|
1967
|
-
Book.find_by(status: :prohibited)
|
|
1968
|
-
# => #<Book id: 1, status: "proposed", ...> (for mysql2 adapter)
|
|
1969
|
-
# => ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for type integer: "prohibited" (for postgresql adapter)
|
|
1970
|
-
# => nil (for sqlite3 adapter)
|
|
1971
|
-
```
|
|
1972
|
-
|
|
1973
|
-
After:
|
|
1974
|
-
|
|
1975
|
-
```ruby
|
|
1976
|
-
# SELECT `books`.* FROM `books` WHERE `books`.`status` IS NULL LIMIT 1
|
|
1977
|
-
Book.find_by(status: :prohibited)
|
|
1978
|
-
# => nil (for all adapters)
|
|
1979
|
-
```
|
|
1980
|
-
|
|
1981
|
-
*Ryuta Kamizono*
|
|
1982
|
-
|
|
1983
|
-
* Fixtures for `has_many :through` associations now load timestamps on join tables.
|
|
1984
|
-
|
|
1985
|
-
Given this fixture:
|
|
1986
|
-
|
|
1987
|
-
```yml
|
|
1988
|
-
### monkeys.yml
|
|
1989
|
-
george:
|
|
1990
|
-
name: George the Monkey
|
|
1991
|
-
fruits: apple
|
|
1992
|
-
|
|
1993
|
-
### fruits.yml
|
|
1994
|
-
apple:
|
|
1995
|
-
name: apple
|
|
1996
|
-
```
|
|
1997
|
-
|
|
1998
|
-
If the join table (`fruit_monkeys`) contains `created_at` or `updated_at` columns,
|
|
1999
|
-
these will now be populated when loading the fixture. Previously, fixture loading
|
|
2000
|
-
would crash if these columns were required, and leave them as null otherwise.
|
|
2001
|
-
|
|
2002
|
-
*Alex Ghiculescu*
|
|
2003
|
-
|
|
2004
|
-
* Allow applications to configure the thread pool for async queries.
|
|
2005
|
-
|
|
2006
|
-
Some applications may want one thread pool per database whereas others want to use
|
|
2007
|
-
a single global thread pool for all queries. By default, Rails will set `async_query_executor`
|
|
2008
|
-
to `nil` which will not initialize any executor. If `load_async` is called and no executor
|
|
2009
|
-
has been configured, the query will be executed in the foreground.
|
|
2010
|
-
|
|
2011
|
-
To create one thread pool for all database connections to use applications can set
|
|
2012
|
-
`config.active_record.async_query_executor` to `:global_thread_pool` and optionally define
|
|
2013
|
-
`config.active_record.global_executor_concurrency`. This defaults to 4. For applications that want
|
|
2014
|
-
to have a thread pool for each database connection, `config.active_record.async_query_executor` can
|
|
2015
|
-
be set to `:multi_thread_pool`. The configuration for each thread pool is set in the database
|
|
2016
|
-
configuration.
|
|
2017
|
-
|
|
2018
|
-
*Eileen M. Uchitelle*
|
|
2019
|
-
|
|
2020
|
-
* Allow new syntax for `enum` to avoid leading `_` from reserved options.
|
|
2021
|
-
|
|
2022
|
-
Before:
|
|
2023
|
-
|
|
2024
|
-
```ruby
|
|
2025
|
-
class Book < ActiveRecord::Base
|
|
2026
|
-
enum status: [ :proposed, :written ], _prefix: true, _scopes: false
|
|
2027
|
-
enum cover: [ :hard, :soft ], _suffix: true, _default: :hard
|
|
2028
|
-
end
|
|
2029
|
-
```
|
|
2030
|
-
|
|
2031
|
-
After:
|
|
2032
|
-
|
|
2033
|
-
```ruby
|
|
2034
|
-
class Book < ActiveRecord::Base
|
|
2035
|
-
enum :status, [ :proposed, :written ], prefix: true, scopes: false
|
|
2036
|
-
enum :cover, [ :hard, :soft ], suffix: true, default: :hard
|
|
2037
|
-
end
|
|
2038
|
-
```
|
|
2039
|
-
|
|
2040
|
-
*Ryuta Kamizono*
|
|
2041
|
-
|
|
2042
|
-
* Add `ActiveRecord::Relation#load_async`.
|
|
2043
|
-
|
|
2044
|
-
This method schedules the query to be performed asynchronously from a thread pool.
|
|
2045
|
-
|
|
2046
|
-
If the result is accessed before a background thread had the opportunity to perform
|
|
2047
|
-
the query, it will be performed in the foreground.
|
|
2048
|
-
|
|
2049
|
-
This is useful for queries that can be performed long enough before their result will be
|
|
2050
|
-
needed, or for controllers which need to perform several independent queries.
|
|
2051
|
-
|
|
2052
|
-
```ruby
|
|
2053
|
-
def index
|
|
2054
|
-
@categories = Category.some_complex_scope.load_async
|
|
2055
|
-
@posts = Post.some_complex_scope.load_async
|
|
2056
|
-
end
|
|
2057
|
-
```
|
|
2058
|
-
|
|
2059
|
-
Active Record logs will also include timing info for the duration of how long
|
|
2060
|
-
the main thread had to wait to access the result. This timing is useful to know
|
|
2061
|
-
whether or not it's worth to load the query asynchronously.
|
|
2062
|
-
|
|
2063
|
-
```
|
|
2064
|
-
DEBUG -- : Category Load (62.1ms) SELECT * FROM `categories` LIMIT 50
|
|
2065
|
-
DEBUG -- : ASYNC Post Load (64ms) (db time 126.1ms) SELECT * FROM `posts` LIMIT 100
|
|
2066
|
-
```
|
|
2067
|
-
|
|
2068
|
-
The duration in the first set of parens is how long the main thread was blocked
|
|
2069
|
-
waiting for the results, and the second set of parens with "db time" is how long
|
|
2070
|
-
the entire query took to execute.
|
|
2071
|
-
|
|
2072
|
-
*Jean Boussier*
|
|
2073
|
-
|
|
2074
|
-
* Implemented `ActiveRecord::Relation#excluding` method.
|
|
2075
|
-
|
|
2076
|
-
This method excludes the specified record (or collection of records) from
|
|
2077
|
-
the resulting relation:
|
|
2078
|
-
|
|
2079
|
-
```ruby
|
|
2080
|
-
Post.excluding(post)
|
|
2081
|
-
Post.excluding(post_one, post_two)
|
|
2082
|
-
```
|
|
2083
|
-
|
|
2084
|
-
Also works on associations:
|
|
2085
|
-
|
|
2086
|
-
```ruby
|
|
2087
|
-
post.comments.excluding(comment)
|
|
2088
|
-
post.comments.excluding(comment_one, comment_two)
|
|
2089
|
-
```
|
|
2090
|
-
|
|
2091
|
-
This is short-hand for `Post.where.not(id: post.id)` (for a single record)
|
|
2092
|
-
and `Post.where.not(id: [post_one.id, post_two.id])` (for a collection).
|
|
2093
|
-
|
|
2094
|
-
*Glen Crawford*
|
|
2095
|
-
|
|
2096
|
-
* Skip optimised #exist? query when #include? is called on a relation
|
|
2097
|
-
with a having clause.
|
|
2098
|
-
|
|
2099
|
-
Relations that have aliased select values AND a having clause that
|
|
2100
|
-
references an aliased select value would generate an error when
|
|
2101
|
-
#include? was called, due to an optimisation that would generate
|
|
2102
|
-
call #exists? on the relation instead, which effectively alters
|
|
2103
|
-
the select values of the query (and thus removes the aliased select
|
|
2104
|
-
values), but leaves the having clause intact. Because the having
|
|
2105
|
-
clause is then referencing an aliased column that is no longer
|
|
2106
|
-
present in the simplified query, an ActiveRecord::InvalidStatement
|
|
2107
|
-
error was raised.
|
|
2108
|
-
|
|
2109
|
-
A sample query affected by this problem:
|
|
2110
|
-
|
|
2111
|
-
```ruby
|
|
2112
|
-
Author.select('COUNT(*) as total_posts', 'authors.*')
|
|
2113
|
-
.joins(:posts)
|
|
2114
|
-
.group(:id)
|
|
2115
|
-
.having('total_posts > 2')
|
|
2116
|
-
.include?(Author.first)
|
|
2117
|
-
```
|
|
2118
|
-
|
|
2119
|
-
This change adds an addition check to the condition that skips the
|
|
2120
|
-
simplified #exists? query, which simply checks for the presence of
|
|
2121
|
-
a having clause.
|
|
2122
|
-
|
|
2123
|
-
Fixes #41417.
|
|
2124
|
-
|
|
2125
|
-
*Michael Smart*
|
|
2126
|
-
|
|
2127
|
-
* Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
|
|
2128
|
-
without Rails knowledge (e.g., if app gets killed during long-running query or due to Rack::Timeout), app won't end
|
|
2129
|
-
up in perpetual crash state for being inconsistent with PostgreSQL.
|
|
2130
|
-
|
|
2131
|
-
*wbharding*, *Martin Tepper*
|
|
2132
|
-
|
|
2133
|
-
* Add ability to apply `scoping` to `all_queries`.
|
|
2134
|
-
|
|
2135
|
-
Some applications may want to use the `scoping` method but previously it only
|
|
2136
|
-
worked on certain types of queries. This change allows the `scoping` method to apply
|
|
2137
|
-
to all queries for a model in a block.
|
|
2138
|
-
|
|
2139
|
-
```ruby
|
|
2140
|
-
Post.where(blog_id: post.blog_id).scoping(all_queries: true) do
|
|
2141
|
-
post.update(title: "a post title") # adds `posts.blog_id = 1` to the query
|
|
2142
|
-
end
|
|
2143
|
-
```
|
|
2144
|
-
|
|
2145
|
-
*Eileen M. Uchitelle*
|
|
2146
|
-
|
|
2147
|
-
* `ActiveRecord::Calculations.calculate` called with `:average`
|
|
2148
|
-
(aliased as `ActiveRecord::Calculations.average`) will now use column-based
|
|
2149
|
-
type casting. This means that floating-point number columns will now be
|
|
2150
|
-
aggregated as `Float` and decimal columns will be aggregated as `BigDecimal`.
|
|
1298
|
+
*Abeid Ahmed*
|
|
2151
1299
|
|
|
2152
|
-
|
|
2153
|
-
|
|
1300
|
+
* When using a `DATABASE_URL`, allow for a configuration to map the protocol in the URL to a specific database
|
|
1301
|
+
adapter. This allows decoupling the adapter the application chooses to use from the database connection details
|
|
1302
|
+
set in the deployment environment.
|
|
2154
1303
|
|
|
2155
1304
|
```ruby
|
|
2156
|
-
#
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
end
|
|
2160
|
-
|
|
2161
|
-
# Before:
|
|
2162
|
-
Measurement.average(:temperature).class
|
|
2163
|
-
# => BigDecimal
|
|
2164
|
-
|
|
2165
|
-
# After:
|
|
2166
|
-
Measurement.average(:temperature).class
|
|
2167
|
-
# => Float
|
|
1305
|
+
# ENV['DATABASE_URL'] = "mysql://localhost/example_database"
|
|
1306
|
+
config.active_record.protocol_adapters.mysql = "trilogy"
|
|
1307
|
+
# will connect to MySQL using the trilogy adapter
|
|
2168
1308
|
```
|
|
2169
1309
|
|
|
2170
|
-
|
|
2171
|
-
database adapter. This is not the case anymore. If you relied on that kind
|
|
2172
|
-
of magic, you now need to register your own `ActiveRecord::Type`
|
|
2173
|
-
(see `ActiveRecord::Attributes::ClassMethods` for documentation).
|
|
2174
|
-
|
|
2175
|
-
*Josua Schmid*
|
|
2176
|
-
|
|
2177
|
-
* PostgreSQL: introduce `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type`.
|
|
2178
|
-
|
|
2179
|
-
This setting controls what native type Active Record should use when you call `datetime` in
|
|
2180
|
-
a migration or schema. It takes a symbol which must correspond to one of the configured
|
|
2181
|
-
`NATIVE_DATABASE_TYPES`. The default is `:timestamp`, meaning `t.datetime` in a migration
|
|
2182
|
-
will create a "timestamp without time zone" column. To use "timestamp with time zone",
|
|
2183
|
-
change this to `:timestamptz` in an initializer.
|
|
2184
|
-
|
|
2185
|
-
You should run `bin/rails db:migrate` to rebuild your schema.rb if you change this.
|
|
1310
|
+
*Jean Boussier*, *Kevin McPhillips*
|
|
2186
1311
|
|
|
2187
|
-
|
|
1312
|
+
* In cases where MySQL returns `warning_count` greater than zero, but returns no warnings when
|
|
1313
|
+
the `SHOW WARNINGS` query is executed, `ActiveRecord.db_warnings_action` proc will still be
|
|
1314
|
+
called with a generic warning message rather than silently ignoring the warning(s).
|
|
2188
1315
|
|
|
2189
|
-
*
|
|
1316
|
+
*Kevin McPhillips*
|
|
2190
1317
|
|
|
2191
|
-
|
|
2192
|
-
and are created as `timestamptz` columns when the schema is loaded.
|
|
1318
|
+
* `DatabaseConfigurations#configs_for` accepts a symbol in the `name` parameter.
|
|
2193
1319
|
|
|
2194
|
-
*
|
|
1320
|
+
*Andrew Novoselac*
|
|
2195
1321
|
|
|
2196
|
-
*
|
|
2197
|
-
`ActiveRecord::
|
|
1322
|
+
* Fix `where(field: values)` queries when `field` is a serialized attribute
|
|
1323
|
+
(for example, when `field` uses `ActiveRecord::Base.serialize` or is a JSON
|
|
1324
|
+
column).
|
|
2198
1325
|
|
|
2199
|
-
*
|
|
1326
|
+
*João Alves*
|
|
2200
1327
|
|
|
2201
|
-
*
|
|
1328
|
+
* Make the output of `ActiveRecord::Core#inspect` configurable.
|
|
2202
1329
|
|
|
2203
|
-
|
|
2204
|
-
named `ApplicationRecord` can now set a specific class to be the `primary_abstract_class`.
|
|
1330
|
+
By default, calling `inspect` on a record will yield a formatted string including just the `id`.
|
|
2205
1331
|
|
|
2206
1332
|
```ruby
|
|
2207
|
-
|
|
2208
|
-
self.primary_abstract_class
|
|
2209
|
-
end
|
|
1333
|
+
Post.first.inspect #=> "#<Post id: 1>"
|
|
2210
1334
|
```
|
|
2211
1335
|
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
needs to know that the default connection is the same as the `ApplicationRecord` connection.
|
|
2215
|
-
However, some applications have a differently named `ApplicationRecord`. This prevents Active
|
|
2216
|
-
Record from opening duplicate connections to the same database.
|
|
2217
|
-
|
|
2218
|
-
*Eileen M. Uchitelle*, *John Crepezzi*
|
|
2219
|
-
|
|
2220
|
-
* Support hash config for `structure_dump_flags` and `structure_load_flags` flags.
|
|
2221
|
-
Now that Active Record supports multiple databases configuration,
|
|
2222
|
-
we need a way to pass specific flags for dump/load databases since
|
|
2223
|
-
the options are not the same for different adapters.
|
|
2224
|
-
We can use in the original way:
|
|
1336
|
+
The attributes to be included in the output of `inspect` can be configured with
|
|
1337
|
+
`ActiveRecord::Core#attributes_for_inspect`.
|
|
2225
1338
|
|
|
2226
1339
|
```ruby
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = '--no-defaults --skip-add-drop-table'
|
|
1340
|
+
Post.attributes_for_inspect = [:id, :title]
|
|
1341
|
+
Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">"
|
|
2230
1342
|
```
|
|
2231
1343
|
|
|
2232
|
-
|
|
2233
|
-
is the adapter
|
|
1344
|
+
With `attributes_for_inspect` set to `:all`, `inspect` will list all the record's attributes.
|
|
2234
1345
|
|
|
2235
1346
|
```ruby
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
postgres: '--no-tablespaces'
|
|
2239
|
-
}
|
|
1347
|
+
Post.attributes_for_inspect = :all
|
|
1348
|
+
Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
|
|
2240
1349
|
```
|
|
2241
1350
|
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
* Connection specification now passes the "url" key as a configuration for the
|
|
2245
|
-
adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
|
|
2246
|
-
urls with the "jdbc" prefix were passed to the Active Record Adapter, others
|
|
2247
|
-
are assumed to be adapter specification urls.
|
|
2248
|
-
|
|
2249
|
-
Fixes #41137.
|
|
2250
|
-
|
|
2251
|
-
*Jonathan Bracy*
|
|
1351
|
+
In `development` and `test` mode, `attributes_for_inspect` will be set to `:all` by default.
|
|
2252
1352
|
|
|
2253
|
-
|
|
1353
|
+
You can also call `full_inspect` to get an inspection with all the attributes.
|
|
2254
1354
|
|
|
2255
|
-
|
|
2256
|
-
model level.
|
|
1355
|
+
The attributes in `attribute_for_inspect` will also be used for `pretty_print`.
|
|
2257
1356
|
|
|
2258
|
-
|
|
2259
|
-
class User < ApplicationRecord
|
|
2260
|
-
has_many :bookmarks
|
|
2261
|
-
has_many :articles, strict_loading: true
|
|
2262
|
-
end
|
|
1357
|
+
*Andrew Novoselac*
|
|
2263
1358
|
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy>
|
|
1359
|
+
* Don't mark attributes as changed when reassigned to `Float::INFINITY` or
|
|
1360
|
+
`-Float::INFINITY`.
|
|
2267
1361
|
|
|
2268
|
-
|
|
2269
|
-
user.bookmarks # => ActiveRecord::StrictLoadingViolationError
|
|
1362
|
+
*Maicol Bentancor*
|
|
2270
1363
|
|
|
2271
|
-
|
|
2272
|
-
user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy>
|
|
2273
|
-
user.articles.strict_loading!(false) # => #<ActiveRecord::Associations::CollectionProxy>
|
|
2274
|
-
```
|
|
1364
|
+
* Support the `RETURNING` clause for MariaDB.
|
|
2275
1365
|
|
|
2276
|
-
*
|
|
1366
|
+
*fatkodima*, *Nikolay Kondratyev*
|
|
2277
1367
|
|
|
2278
|
-
*
|
|
2279
|
-
presence of exactly one record.
|
|
1368
|
+
* The SQLite3 adapter now implements the `supports_deferrable_constraints?` contract.
|
|
2280
1369
|
|
|
2281
|
-
|
|
2282
|
-
multiple rows matching the condition; especially for when database
|
|
2283
|
-
constraints aren't enough or are impractical.
|
|
1370
|
+
Allows foreign keys to be deferred by adding the `:deferrable` key to the `foreign_key` options.
|
|
2284
1371
|
|
|
2285
1372
|
```ruby
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
# => #<Product ...> (if one Product with given price)
|
|
2289
|
-
# => ActiveRecord::SoleRecordExceeded (if more than one Product with given price)
|
|
2290
|
-
|
|
2291
|
-
user.api_keys.find_sole_by(key: key)
|
|
2292
|
-
# as above
|
|
1373
|
+
add_reference :person, :alias, foreign_key: { deferrable: :deferred }
|
|
1374
|
+
add_reference :alias, :person, foreign_key: { deferrable: :deferred }
|
|
2293
1375
|
```
|
|
2294
1376
|
|
|
2295
|
-
*
|
|
2296
|
-
|
|
2297
|
-
* Makes `ActiveRecord::AttributeMethods::Query` respect the getter overrides defined in the model.
|
|
1377
|
+
*Stephen Margheim*
|
|
2298
1378
|
|
|
2299
|
-
|
|
1379
|
+
* Add the `set_constraints` helper to PostgreSQL connections.
|
|
2300
1380
|
|
|
2301
1381
|
```ruby
|
|
2302
|
-
|
|
2303
|
-
def admin
|
|
2304
|
-
false # Overriding the getter to always return false
|
|
2305
|
-
end
|
|
2306
|
-
end
|
|
2307
|
-
|
|
2308
|
-
user = User.first
|
|
2309
|
-
user.update(admin: true)
|
|
2310
|
-
|
|
2311
|
-
user.admin # false (as expected, due to the getter overwrite)
|
|
2312
|
-
user.admin? # true (not expected, returned the DB column value)
|
|
2313
|
-
```
|
|
2314
|
-
|
|
2315
|
-
After this commit, `user.admin?` above returns false, as expected.
|
|
2316
|
-
|
|
2317
|
-
Fixes #40771.
|
|
2318
|
-
|
|
2319
|
-
*Felipe*
|
|
1382
|
+
Post.create!(user_id: -1) # => ActiveRecord::InvalidForeignKey
|
|
2320
1383
|
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
*Ryota Egusa*
|
|
2329
|
-
|
|
2330
|
-
* Expose an `invert_where` method that will invert all scope conditions.
|
|
2331
|
-
|
|
2332
|
-
```ruby
|
|
2333
|
-
class User
|
|
2334
|
-
scope :active, -> { where(accepted: true, locked: false) }
|
|
1384
|
+
Post.transaction do
|
|
1385
|
+
Post.connection.set_constraints(:deferred)
|
|
1386
|
+
p = Post.create!(user_id: -1)
|
|
1387
|
+
u = User.create!
|
|
1388
|
+
p.user = u
|
|
1389
|
+
p.save!
|
|
2335
1390
|
end
|
|
2336
|
-
|
|
2337
|
-
User.active
|
|
2338
|
-
# ... WHERE `accepted` = 1 AND `locked` = 0
|
|
2339
|
-
|
|
2340
|
-
User.active.invert_where
|
|
2341
|
-
# ... WHERE NOT (`accepted` = 1 AND `locked` = 0)
|
|
2342
|
-
```
|
|
2343
|
-
|
|
2344
|
-
*Kevin Deisz*
|
|
2345
|
-
|
|
2346
|
-
* Restore possibility of passing `false` to :polymorphic option of `belongs_to`.
|
|
2347
|
-
|
|
2348
|
-
Previously, passing `false` would trigger the option validation logic
|
|
2349
|
-
to throw an error saying :polymorphic would not be a valid option.
|
|
2350
|
-
|
|
2351
|
-
*glaszig*
|
|
2352
|
-
|
|
2353
|
-
* Remove deprecated `database` kwarg from `connected_to`.
|
|
2354
|
-
|
|
2355
|
-
*Eileen M. Uchitelle*, *John Crepezzi*
|
|
2356
|
-
|
|
2357
|
-
* Allow adding nonnamed expression indexes to be revertible.
|
|
2358
|
-
|
|
2359
|
-
Previously, the following code would raise an error, when executed while rolling back,
|
|
2360
|
-
and the index name should be specified explicitly. Now, the index name is inferred
|
|
2361
|
-
automatically.
|
|
2362
|
-
|
|
2363
|
-
```ruby
|
|
2364
|
-
add_index(:items, "to_tsvector('english', description)")
|
|
2365
1391
|
```
|
|
2366
1392
|
|
|
2367
|
-
|
|
1393
|
+
*Cody Cutrer*
|
|
2368
1394
|
|
|
2369
|
-
|
|
1395
|
+
* Include `ActiveModel::API` in `ActiveRecord::Base`.
|
|
2370
1396
|
|
|
2371
|
-
*
|
|
1397
|
+
*Sean Doyle*
|
|
2372
1398
|
|
|
2373
|
-
|
|
1399
|
+
* Ensure `#signed_id` outputs `url_safe` strings.
|
|
2374
1400
|
|
|
2375
|
-
*
|
|
1401
|
+
*Jason Meller*
|
|
2376
1402
|
|
|
2377
|
-
* Add
|
|
1403
|
+
* Add `nulls_last` and working `desc.nulls_first` for MySQL.
|
|
2378
1404
|
|
|
2379
|
-
|
|
1405
|
+
*Tristan Fellows*
|
|
2380
1406
|
|
|
2381
|
-
|
|
1407
|
+
* Allow for more complex hash arguments for `order` which mimics `where` in `ActiveRecord::Relation`.
|
|
2382
1408
|
|
|
2383
1409
|
```ruby
|
|
2384
|
-
|
|
2385
|
-
default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true
|
|
2386
|
-
end
|
|
1410
|
+
Topic.includes(:posts).order(posts: { created_at: :desc })
|
|
2387
1411
|
```
|
|
2388
1412
|
|
|
2389
|
-
*
|
|
2390
|
-
|
|
2391
|
-
* Add `where.associated` to check for the presence of an association.
|
|
2392
|
-
|
|
2393
|
-
```ruby
|
|
2394
|
-
# Before:
|
|
2395
|
-
account.users.joins(:contact).where.not(contact_id: nil)
|
|
2396
|
-
|
|
2397
|
-
# After:
|
|
2398
|
-
account.users.where.associated(:contact)
|
|
2399
|
-
```
|
|
2400
|
-
|
|
2401
|
-
Also mirrors `where.missing`.
|
|
2402
|
-
|
|
2403
|
-
*Kasper Timm Hansen*
|
|
2404
|
-
|
|
2405
|
-
* Allow constructors (`build_association` and `create_association`) on
|
|
2406
|
-
`has_one :through` associations.
|
|
2407
|
-
|
|
2408
|
-
*Santiago Perez Perret*
|
|
2409
|
-
|
|
1413
|
+
*Myles Boone*
|
|
2410
1414
|
|
|
2411
|
-
Please check [
|
|
1415
|
+
Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activerecord/CHANGELOG.md) for previous changes.
|