activerecord 6.1.4 → 7.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1049 -977
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +33 -17
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +34 -27
- data/lib/active_record/associations/collection_proxy.rb +8 -3
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +187 -55
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +49 -13
- data/lib/active_record/associations/preloader.rb +39 -113
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +90 -82
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +49 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +66 -12
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +13 -14
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +6 -21
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +47 -561
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +42 -72
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +34 -9
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +69 -18
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
- data/lib/active_record/connection_adapters/abstract_adapter.rb +149 -74
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +97 -81
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +35 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +35 -21
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +4 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +50 -50
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +27 -16
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +205 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +29 -4
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +25 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +15 -16
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +47 -53
- data/lib/active_record/core.rb +122 -132
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -9
- data/lib/active_record/database_configurations/hash_config.rb +63 -5
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +16 -32
- data/lib/active_record/delegated_type.rb +52 -11
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +90 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +49 -42
- data/lib/active_record/errors.rb +67 -4
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +41 -6
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +17 -20
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +80 -14
- data/lib/active_record/integration.rb +4 -3
- data/lib/active_record/internal_metadata.rb +3 -5
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/locking/pessimistic.rb +9 -3
- data/lib/active_record/log_subscriber.rb +14 -3
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +8 -3
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +4 -4
- data/lib/active_record/migration/compatibility.rb +83 -1
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +109 -79
- data/lib/active_record/model_schema.rb +45 -58
- data/lib/active_record/nested_attributes.rb +13 -12
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +219 -52
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +127 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +66 -129
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +67 -50
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +40 -36
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +31 -35
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +235 -61
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +171 -84
- data/lib/active_record/result.rb +17 -7
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema_dumper.rb +10 -3
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/default.rb +61 -12
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +64 -34
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/suppressor.rb +11 -15
- data/lib/active_record/tasks/database_tasks.rb +116 -58
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -12
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +4 -4
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +2 -2
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +1 -1
- data/lib/active_record.rb +204 -28
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/predications.rb +11 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +8 -2
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +58 -2
- data/lib/arel.rb +2 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- metadata +56 -13
data/CHANGELOG.md
CHANGED
@@ -1,1591 +1,1663 @@
|
|
1
|
-
|
1
|
+
* Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name`.
|
2
2
|
|
3
|
-
*
|
4
|
-
|
5
|
-
*Jamie McCarthy*
|
6
|
-
|
7
|
-
* Raise an error if `pool_config` is `nil` in `set_pool_config`.
|
8
|
-
|
9
|
-
*Eileen M. Uchitelle*
|
10
|
-
|
11
|
-
* Fix compatibility with `psych >= 4`.
|
12
|
-
|
13
|
-
Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility
|
14
|
-
Active Record's schema cache loader and `YAMLColumn` now uses `YAML.unsafe_load` if available.
|
15
|
-
|
16
|
-
*Jean Boussier*
|
17
|
-
|
18
|
-
* Support using replicas when using `rails dbconsole`.
|
19
|
-
|
20
|
-
*Christopher Thornton*
|
21
|
-
|
22
|
-
* Restore connection pools after transactional tests.
|
23
|
-
|
24
|
-
*Eugene Kenny*
|
25
|
-
|
26
|
-
* Change `upsert_all` to fails cleanly for MySQL when `:unique_by` is used.
|
27
|
-
|
28
|
-
*Bastian Bartmann*
|
29
|
-
|
30
|
-
* Fix user-defined `self.default_scope` to respect table alias.
|
3
|
+
*Rafael Mendonça França*
|
31
4
|
|
32
|
-
|
5
|
+
* Remove deprecated `ActiveRecord::Connection#in_clause_length`.
|
33
6
|
|
34
|
-
*
|
7
|
+
*Rafael Mendonça França*
|
35
8
|
|
36
|
-
|
9
|
+
* Remove deprecated `ActiveRecord::Connection#allowed_index_name_length`.
|
37
10
|
|
38
|
-
*
|
39
|
-
`quoted_node` so that PostgreSQL arrays are quoted properly.
|
11
|
+
*Rafael Mendonça França*
|
40
12
|
|
41
|
-
|
13
|
+
* Remove deprecated `ActiveRecord::Base#remove_connection`.
|
42
14
|
|
43
|
-
*
|
15
|
+
*Rafael Mendonça França*
|
44
16
|
|
45
|
-
|
17
|
+
* Load STI Models in fixtures
|
46
18
|
|
47
|
-
|
19
|
+
Data from Fixtures now loads based on the specific class for models with
|
20
|
+
Single Table Inheritance. This affects enums defined in subclasses, previously
|
21
|
+
the value of these fields was not parsed and remained `nil`
|
48
22
|
|
49
|
-
*
|
23
|
+
*Andres Howard*
|
50
24
|
|
51
|
-
*
|
25
|
+
* `#authenticate` returns false when the password is blank instead of raising an error.
|
52
26
|
|
53
|
-
*
|
27
|
+
*Muhammad Muhammad Ibrahim*
|
54
28
|
|
55
|
-
*
|
29
|
+
* Fix `ActiveRecord::QueryMethods#in_order_of` behavior for integer enums.
|
56
30
|
|
57
|
-
|
58
|
-
relation set `strict_loading` to false the false wasn't considered when
|
59
|
-
deciding whether to raise/warn about strict loading.
|
31
|
+
`ActiveRecord::QueryMethods#in_order_of` didn't work as expected for enums stored as integers in the database when passing an array of strings or symbols as the order argument. This unexpected behavior occurred because the string or symbol values were not casted to match the integers in the database.
|
60
32
|
|
61
|
-
|
62
|
-
class Dog < ActiveRecord::Base
|
63
|
-
self.strict_loading_by_default = true
|
33
|
+
The following example now works as expected:
|
64
34
|
|
65
|
-
|
35
|
+
```ruby
|
36
|
+
class Book < ApplicationRecord
|
37
|
+
enum status: [:proposed, :written, :published]
|
66
38
|
end
|
67
|
-
```
|
68
|
-
|
69
|
-
In the example, `dog.treats` would still raise even though
|
70
|
-
`strict_loading` was set to false. This is a bug effecting more than
|
71
|
-
Active Storage which is why I made this PR superceeding #41461. We need
|
72
|
-
to fix this for all applications since the behavior is a little
|
73
|
-
surprising. I took the test from ##41461 and the code suggestion from #41453
|
74
|
-
with some additions.
|
75
|
-
|
76
|
-
*Eileen M. Uchitelle*, *Radamés Roriz*
|
77
|
-
|
78
|
-
* Fix numericality validator without precision.
|
79
|
-
|
80
|
-
*Ryuta Kamizono*
|
81
|
-
|
82
|
-
* Fix aggregate attribute on Enum types.
|
83
|
-
|
84
|
-
*Ryuta Kamizono*
|
85
39
|
|
86
|
-
|
40
|
+
Book.in_order_of(:status, %w[written published proposed])
|
41
|
+
```
|
87
42
|
|
88
|
-
*
|
43
|
+
*Alexandre Ruban*
|
89
44
|
|
90
|
-
*
|
45
|
+
* Ignore persisted in-memory records when merging target lists.
|
91
46
|
|
92
|
-
*
|
47
|
+
*Kevin Sjöberg*
|
93
48
|
|
94
|
-
*
|
49
|
+
* Add a new option `:update_only` to `upsert_all` to configure the list of columns to update in case of conflict.
|
95
50
|
|
96
|
-
|
51
|
+
Before, you could only customize the update SQL sentence via `:on_duplicate`. There is now a new option `:update_only` that lets you provide a list of columns to update in case of conflict:
|
97
52
|
|
53
|
+
```ruby
|
54
|
+
Commodity.upsert_all(
|
55
|
+
[
|
56
|
+
{ id: 2, name: "Copper", price: 4.84 },
|
57
|
+
{ id: 4, name: "Gold", price: 1380.87 },
|
58
|
+
{ id: 6, name: "Aluminium", price: 0.35 }
|
59
|
+
],
|
60
|
+
update_only: [:price] # Only prices will be updated
|
61
|
+
)
|
62
|
+
```
|
98
63
|
|
99
|
-
|
64
|
+
*Jorge Manrubia*
|
100
65
|
|
101
|
-
*
|
66
|
+
* Remove deprecated `ActiveRecord::Result#map!` and `ActiveRecord::Result#collect!`.
|
102
67
|
|
68
|
+
*Rafael Mendonça França*
|
103
69
|
|
104
|
-
|
70
|
+
* Remove deprecated `ActiveRecord::Base.configurations.to_h`.
|
105
71
|
|
106
|
-
*
|
72
|
+
*Rafael Mendonça França*
|
107
73
|
|
74
|
+
* Remove deprecated `ActiveRecord::Base.configurations.default_hash`.
|
108
75
|
|
109
|
-
|
76
|
+
*Rafael Mendonça França*
|
110
77
|
|
111
|
-
*
|
112
|
-
to the connection session.
|
78
|
+
* Remove deprecated `ActiveRecord::Base.arel_attribute`.
|
113
79
|
|
114
80
|
*Rafael Mendonça França*
|
115
81
|
|
116
|
-
*
|
117
|
-
are enabled.
|
82
|
+
* Remove deprecated `ActiveRecord::Base.connection_config`.
|
118
83
|
|
119
84
|
*Rafael Mendonça França*
|
120
85
|
|
121
|
-
*
|
122
|
-
an `IN` clause.
|
86
|
+
* Filter attributes in SQL logs
|
123
87
|
|
124
|
-
|
125
|
-
|
126
|
-
* Skip optimised #exist? query when #include? is called on a relation
|
127
|
-
with a having clause
|
88
|
+
Previously, SQL queries in logs containing `ActiveRecord::Base.filter_attributes` were not filtered.
|
128
89
|
|
129
|
-
|
130
|
-
references an aliased select value would generate an error when
|
131
|
-
#include? was called, due to an optimisation that would generate
|
132
|
-
call #exists? on the relation instead, which effectively alters
|
133
|
-
the select values of the query (and thus removes the aliased select
|
134
|
-
values), but leaves the having clause intact. Because the having
|
135
|
-
clause is then referencing an aliased column that is no longer
|
136
|
-
present in the simplified query, an ActiveRecord::InvalidStatement
|
137
|
-
error was raised.
|
90
|
+
Now, the filter attributes will be masked `[FILTERED]` in the logs when `prepared_statement` is enabled.
|
138
91
|
|
139
|
-
|
92
|
+
```
|
93
|
+
# Before:
|
94
|
+
Foo Load (0.2ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "hello"], ["LIMIT", 1]]
|
140
95
|
|
141
|
-
|
142
|
-
|
143
|
-
.joins(:posts)
|
144
|
-
.group(:id)
|
145
|
-
.having('total_posts > 2')
|
146
|
-
.include?(Author.first)
|
96
|
+
# After:
|
97
|
+
Foo Load (0.5ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "[FILTERED]"], ["LIMIT", 1]]
|
147
98
|
```
|
148
99
|
|
149
|
-
|
150
|
-
simplified #exists? query, which simply checks for the presence of
|
151
|
-
a having clause.
|
100
|
+
*Aishwarya Subramanian*
|
152
101
|
|
153
|
-
|
102
|
+
* Remove deprecated `Tasks::DatabaseTasks.spec`.
|
154
103
|
|
155
|
-
*
|
104
|
+
*Rafael Mendonça França*
|
156
105
|
|
157
|
-
*
|
158
|
-
without Rails knowledge (e.g., if app gets kill -9d during long-running query or due to Rack::Timeout), app won't end
|
159
|
-
up in perpetual crash state for being inconsistent with Postgres.
|
106
|
+
* Remove deprecated `Tasks::DatabaseTasks.current_config`.
|
160
107
|
|
161
|
-
*
|
108
|
+
*Rafael Mendonça França*
|
162
109
|
|
110
|
+
* Deprecate `Tasks::DatabaseTasks.schema_file_type`.
|
163
111
|
|
164
|
-
|
112
|
+
*Rafael Mendonça França*
|
165
113
|
|
166
|
-
*
|
114
|
+
* Remove deprecated `Tasks::DatabaseTasks.dump_filename`.
|
167
115
|
|
168
|
-
|
169
|
-
for validating the money format in the PostgreSQL adapter. This patch
|
170
|
-
fixes the regexp.
|
116
|
+
*Rafael Mendonça França*
|
171
117
|
|
172
|
-
|
118
|
+
* Remove deprecated `Tasks::DatabaseTasks.schema_file`.
|
173
119
|
|
174
|
-
|
120
|
+
*Rafael Mendonça França*
|
175
121
|
|
176
|
-
|
122
|
+
* Remove deprecated `environment` and `name` arguments from `Tasks::DatabaseTasks.schema_up_to_date?`.
|
177
123
|
|
124
|
+
*Rafael Mendonça França*
|
178
125
|
|
179
|
-
|
126
|
+
* Merging conditions on the same column no longer maintain both conditions,
|
127
|
+
and will be consistently replaced by the latter condition.
|
180
128
|
|
181
|
-
|
129
|
+
```ruby
|
130
|
+
# Rails 6.1 (IN clause is replaced by merger side equality condition)
|
131
|
+
Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
|
132
|
+
# Rails 6.1 (both conflict conditions exists, deprecated)
|
133
|
+
Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []
|
134
|
+
# Rails 6.1 with rewhere to migrate to Rails 7.0's behavior
|
135
|
+
Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]
|
136
|
+
# Rails 7.0 (same behavior with IN clause, mergee side condition is consistently replaced)
|
137
|
+
Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
|
138
|
+
Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]
|
182
139
|
|
183
|
-
*
|
140
|
+
*Rafael Mendonça França*
|
184
141
|
|
185
|
-
*
|
142
|
+
* Remove deprecated support to `Model.reorder(nil).first` to search using non-deterministic order.
|
186
143
|
|
187
|
-
|
188
|
-
case the job would enqueue even though the database deletion
|
189
|
-
rolledback putting things in a funky state.
|
144
|
+
*Rafael Mendonça França*
|
190
145
|
|
191
|
-
|
146
|
+
* Remove deprecated rake tasks:
|
192
147
|
|
193
|
-
*
|
148
|
+
* `db:schema:load_if_ruby`
|
149
|
+
* `db:structure:dump`
|
150
|
+
* `db:structure:load`
|
151
|
+
* `db:structure:load_if_sql`
|
152
|
+
* `db:structure:dump:#{name}`
|
153
|
+
* `db:structure:load:#{name}`
|
154
|
+
* `db:test:load_structure`
|
155
|
+
* `db:test:load_structure:#{name}`
|
194
156
|
|
195
|
-
*
|
157
|
+
*Rafael Mendonça França*
|
196
158
|
|
197
|
-
|
159
|
+
* Remove deprecated `DatabaseConfig#config` method.
|
198
160
|
|
199
|
-
*
|
200
|
-
adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
|
201
|
-
urls with the "jdbc" prefix were passed to the Active Record Adapter, others
|
202
|
-
are assumed to be adapter specification urls.
|
161
|
+
*Rafael Mendonça França*
|
203
162
|
|
204
|
-
|
163
|
+
* Rollback transactions when the block returns earlier than expected.
|
205
164
|
|
206
|
-
|
165
|
+
Before this change, when a transaction block returned early, the transaction would be committed.
|
207
166
|
|
208
|
-
|
167
|
+
The problem is that timeouts triggered inside the transaction block was also making the incomplete transaction
|
168
|
+
to be committed, so in order to avoid this mistake, the transaction block is rolled back.
|
209
169
|
|
210
|
-
*
|
170
|
+
*Rafael Mendonça França*
|
211
171
|
|
212
|
-
*
|
172
|
+
* Add middleware for automatic shard swapping.
|
213
173
|
|
214
|
-
|
174
|
+
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:
|
215
175
|
|
216
|
-
|
176
|
+
```ruby
|
177
|
+
config.active_record.shard_resolver = ->(request) {
|
178
|
+
subdomain = request.subdomain
|
179
|
+
tenant = Tenant.find_by_subdomain!(subdomain)
|
180
|
+
tenant.shard
|
181
|
+
}
|
182
|
+
```
|
217
183
|
|
218
|
-
|
184
|
+
See guides for more details.
|
219
185
|
|
220
|
-
*
|
186
|
+
*Eileen M. Uchitelle*, *John Crepezzi*
|
221
187
|
|
222
|
-
|
188
|
+
* Remove deprecated support to pass a column to `type_cast`.
|
223
189
|
|
224
|
-
*
|
190
|
+
*Rafael Mendonça França*
|
225
191
|
|
226
|
-
|
192
|
+
* Remove deprecated support to type cast to database values `ActiveRecord::Base` objects.
|
227
193
|
|
194
|
+
*Rafael Mendonça França*
|
228
195
|
|
229
|
-
|
196
|
+
* Remove deprecated support to quote `ActiveRecord::Base` objects.
|
230
197
|
|
231
|
-
*
|
198
|
+
*Rafael Mendonça França*
|
232
199
|
|
233
|
-
|
200
|
+
* Remove deprecacated support to resolve connection using `"primary"` as connection specification name.
|
234
201
|
|
235
|
-
*
|
202
|
+
*Rafael Mendonça França*
|
236
203
|
|
237
|
-
|
204
|
+
* Remove deprecation warning when using `:interval` column is used in PostgreSQL database.
|
238
205
|
|
239
|
-
|
206
|
+
Now, interval columns will return `ActiveSupport::Duration` objects instead of strings.
|
240
207
|
|
241
|
-
|
208
|
+
To keep the old behavior, you can add this line to your model:
|
242
209
|
|
243
|
-
|
210
|
+
```ruby
|
211
|
+
attribute :column, :string
|
212
|
+
```
|
244
213
|
|
245
|
-
*
|
214
|
+
*Rafael Mendonça França*
|
246
215
|
|
247
|
-
*
|
216
|
+
* Remove deprecated support to YAML load `ActiveRecord::Base` instance in the Rails 4.2 and 4.1 formats.
|
248
217
|
|
249
|
-
*
|
218
|
+
*Rafael Mendonça França*
|
250
219
|
|
251
|
-
*
|
220
|
+
* Remove deprecated option `:spec_name` in the `configs_for` method.
|
252
221
|
|
253
|
-
*
|
222
|
+
*Rafael Mendonça França*
|
254
223
|
|
255
|
-
*
|
224
|
+
* Remove deprecated `ActiveRecord::Base.allow_unsafe_raw_sql`.
|
256
225
|
|
257
226
|
*Rafael Mendonça França*
|
258
227
|
|
259
|
-
* Fix
|
260
|
-
|
261
|
-
*Ryuta Kamizono*
|
228
|
+
* Fix regression bug that caused ignoring additional conditions for preloading has_many-through relations.
|
262
229
|
|
263
|
-
|
230
|
+
Fixes #43132
|
264
231
|
|
265
|
-
*
|
232
|
+
*Alexander Pauly*
|
266
233
|
|
267
|
-
*
|
234
|
+
* Fix `has_many` inversing recursion on models with recursive associations.
|
268
235
|
|
269
|
-
|
270
|
-
to throw an error saying :polymorphic would not be a valid option.
|
236
|
+
*Gannon McGibbon*
|
271
237
|
|
272
|
-
|
238
|
+
* Add `accepts_nested_attributes_for` support for `delegated_type`
|
273
239
|
|
274
|
-
|
240
|
+
```ruby
|
241
|
+
class Entry < ApplicationRecord
|
242
|
+
delegated_type :entryable, types: %w[ Message Comment ]
|
243
|
+
accepts_nested_attributes_for :entryable
|
244
|
+
end
|
275
245
|
|
276
|
-
|
246
|
+
entry = Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })
|
247
|
+
# => #<Entry:0x00>
|
248
|
+
# id: 1
|
249
|
+
# entryable_id: 1,
|
250
|
+
# entryable_type: 'Message'
|
251
|
+
# ...>
|
252
|
+
|
253
|
+
entry.entryable
|
254
|
+
# => #<Message:0x01>
|
255
|
+
# id: 1
|
256
|
+
# content: 'Hello world'
|
257
|
+
# ...>
|
258
|
+
```
|
277
259
|
|
278
|
-
Previously
|
279
|
-
and the index name should be specified explicitly. Now, the index name is inferred
|
280
|
-
automatically.
|
260
|
+
Previously it would raise an error:
|
281
261
|
|
282
262
|
```ruby
|
283
|
-
|
263
|
+
Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })
|
264
|
+
# ArgumentError: Cannot build association `entryable'. Are you trying to build a polymorphic one-to-one association?
|
284
265
|
```
|
285
266
|
|
286
|
-
*
|
287
|
-
|
288
|
-
|
289
|
-
## Rails 6.1.0 (December 09, 2020) ##
|
290
|
-
|
291
|
-
* Only warn about negative enums if a positive form that would cause conflicts exists.
|
292
|
-
|
293
|
-
Fixes #39065.
|
294
|
-
|
295
|
-
*Alex Ghiculescu*
|
296
|
-
|
297
|
-
* Change `attribute_for_inspect` to take `filter_attributes` in consideration.
|
267
|
+
*Sjors Baltus*
|
298
268
|
|
299
|
-
|
269
|
+
* Use subquery for DELETE with GROUP_BY and HAVING clauses.
|
300
270
|
|
301
|
-
|
271
|
+
Prior to this change, deletes with GROUP_BY and HAVING were returning an error.
|
302
272
|
|
303
|
-
|
273
|
+
After this change, GROUP_BY and HAVING are valid clauses in DELETE queries, generating the following query:
|
304
274
|
|
305
|
-
|
275
|
+
```sql
|
276
|
+
DELETE FROM "posts" WHERE "posts"."id" IN (
|
277
|
+
SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" GROUP BY "posts"."id" HAVING (count(comments.id) >= 2))
|
278
|
+
) [["flagged", "t"]]
|
279
|
+
```
|
306
280
|
|
307
|
-
*
|
281
|
+
*Ignacio Chiazzo Cardarello*
|
308
282
|
|
309
|
-
|
310
|
-
class AdminAuthor
|
311
|
-
delegate_missing_to :@author
|
283
|
+
* Use subquery for UPDATE with GROUP_BY and HAVING clauses.
|
312
284
|
|
313
|
-
|
314
|
-
@author = author
|
315
|
-
end
|
316
|
-
end
|
285
|
+
Prior to this change, updates with GROUP_BY and HAVING were being ignored, generating a SQL like this:
|
317
286
|
|
318
|
-
|
287
|
+
```sql
|
288
|
+
UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
|
289
|
+
SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
|
290
|
+
) [["flagged", "t"]]
|
319
291
|
```
|
320
292
|
|
321
|
-
|
293
|
+
After this change, GROUP_BY and HAVING clauses are used as a subquery in updates, like this:
|
322
294
|
|
323
|
-
|
295
|
+
```sql
|
296
|
+
UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
|
297
|
+
SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
|
298
|
+
GROUP BY posts.id HAVING (count(comments.id) >= 2)
|
299
|
+
) [["flagged", "t"]]
|
300
|
+
```
|
324
301
|
|
325
|
-
|
302
|
+
*Ignacio Chiazzo Cardarello*
|
326
303
|
|
327
|
-
|
304
|
+
* Add support for setting the filename of the schema or structure dump in the database config.
|
328
305
|
|
329
|
-
|
330
|
-
MealsRecord.connected_to(role: :reading) do
|
331
|
-
Dog.first # read from animals replica
|
332
|
-
Dinner.first # read from meals replica
|
333
|
-
Person.first # read from primary writer
|
334
|
-
end
|
335
|
-
end
|
306
|
+
Applications may now set their the filename or path of the schema / structure dump file in their database configuration.
|
336
307
|
|
337
|
-
After:
|
338
308
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
309
|
+
```yaml
|
310
|
+
production:
|
311
|
+
primary:
|
312
|
+
database: my_db
|
313
|
+
schema_dump: my_schema_dump_filename.rb
|
314
|
+
animals:
|
315
|
+
database: animals_db
|
316
|
+
schema_dump: false
|
317
|
+
```
|
344
318
|
|
345
|
-
|
319
|
+
The filename set in `schema_dump` will be used by the application. If set to `false` the schema will not be dumped. The database tasks are responsible for adding the database directory to the filename. If a full path is provided, the Rails tasks will use that instead of `ActiveRecord::DatabaseTasks.db_dir`.
|
346
320
|
|
347
|
-
*
|
321
|
+
*Eileen M. Uchitelle*, *Ryan Kerr*
|
348
322
|
|
349
|
-
|
323
|
+
* Add `ActiveRecord::Base.prohibit_shard_swapping` to prevent attempts to change the shard within a block.
|
350
324
|
|
351
|
-
|
325
|
+
*John Crepezzi*, *Eileen M. Uchitelle*
|
352
326
|
|
353
|
-
|
327
|
+
* Filter unchanged attributes with default function from insert query when `partial_inserts` is disabled.
|
354
328
|
|
355
|
-
*
|
329
|
+
*Akshay Birajdar*, *Jacopo Beschi*
|
356
330
|
|
357
|
-
|
331
|
+
* Add support for FILTER clause (SQL:2003) to Arel.
|
358
332
|
|
359
|
-
|
333
|
+
Currently supported by PostgreSQL 9.4+ and SQLite 3.30+.
|
360
334
|
|
361
|
-
*
|
335
|
+
*Andrey Novikov*
|
362
336
|
|
363
|
-
|
337
|
+
* Automatically set timestamps on record creation during bulk insert/upsert
|
364
338
|
|
365
|
-
|
339
|
+
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}`).
|
366
340
|
|
367
|
-
|
341
|
+
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.
|
368
342
|
|
369
|
-
|
343
|
+
Note that this means `upsert_all` on models with `record_timestamps = false` will no longer touch `updated_{at,on}` automatically.
|
370
344
|
|
371
|
-
*
|
372
|
-
no longer enforce case sensitive comparison by default.
|
345
|
+
*Sam Bostock*
|
373
346
|
|
374
|
-
|
347
|
+
* Don't require `role` when passing `shard` to `connected_to`.
|
375
348
|
|
376
|
-
|
349
|
+
`connected_to` can now be called with a `shard` only. Note that `role` is still inherited if `connected_to` calls are nested.
|
377
350
|
|
378
|
-
|
379
|
-
`table_name_length`
|
380
|
-
`columns_per_table`
|
381
|
-
`indexes_per_table`
|
382
|
-
`columns_per_multicolumn_index`
|
383
|
-
`sql_query_length`
|
384
|
-
`joins_per_query`
|
351
|
+
*Eileen M. Uchitelle*
|
385
352
|
|
386
|
-
|
353
|
+
* Add option to lazily load the schema cache on the connection.
|
387
354
|
|
388
|
-
|
355
|
+
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.
|
389
356
|
|
390
|
-
|
357
|
+
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.
|
391
358
|
|
392
|
-
*
|
359
|
+
*Eileen M. Uchitelle*
|
393
360
|
|
394
|
-
|
361
|
+
* Allow automatic `inverse_of` detection for associations with scopes.
|
395
362
|
|
396
|
-
|
363
|
+
Automatic `inverse_of` detection now works for associations with scopes. For
|
364
|
+
example, the `comments` association here now automatically detects
|
365
|
+
`inverse_of: :post`, so we don't need to pass that option:
|
397
366
|
|
398
|
-
|
367
|
+
```ruby
|
368
|
+
class Post < ActiveRecord::Base
|
369
|
+
has_many :comments, -> { visible }
|
370
|
+
end
|
399
371
|
|
400
|
-
|
372
|
+
class Comment < ActiveRecord::Base
|
373
|
+
belongs_to :post
|
374
|
+
end
|
375
|
+
```
|
401
376
|
|
402
|
-
|
377
|
+
Note that the automatic detection still won't work if the inverse
|
378
|
+
association has a scope. In this example a scope on the `post` association
|
379
|
+
would still prevent Rails from finding the inverse for the `comments`
|
380
|
+
association.
|
403
381
|
|
404
|
-
|
382
|
+
This will be the default for new apps in Rails 7. To opt in:
|
405
383
|
|
406
|
-
|
384
|
+
```ruby
|
385
|
+
config.active_record.automatic_scope_inversing = true
|
386
|
+
```
|
407
387
|
|
408
|
-
*
|
388
|
+
*Daniel Colson*, *Chris Bloom*
|
409
389
|
|
410
|
-
|
390
|
+
* Accept optional transaction args to `ActiveRecord::Locking::Pessimistic#with_lock`
|
411
391
|
|
412
|
-
|
413
|
-
|
392
|
+
`#with_lock` now accepts transaction options like `requires_new:`,
|
393
|
+
`isolation:`, and `joinable:`
|
414
394
|
|
415
|
-
|
395
|
+
* Adds support for deferrable foreign key constraints in PostgreSQL.
|
416
396
|
|
417
|
-
|
418
|
-
|
419
|
-
|
397
|
+
By default, foreign key constraints in PostgreSQL are checked after each statement. This works for most use cases,
|
398
|
+
but becomes a major limitation when creating related records before the parent record is inserted into the database.
|
399
|
+
One example of this is looking up / creating a person via one or more unique alias.
|
420
400
|
|
421
|
-
|
401
|
+
```ruby
|
402
|
+
Person.transaction do
|
403
|
+
alias = Alias
|
404
|
+
.create_with(user_id: SecureRandom.uuid)
|
405
|
+
.create_or_find_by(name: "DHH")
|
406
|
+
|
407
|
+
person = Person
|
408
|
+
.create_with(name: "David Heinemeier Hansson")
|
409
|
+
.create_or_find_by(id: alias.user_id)
|
410
|
+
end
|
411
|
+
```
|
422
412
|
|
423
|
-
|
424
|
-
User.find_by(name: "David") # => #<User name: "David", ...>
|
425
|
-
end
|
413
|
+
Using the default behavior, the transaction would fail when executing the first `INSERT` statement.
|
426
414
|
|
427
|
-
|
415
|
+
By passing the `:deferrable` option to the `add_foreign_key` statement in migrations, it's possible to defer this
|
416
|
+
check.
|
428
417
|
|
429
|
-
|
418
|
+
```ruby
|
419
|
+
add_foreign_key :aliases, :person, deferrable: true
|
420
|
+
```
|
430
421
|
|
431
|
-
|
432
|
-
|
433
|
-
|
422
|
+
Passing `deferrable: true` doesn't change the default behavior, but allows manually deferring the check using
|
423
|
+
`SET CONSTRAINTS ALL DEFERRED` within a transaction. This will cause the foreign keys to be checked after the
|
424
|
+
transaction.
|
434
425
|
|
435
|
-
|
426
|
+
It's also possible to adjust the default behavior from an immediate check (after the statement), to a deferred check
|
427
|
+
(after the transaction):
|
436
428
|
|
437
|
-
|
438
|
-
|
429
|
+
```ruby
|
430
|
+
add_foreign_key :aliases, :person, deferrable: :deferred
|
431
|
+
```
|
439
432
|
|
440
|
-
|
433
|
+
*Benedikt Deicke*
|
441
434
|
|
442
|
-
|
443
|
-
# SELECT * FROM users WHERE name = 'David'
|
435
|
+
* Allow configuring Postgres password through the socket URL.
|
444
436
|
|
445
|
-
|
437
|
+
For example:
|
438
|
+
```ruby
|
439
|
+
ActiveRecord::DatabaseConfigurations::UrlConfig.new(
|
440
|
+
:production, :production, 'postgres:///?user=user&password=secret&dbname=app', {}
|
441
|
+
).configuration_hash
|
442
|
+
```
|
446
443
|
|
447
|
-
|
444
|
+
will now return,
|
448
445
|
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
`values`
|
453
|
-
`[]=`
|
446
|
+
```ruby
|
447
|
+
{ :user=>"user", :password=>"secret", :dbname=>"app", :adapter=>"postgresql" }
|
448
|
+
```
|
454
449
|
|
455
|
-
*
|
450
|
+
*Abeid Ahmed*
|
456
451
|
|
457
|
-
*
|
452
|
+
* PostgreSQL: support custom enum types
|
458
453
|
|
459
|
-
|
454
|
+
In migrations, use `create_enum` to add a new enum type, and `t.enum` to add a column.
|
460
455
|
|
461
|
-
|
462
|
-
|
456
|
+
```ruby
|
457
|
+
def up
|
458
|
+
create_enum :mood, ["happy", "sad"]
|
463
459
|
|
464
|
-
|
460
|
+
change_table :cats do |t|
|
461
|
+
t.enum :current_mood, enum_type: "mood", default: "happy", null: false
|
462
|
+
end
|
463
|
+
end
|
464
|
+
```
|
465
465
|
|
466
|
-
|
467
|
-
|
466
|
+
Enums will be presented correctly in `schema.rb`. Note that this is only supported by
|
467
|
+
the PostgreSQL adapter.
|
468
468
|
|
469
|
-
*
|
469
|
+
*Alex Ghiculescu*
|
470
470
|
|
471
|
-
*
|
471
|
+
* Avoid COMMENT statements in PostgreSQL structure dumps
|
472
472
|
|
473
|
-
|
473
|
+
COMMENT statements are now omitted from the output of `db:structure:dump` when using PostgreSQL >= 11.
|
474
|
+
This allows loading the dump without a pgsql superuser account.
|
474
475
|
|
475
|
-
|
476
|
+
Fixes #36816, #43107.
|
476
477
|
|
477
|
-
*
|
478
|
+
*Janosch Müller*
|
478
479
|
|
479
|
-
*
|
480
|
+
* Add support for generated columns in PostgreSQL adapter
|
480
481
|
|
481
|
-
|
482
|
+
Generated columns are supported since version 12.0 of PostgreSQL. This adds
|
483
|
+
support of those to the PostgreSQL adapter.
|
482
484
|
|
483
|
-
|
484
|
-
|
485
|
+
```ruby
|
486
|
+
create_table :users do |t|
|
487
|
+
t.string :name
|
488
|
+
t.virtual :name_upcased, type: :string, as: 'upper(name)', stored: true
|
489
|
+
end
|
490
|
+
```
|
485
491
|
|
486
|
-
*
|
492
|
+
*Michał Begejowicz*
|
487
493
|
|
488
|
-
* Connections can be granularly switched for abstract classes when `connected_to` is called.
|
489
494
|
|
490
|
-
|
495
|
+
## Rails 7.0.0.alpha2 (September 15, 2021) ##
|
491
496
|
|
492
|
-
|
497
|
+
* No changes.
|
493
498
|
|
494
|
-
Given an application we have a `User` model that inherits from `ApplicationRecord` and a `Dog` model that inherits from `AnimalsRecord`. `AnimalsRecord` and `ApplicationRecord` have writing and reading connections as well as shard `default`, `one`, and `two`.
|
495
499
|
|
496
|
-
|
497
|
-
ActiveRecord::Base.connected_to(role: :reading) do
|
498
|
-
User.first # reads from default replica
|
499
|
-
Dog.first # reads from default replica
|
500
|
+
## Rails 7.0.0.alpha1 (September 15, 2021) ##
|
500
501
|
|
501
|
-
|
502
|
-
User.first # reads from default replica
|
503
|
-
Dog.first # reads from shard one primary
|
504
|
-
end
|
502
|
+
* Remove warning when overwriting existing scopes
|
505
503
|
|
506
|
-
|
507
|
-
Dog.first # reads from default replica
|
504
|
+
Removes the following unnecessary warning message that appeared when overwriting existing scopes
|
508
505
|
|
509
|
-
|
510
|
-
|
511
|
-
Dog.first # reads from default replica
|
512
|
-
end
|
513
|
-
end
|
506
|
+
```
|
507
|
+
Creating scope :my_scope_name. Overwriting existing method "MyClass.my_scope_name" when overwriting existing scopes
|
514
508
|
```
|
515
509
|
|
516
|
-
|
517
|
-
|
518
|
-
* Allow double-dash comment syntax when querying read-only databases
|
519
|
-
|
520
|
-
*James Adam*
|
510
|
+
*Weston Ganger*
|
521
511
|
|
522
|
-
*
|
512
|
+
* Use full precision for `updated_at` in `insert_all`/`upsert_all`
|
523
513
|
|
524
|
-
|
514
|
+
`CURRENT_TIMESTAMP` provides differing precision depending on the database,
|
515
|
+
and not all databases support explicitly specifying additional precision.
|
525
516
|
|
526
|
-
|
527
|
-
|
528
|
-
topic.values_at(:title, :author_name)
|
529
|
-
# => ["Budget", "Jason"]
|
530
|
-
```
|
517
|
+
Instead, we delegate to the new `connection.high_precision_current_timestamp`
|
518
|
+
for the SQL to produce a high precision timestamp on the current database.
|
531
519
|
|
532
|
-
|
520
|
+
Fixes #42992
|
533
521
|
|
534
|
-
*
|
522
|
+
*Sam Bostock*
|
535
523
|
|
536
|
-
*
|
524
|
+
* Add ssl support for postgresql database tasks
|
537
525
|
|
538
|
-
|
526
|
+
Add `PGSSLMODE`, `PGSSLCERT`, `PGSSLKEY` and `PGSSLROOTCERT` to pg_env from database config
|
527
|
+
when running postgresql database tasks.
|
539
528
|
|
540
|
-
|
529
|
+
```yaml
|
530
|
+
# config/database.yml
|
541
531
|
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
}
|
548
|
-
end
|
532
|
+
production:
|
533
|
+
sslmode: verify-full
|
534
|
+
sslcert: client.crt
|
535
|
+
sslkey: client.key
|
536
|
+
sslrootcert: ca.crt
|
549
537
|
```
|
550
538
|
|
551
|
-
|
552
|
-
|
553
|
-
* `BatchEnumerator#update_all` and `BatchEnumerator#delete_all` now return the
|
554
|
-
total number of rows affected, just like their non-batched counterparts.
|
539
|
+
Environment variables
|
555
540
|
|
556
|
-
```
|
557
|
-
|
558
|
-
|
541
|
+
```
|
542
|
+
PGSSLMODE=verify-full
|
543
|
+
PGSSLCERT=client.crt
|
544
|
+
PGSSLKEY=client.key
|
545
|
+
PGSSLROOTCERT=ca.crt
|
559
546
|
```
|
560
547
|
|
561
|
-
Fixes #
|
562
|
-
|
563
|
-
*Eugene Kenny*
|
548
|
+
Fixes #42994
|
564
549
|
|
565
|
-
*
|
566
|
-
`ActiveSupport::Duration` when loading records from database and
|
567
|
-
serialization to ISO 8601 formatted duration string on save.
|
568
|
-
Add support to define a column in migrations and get it in a schema dump.
|
569
|
-
Optional column precision is supported.
|
550
|
+
*Michael Bayucot*
|
570
551
|
|
571
|
-
|
552
|
+
* Avoid scoping update callbacks in `ActiveRecord::Relation#update!`.
|
572
553
|
|
573
|
-
|
554
|
+
Making it consistent with how scoping is applied only to the query in `ActiveRecord::Relation#update`
|
555
|
+
and not also to the callbacks from the update itself.
|
574
556
|
|
575
|
-
|
557
|
+
*Dylan Thacker-Smith*
|
576
558
|
|
577
|
-
|
559
|
+
* Fix 2 cases that inferred polymorphic class from the association's `foreign_type`
|
560
|
+
using `String#constantize` instead of the model's `polymorphic_class_for`.
|
578
561
|
|
579
|
-
|
562
|
+
When updating a polymorphic association, the old `foreign_type` was not inferred correctly when:
|
563
|
+
1. `touch`ing the previously associated record
|
564
|
+
2. updating the previously associated record's `counter_cache`
|
580
565
|
|
581
|
-
|
582
|
-
t.string :name
|
583
|
-
t.interval :duration
|
584
|
-
end
|
566
|
+
*Jimmy Bourassa*
|
585
567
|
|
586
|
-
|
587
|
-
attribute :duration, :interval
|
588
|
-
end
|
568
|
+
* Add config option for ignoring tables when dumping the schema cache.
|
589
569
|
|
590
|
-
|
591
|
-
Event.last.duration # => 2 days
|
592
|
-
Event.last.duration.iso8601 # => "P2D"
|
593
|
-
Event.new(duration: 'P1DT12H3S').duration # => 1 day, 12 hours, and 3 seconds
|
594
|
-
Event.new(duration: '1 day') # Unknown value will be ignored and NULL will be written to database
|
570
|
+
Applications can now be configured to ignore certain tables when dumping the schema cache.
|
595
571
|
|
596
|
-
|
597
|
-
|
598
|
-
* Allow associations supporting the `dependent:` key to take `dependent: :destroy_async`.
|
572
|
+
The configuration option can table an array of tables:
|
599
573
|
|
600
574
|
```ruby
|
601
|
-
|
602
|
-
belongs_to :supplier, dependent: :destroy_async
|
603
|
-
end
|
575
|
+
config.active_record.schema_cache_ignored_tables = ["ignored_table", "another_ignored_table"]
|
604
576
|
```
|
605
577
|
|
606
|
-
|
578
|
+
Or a regex:
|
607
579
|
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
*Jason Schweier*
|
613
|
-
|
614
|
-
* `connects_to` can only be called on `ActiveRecord::Base` or abstract classes.
|
615
|
-
|
616
|
-
Ensure that `connects_to` can only be called from `ActiveRecord::Base` or abstract classes. This protects the application from opening duplicate or too many connections.
|
580
|
+
```ruby
|
581
|
+
config.active_record.schema_cache_ignored_tables = [/^_/]
|
582
|
+
```
|
617
583
|
|
618
|
-
*Eileen M. Uchitelle
|
584
|
+
*Eileen M. Uchitelle*
|
619
585
|
|
620
|
-
*
|
621
|
-
`ActiveRecord::StatementInvalid` when they encounter a connection error.
|
586
|
+
* Make schema cache methods return consistent results.
|
622
587
|
|
623
|
-
|
588
|
+
Previously the schema cache methods `primary_keys`, `columns`, `columns_hash`, and `indexes`
|
589
|
+
would behave differently than one another when a table didn't exist and differently across
|
590
|
+
database adapters. This change unifies the behavior so each method behaves the same regardless
|
591
|
+
of adapter.
|
624
592
|
|
625
|
-
|
626
|
-
`ActiveRecord::StatementInvalid` when it can't connect to the MySQL server.
|
593
|
+
The behavior now is:
|
627
594
|
|
628
|
-
|
595
|
+
`columns`: (unchanged) raises a db error if the table does not exist.
|
596
|
+
`columns_hash`: (unchanged) raises a db error if the table does not exist.
|
597
|
+
`primary_keys`: (unchanged) returns `nil` if the table does not exist.
|
598
|
+
`indexes`: (changed for mysql2) returns `[]` if the table does not exist.
|
629
599
|
|
630
|
-
*
|
600
|
+
*Eileen M. Uchitelle*
|
631
601
|
|
632
|
-
|
602
|
+
* Reestablish connection to previous database after after running `db:schema:load:name`
|
633
603
|
|
634
|
-
|
604
|
+
After running `db:schema:load:name` the previous connection is restored.
|
635
605
|
|
636
|
-
|
606
|
+
*Jacopo Beschi*
|
637
607
|
|
638
|
-
|
608
|
+
* Add database config option `database_tasks`
|
639
609
|
|
640
|
-
|
610
|
+
If you would like to connect to an external database without any database
|
611
|
+
management tasks such as schema management, migrations, seeds, etc. you can set
|
612
|
+
the per database config option `database_tasks: false`
|
641
613
|
|
642
|
-
```
|
643
|
-
|
644
|
-
enum label: [:default, :child]
|
645
|
-
has_many :children, class_name: "Comment", foreign_key: :parent_id
|
646
|
-
end
|
614
|
+
```yaml
|
615
|
+
# config/database.yml
|
647
616
|
|
648
|
-
|
649
|
-
|
617
|
+
production:
|
618
|
+
primary:
|
619
|
+
database: my_database
|
620
|
+
adapter: mysql2
|
621
|
+
animals:
|
622
|
+
database: my_animals_database
|
623
|
+
adapter: mysql2
|
624
|
+
database_tasks: false
|
650
625
|
```
|
651
626
|
|
652
|
-
*
|
653
|
-
|
654
|
-
* Support storing demodulized class name for polymorphic type.
|
627
|
+
*Weston Ganger*
|
655
628
|
|
656
|
-
|
657
|
-
by `store_full_sti_class` class attribute.
|
629
|
+
* Fix `ActiveRecord::InternalMetadata` to not be broken by `config.active_record.record_timestamps = false`
|
658
630
|
|
659
|
-
|
660
|
-
|
661
|
-
*Ryuta Kamizono*
|
631
|
+
Since the model always create the timestamp columns, it has to set them, otherwise it breaks
|
632
|
+
various DB management tasks.
|
662
633
|
|
663
|
-
|
664
|
-
`rails db:schema:{load, dump}` tasks to work with either `:ruby` or `:sql` format,
|
665
|
-
depending on `config.active_record.schema_format` configuration value.
|
634
|
+
Fixes #42983
|
666
635
|
|
667
|
-
|
636
|
+
* Add `ActiveRecord::QueryLogs`.
|
668
637
|
|
669
|
-
|
638
|
+
Configurable tags can be automatically added to all SQL queries generated by Active Record.
|
670
639
|
|
671
640
|
```ruby
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
post.title # => "Welcome to the weblog"
|
679
|
-
post.body # => "Such a lovely day"
|
680
|
-
|
681
|
-
# Rails 6.1 (respect the `select` values)
|
682
|
-
post = Post.select("UPPER(title) AS title").eager_load(:comments).first
|
683
|
-
post.title # => "WELCOME TO THE WEBLOG"
|
684
|
-
post.body # => ActiveModel::MissingAttributeError
|
641
|
+
# config/application.rb
|
642
|
+
module MyApp
|
643
|
+
class Application < Rails::Application
|
644
|
+
config.active_record.query_log_tags_enabled = true
|
645
|
+
end
|
646
|
+
end
|
685
647
|
```
|
686
648
|
|
687
|
-
|
688
|
-
|
689
|
-
* Allow attribute's default to be configured but keeping its own type.
|
649
|
+
By default the application, controller and action details are added to the query tags:
|
690
650
|
|
691
651
|
```ruby
|
692
|
-
class
|
693
|
-
|
652
|
+
class BooksController < ApplicationController
|
653
|
+
def index
|
654
|
+
@books = Book.all
|
655
|
+
end
|
694
656
|
end
|
695
|
-
|
696
|
-
# Rails 6.0
|
697
|
-
Post.type_for_attribute(:written_at) # => #<Type::Value ... precision: nil, ...>
|
698
|
-
|
699
|
-
# Rails 6.1
|
700
|
-
Post.type_for_attribute(:written_at) # => #<Type::DateTime ... precision: 6, ...>
|
701
657
|
```
|
702
658
|
|
703
|
-
|
659
|
+
```ruby
|
660
|
+
GET /books
|
661
|
+
# SELECT * FROM books /*application:MyApp;controller:books;action:index*/
|
662
|
+
```
|
704
663
|
|
705
|
-
|
664
|
+
Custom tags containing static values and Procs can be defined in the application configuration:
|
706
665
|
|
707
666
|
```ruby
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
667
|
+
config.active_record.query_log_tags = [
|
668
|
+
:application,
|
669
|
+
:controller,
|
670
|
+
:action,
|
671
|
+
{
|
672
|
+
custom_static: "foo",
|
673
|
+
custom_dynamic: -> { Time.now }
|
674
|
+
}
|
675
|
+
]
|
713
676
|
```
|
714
677
|
|
715
|
-
*
|
678
|
+
*Keeran Raj Hawoldar*, *Eileen M. Uchitelle*, *Kasper Timm Hansen*
|
716
679
|
|
717
|
-
*
|
680
|
+
* Added support for multiple databases to `rails db:setup` and `rails db:reset`.
|
718
681
|
|
719
|
-
*
|
682
|
+
*Ryan Hall*
|
720
683
|
|
721
|
-
*
|
722
|
-
allows you to specify that all string columns should be frozen unless
|
723
|
-
otherwise specified. This will reduce memory pressure for applications which
|
724
|
-
do not generally mutate string properties of Active Record objects.
|
684
|
+
* Add `ActiveRecord::Relation#structurally_compatible?`.
|
725
685
|
|
726
|
-
|
686
|
+
Adds a query method by which a user can tell if the relation that they're
|
687
|
+
about to use for `#or` or `#and` is structurally compatible with the
|
688
|
+
receiver.
|
727
689
|
|
728
|
-
*
|
690
|
+
*Kevin Newton*
|
729
691
|
|
730
|
-
|
692
|
+
* Add `ActiveRecord::QueryMethods#in_order_of`.
|
731
693
|
|
732
|
-
|
694
|
+
This allows you to specify an explicit order that you'd like records
|
695
|
+
returned in based on a SQL expression. By default, this will be accomplished
|
696
|
+
using a case statement, as in:
|
733
697
|
|
734
698
|
```ruby
|
735
|
-
|
736
|
-
mary_and_bob = Author.where(id: [mary, bob])
|
737
|
-
|
738
|
-
david_and_mary.merge(mary_and_bob) # => [mary, bob]
|
739
|
-
|
740
|
-
david_and_mary.and(mary_and_bob) # => [mary]
|
741
|
-
david_and_mary.or(mary_and_bob) # => [david, mary, bob]
|
699
|
+
Post.in_order_of(:id, [3, 5, 1])
|
742
700
|
```
|
743
701
|
|
744
|
-
|
745
|
-
|
746
|
-
* Merging conditions on the same column no longer maintain both conditions,
|
747
|
-
and will be consistently replaced by the latter condition in Rails 6.2.
|
748
|
-
To migrate to Rails 6.2's behavior, use `relation.merge(other, rewhere: true)`.
|
749
|
-
|
750
|
-
```ruby
|
751
|
-
# Rails 6.1 (IN clause is replaced by merger side equality condition)
|
752
|
-
Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
|
702
|
+
will generate the SQL:
|
753
703
|
|
754
|
-
|
755
|
-
|
704
|
+
```sql
|
705
|
+
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
|
706
|
+
```
|
756
707
|
|
757
|
-
|
758
|
-
|
708
|
+
However, because this functionality is built into MySQL in the form of the
|
709
|
+
`FIELD` function, that connection adapter will generate the following SQL
|
710
|
+
instead:
|
759
711
|
|
760
|
-
|
761
|
-
|
762
|
-
Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]
|
712
|
+
```sql
|
713
|
+
SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC
|
763
714
|
```
|
764
715
|
|
765
|
-
*
|
716
|
+
*Kevin Newton*
|
766
717
|
|
767
|
-
*
|
718
|
+
* Fix `eager_loading?` when ordering with `Symbol`.
|
768
719
|
|
769
|
-
|
720
|
+
`eager_loading?` is triggered correctly when using `order` with symbols.
|
770
721
|
|
771
|
-
|
722
|
+
```ruby
|
723
|
+
scope = Post.includes(:comments).order(:"comments.label")
|
724
|
+
=> true
|
725
|
+
```
|
772
726
|
|
773
|
-
|
774
|
-
`ActiveRecord::Persistence.upsert_all` was used with the name of an expression index, an error
|
775
|
-
was raised. Adding a guard around the formatting behavior for the `:unique_by` corrects this.
|
727
|
+
*Jacopo Beschi*
|
776
728
|
|
777
|
-
|
729
|
+
* Two change tracking methods are added for `belongs_to` associations.
|
778
730
|
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
t.index "lower(name)", unique: true
|
783
|
-
end
|
731
|
+
The `association_changed?` method (assuming an association named `:association`) returns true
|
732
|
+
if a different associated object has been assigned and the foreign key will be updated in the
|
733
|
+
next save.
|
784
734
|
|
785
|
-
|
786
|
-
|
735
|
+
The `association_previously_changed?` method returns true if the previous save updated the
|
736
|
+
association to reference a different associated object.
|
787
737
|
|
788
|
-
|
738
|
+
*George Claghorn*
|
789
739
|
|
790
|
-
|
740
|
+
* Add option to disable schema dump per-database.
|
791
741
|
|
792
|
-
|
742
|
+
Dumping the schema is on by default for all databases in an application. To turn it off for a
|
743
|
+
specific database, use the `schema_dump` option:
|
793
744
|
|
794
|
-
|
745
|
+
```yaml
|
746
|
+
# config/database.yml
|
795
747
|
|
796
|
-
|
797
|
-
|
798
|
-
remove_check_constraint :products, name: "price_check"
|
748
|
+
production:
|
749
|
+
schema_dump: false
|
799
750
|
```
|
800
751
|
|
801
|
-
*
|
752
|
+
*Luis Vasconcellos*, *Eileen M. Uchitelle*
|
802
753
|
|
803
|
-
*
|
804
|
-
to enable/disable strict_loading mode by default for a model. The configuration's value is
|
805
|
-
inheritable by subclasses, but they can override that value and it will not impact parent class.
|
754
|
+
* Fix `eager_loading?` when ordering with `Hash` syntax.
|
806
755
|
|
807
|
-
|
756
|
+
`eager_loading?` is triggered correctly when using `order` with hash syntax
|
757
|
+
on an outer table.
|
808
758
|
|
809
759
|
```ruby
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
has_many :projects
|
814
|
-
end
|
815
|
-
|
816
|
-
dev = Developer.first
|
817
|
-
dev.projects.first
|
818
|
-
# => ActiveRecord::StrictLoadingViolationError Exception: Developer is marked as strict_loading and Project cannot be lazily loaded.
|
760
|
+
Post.includes(:comments).order({ "comments.label": :ASC }).eager_loading?
|
761
|
+
# => true
|
819
762
|
```
|
820
763
|
|
821
|
-
*
|
764
|
+
*Jacopo Beschi*
|
822
765
|
|
823
|
-
*
|
766
|
+
* Move the forcing of clear text encoding to the `ActiveRecord::Encryption::Encryptor`.
|
824
767
|
|
825
|
-
|
768
|
+
Fixes #42699.
|
826
769
|
|
827
|
-
*
|
828
|
-
|
829
|
-
Before:
|
770
|
+
*J Smith*
|
830
771
|
|
831
|
-
|
832
|
-
create_table "accounts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
|
833
|
-
end
|
834
|
-
```
|
772
|
+
* `partial_inserts` is now disabled by default in new apps.
|
835
773
|
|
836
|
-
|
774
|
+
This will be the default for new apps in Rails 7. To opt in:
|
837
775
|
|
838
776
|
```ruby
|
839
|
-
|
840
|
-
end
|
777
|
+
config.active_record.partial_inserts = true
|
841
778
|
```
|
842
779
|
|
843
|
-
|
780
|
+
If a migration removes the default value of a column, this option
|
781
|
+
would cause old processes to no longer be able to create new records.
|
844
782
|
|
845
|
-
|
846
|
-
|
783
|
+
If you need to remove a column, you should first use `ignored_columns`
|
784
|
+
to stop using it.
|
847
785
|
|
848
|
-
*
|
786
|
+
*Jean Boussier*
|
849
787
|
|
850
|
-
*
|
788
|
+
* Rails can now verify foreign keys after loading fixtures in tests.
|
851
789
|
|
852
|
-
|
790
|
+
This will be the default for new apps in Rails 7. To opt in:
|
853
791
|
|
854
792
|
```ruby
|
855
|
-
|
856
|
-
|
857
|
-
# duplicated group fields, deprecated.
|
858
|
-
accounts.merge(accounts.where.not(credit_limit: nil)).sum(:credit_limit)
|
859
|
-
# => {
|
860
|
-
# [1, 1] => 50,
|
861
|
-
# [2, 2] => 60
|
862
|
-
# }
|
863
|
-
|
864
|
-
# use `uniq!(:group)` to deduplicate group fields.
|
865
|
-
accounts.merge(accounts.where.not(credit_limit: nil)).uniq!(:group).sum(:credit_limit)
|
866
|
-
# => {
|
867
|
-
# 1 => 50,
|
868
|
-
# 2 => 60
|
869
|
-
# }
|
793
|
+
config.active_record.verify_foreign_keys_for_fixtures = true
|
870
794
|
```
|
871
795
|
|
872
|
-
|
796
|
+
Tests will not run if there is a foreign key constraint violation in your fixture data.
|
873
797
|
|
874
|
-
|
798
|
+
The feature is supported by SQLite and PostgreSQL, other adapters can also add support for it.
|
875
799
|
|
876
|
-
|
800
|
+
*Alex Ghiculescu*
|
877
801
|
|
878
|
-
|
879
|
-
accounts = Account.where(id: [1, 2]).annotate("david and mary")
|
802
|
+
* Clear cached `has_one` association after setting `belongs_to` association to `nil`.
|
880
803
|
|
881
|
-
|
882
|
-
|
883
|
-
# SELECT accounts.* FROM accounts WHERE accounts.id = 3 /* david and mary */ /* david and mary */
|
804
|
+
After setting a `belongs_to` relation to `nil` and updating an unrelated attribute on the owner,
|
805
|
+
the owner should still return `nil` on the `has_one` relation.
|
884
806
|
|
885
|
-
#
|
886
|
-
accounts.merge(accounts.rewhere(id: 3)).uniq!(:annotate)
|
887
|
-
# SELECT accounts.* FROM accounts WHERE accounts.id = 3 /* david and mary */
|
888
|
-
```
|
807
|
+
Fixes #42597.
|
889
808
|
|
890
|
-
*
|
809
|
+
*Michiel de Mare*
|
891
810
|
|
892
|
-
*
|
811
|
+
* OpenSSL constants are now used for Digest computations.
|
893
812
|
|
894
|
-
|
895
|
-
cache. This avoids raising an unnecessary `ActiveRecord::StaleObjectError`
|
896
|
-
upon subsequent transactions by maintaining parity with the corresponding
|
897
|
-
database record's `lock_version` column.
|
813
|
+
*Dirkjan Bussink*
|
898
814
|
|
899
|
-
|
815
|
+
* Adds support for `if_not_exists` to `add_foreign_key` and `if_exists` to `remove_foreign_key`.
|
900
816
|
|
901
|
-
|
817
|
+
Applications can set their migrations to ignore exceptions raised when adding a foreign key
|
818
|
+
that already exists or when removing a foreign key that does not exist.
|
902
819
|
|
903
|
-
|
820
|
+
Example Usage:
|
904
821
|
|
905
822
|
```ruby
|
906
|
-
|
823
|
+
class AddAuthorsForeignKeyToArticles < ActiveRecord::Migration[7.0]
|
824
|
+
def change
|
825
|
+
add_foreign_key :articles, :authors, if_not_exists: true
|
826
|
+
end
|
827
|
+
end
|
828
|
+
```
|
907
829
|
|
908
|
-
|
909
|
-
|
830
|
+
```ruby
|
831
|
+
class RemoveAuthorsForeignKeyFromArticles < ActiveRecord::Migration[7.0]
|
832
|
+
def change
|
833
|
+
remove_foreign_key :articles, :authors, if_exists: true
|
834
|
+
end
|
835
|
+
end
|
836
|
+
```
|
910
837
|
|
911
|
-
|
912
|
-
david_and_mary.merge(Author.rewhere(id: bob)) # => [bob]
|
838
|
+
*Roberto Miranda*
|
913
839
|
|
914
|
-
|
915
|
-
david_and_mary.merge(Author.where(id: bob), rewhere: true) # => [bob]
|
916
|
-
```
|
840
|
+
* Prevent polluting ENV during postgresql structure dump/load.
|
917
841
|
|
918
|
-
|
842
|
+
Some configuration parameters were provided to pg_dump / psql via
|
843
|
+
environment variables which persisted beyond the command being run, and may
|
844
|
+
have caused subsequent commands and connections to fail. Tasks running
|
845
|
+
across multiple postgresql databases like `rails db:test:prepare` may have
|
846
|
+
been affected.
|
919
847
|
|
920
|
-
*
|
921
|
-
set to expire and scoped with a purpose. This is particularly useful for things like password reset
|
922
|
-
or email verification, where you want the bearer of the signed id to be able to interact with the
|
923
|
-
underlying record, but usually only within a certain time period.
|
848
|
+
*Samuel Cochran*
|
924
849
|
|
925
|
-
|
926
|
-
signed_id = User.first.signed_id expires_in: 15.minutes, purpose: :password_reset
|
850
|
+
* Set precision 6 by default for `datetime` columns.
|
927
851
|
|
928
|
-
|
852
|
+
By default, datetime columns will have microseconds precision instead of seconds precision.
|
929
853
|
|
930
|
-
|
931
|
-
User.find_signed signed_id, purpose: :password_reset # => nil, since the signed id has expired
|
854
|
+
*Roberto Miranda*
|
932
855
|
|
933
|
-
|
934
|
-
User.find_signed signed_id, purpose: :password_reset # => User.first
|
856
|
+
* Allow preloading of associations with instance dependent scopes.
|
935
857
|
|
936
|
-
|
937
|
-
```
|
858
|
+
*John Hawthorn*, *John Crepezzi*, *Adam Hess*, *Eileen M. Uchitelle*, *Dinah Shi*
|
938
859
|
|
939
|
-
|
860
|
+
* Do not try to rollback transactions that failed due to a `ActiveRecord::TransactionRollbackError`.
|
940
861
|
|
941
|
-
*
|
862
|
+
*Jamie McCarthy*
|
942
863
|
|
943
|
-
|
864
|
+
* Active Record Encryption will now encode values as UTF-8 when using deterministic
|
865
|
+
encryption. The encoding is part of the encrypted payload, so different encodings for
|
866
|
+
different values result in different ciphertexts. This can break unique constraints and
|
867
|
+
queries.
|
944
868
|
|
945
|
-
|
869
|
+
The new behavior is configurable via `active_record.encryption.forced_encoding_for_deterministic_encryption`
|
870
|
+
that is `Encoding::UTF_8` by default. It can be disabled by setting it to `nil`.
|
946
871
|
|
947
|
-
*
|
872
|
+
*Jorge Manrubia*
|
948
873
|
|
949
|
-
*
|
874
|
+
* The MySQL adapter now cast numbers and booleans bind parameters to string for safety reasons.
|
950
875
|
|
951
|
-
|
876
|
+
When comparing a string and a number in a query, MySQL converts the string to a number. So for
|
877
|
+
instance `"foo" = 0`, will implicitly cast `"foo"` to `0` and will evaluate to `TRUE` which can
|
878
|
+
lead to security vulnerabilities.
|
952
879
|
|
953
|
-
|
954
|
-
|
955
|
-
posts = posts.where("posts.hidden": false, "comments.hidden": false)
|
880
|
+
Active Record already protect against that vulnerability when it knows the type of the column
|
881
|
+
being compared, however until now it was still vulnerable when using bind parameters:
|
956
882
|
|
957
|
-
|
958
|
-
|
883
|
+
```ruby
|
884
|
+
User.where("login_token = ?", 0).first
|
885
|
+
```
|
959
886
|
|
960
|
-
|
961
|
-
posts.unscope(where: :hidden).count
|
962
|
-
# => { false => 11, true => 1 }
|
887
|
+
Would perform:
|
963
888
|
|
964
|
-
|
965
|
-
|
966
|
-
# => { false => 11 }
|
889
|
+
```sql
|
890
|
+
SELECT * FROM `users` WHERE `login_token` = 0 LIMIT 1;
|
967
891
|
```
|
968
892
|
|
969
|
-
|
893
|
+
Now it will perform:
|
970
894
|
|
971
|
-
|
895
|
+
```sql
|
896
|
+
SELECT * FROM `users` WHERE `login_token` = '0' LIMIT 1;
|
897
|
+
```
|
972
898
|
|
973
|
-
|
974
|
-
steve = Person.find_by(name: "Steve")
|
975
|
-
david = Author.find_by(name: "David")
|
899
|
+
*Jean Boussier*
|
976
900
|
|
977
|
-
|
901
|
+
* Fixture configurations (`_fixture`) are now strictly validated.
|
978
902
|
|
979
|
-
|
980
|
-
|
903
|
+
If an error will be raised if that entry contains unknown keys while previously it
|
904
|
+
would silently have no effects.
|
981
905
|
|
982
|
-
|
983
|
-
relation.rewhere(writer: david).to_a # => [david]
|
984
|
-
```
|
906
|
+
*Jean Boussier*
|
985
907
|
|
986
|
-
|
908
|
+
* Add `ActiveRecord::Base.update!` that works like `ActiveRecord::Base.update` but raises exceptions.
|
987
909
|
|
988
|
-
|
910
|
+
This allows for the same behavior as the instance method `#update!` at a class level.
|
989
911
|
|
990
912
|
```ruby
|
991
|
-
|
992
|
-
=> #<Knot id: 1, created_at: "2016-05-05 01:29:47.116928000 +0000">
|
913
|
+
Person.update!(:all, state: "confirmed")
|
993
914
|
```
|
994
915
|
|
995
|
-
*
|
916
|
+
*Dorian Marié*
|
996
917
|
|
997
|
-
*
|
918
|
+
* Add `ActiveRecord::Base#attributes_for_database`.
|
998
919
|
|
999
|
-
|
920
|
+
Returns attributes with values for assignment to the database.
|
1000
921
|
|
1001
|
-
*
|
922
|
+
*Chris Salzberg*
|
1002
923
|
|
1003
|
-
|
924
|
+
* Use an empty query to check if the PostgreSQL connection is still active.
|
1004
925
|
|
1005
|
-
|
926
|
+
An empty query is faster than `SELECT 1`.
|
1006
927
|
|
1007
|
-
*
|
928
|
+
*Heinrich Lee Yu*
|
1008
929
|
|
1009
|
-
*
|
930
|
+
* Add `ActiveRecord::Base#previously_persisted?`.
|
1010
931
|
|
1011
|
-
|
932
|
+
Returns `true` if the object has been previously persisted but now it has been deleted.
|
1012
933
|
|
1013
|
-
*
|
934
|
+
* Deprecate `partial_writes` in favor of `partial_inserts` and `partial_updates`.
|
1014
935
|
|
1015
|
-
|
936
|
+
This allows to have a different behavior on update and create.
|
1016
937
|
|
1017
|
-
*
|
938
|
+
*Jean Boussier*
|
1018
939
|
|
1019
|
-
*
|
940
|
+
* Fix compatibility with `psych >= 4`.
|
1020
941
|
|
1021
|
-
|
942
|
+
Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility,
|
943
|
+
Active Record's schema cache loader and `YAMLColumn` now uses `YAML.unsafe_load` if available.
|
1022
944
|
|
1023
|
-
*
|
945
|
+
*Jean Boussier*
|
1024
946
|
|
1025
|
-
|
947
|
+
* `ActiveRecord::Base.logger` is now a `class_attribute`.
|
1026
948
|
|
1027
|
-
|
949
|
+
This means it can no longer be accessed directly through `@@logger`, and that setting `logger =`
|
950
|
+
on a subclass won't change the parent's logger.
|
1028
951
|
|
1029
|
-
*
|
952
|
+
*Jean Boussier*
|
1030
953
|
|
1031
|
-
|
1032
|
-
index won't be added.
|
954
|
+
* Add `.asc.nulls_first` for all databases. Unfortunately MySQL still doesn't like `nulls_last`.
|
1033
955
|
|
1034
|
-
|
956
|
+
*Keenan Brock*
|
1035
957
|
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
958
|
+
* Improve performance of `one?` and `many?` by limiting the generated count query to 2 results.
|
959
|
+
|
960
|
+
*Gonzalo Riestra*
|
961
|
+
|
962
|
+
* Don't check type when using `if_not_exists` on `add_column`.
|
963
|
+
|
964
|
+
Previously, if a migration called `add_column` with the `if_not_exists` option set to true
|
965
|
+
the `column_exists?` check would look for a column with the same name and type as the migration.
|
966
|
+
|
967
|
+
Recently it was discovered that the type passed to the migration is not always the same type
|
968
|
+
as the column after migration. For example a column set to `:mediumblob` in the migration will
|
969
|
+
be casted to `binary` when calling `column.type`. Since there is no straightforward way to cast
|
970
|
+
the type to the database type without running the migration, we opted to drop the type check from
|
971
|
+
`add_column`. This means that migrations adding a duplicate column with a different type will no
|
972
|
+
longer raise an error.
|
1039
973
|
|
1040
|
-
|
1041
|
-
created within that migration so that if table and its indexes exist then there is no
|
1042
|
-
attempt to create them again.
|
974
|
+
*Eileen M. Uchitelle*
|
1043
975
|
|
1044
|
-
|
976
|
+
* Log a warning message when running SQLite in production.
|
1045
977
|
|
1046
|
-
|
978
|
+
Using SQLite in production ENV is generally discouraged. SQLite is also the default adapter
|
979
|
+
in a new Rails application.
|
980
|
+
For the above reasons log a warning message when running SQLite in production.
|
1047
981
|
|
1048
|
-
|
982
|
+
The warning can be disabled by setting `config.active_record.sqlite3_production_warning=false`.
|
1049
983
|
|
1050
|
-
*
|
984
|
+
*Jacopo Beschi*
|
1051
985
|
|
1052
|
-
|
986
|
+
* Add option to disable joins for `has_one` associations.
|
1053
987
|
|
1054
|
-
|
988
|
+
In a multiple database application, associations can't join across
|
989
|
+
databases. When set, this option instructs Rails to generate 2 or
|
990
|
+
more queries rather than generating joins for `has_one` associations.
|
1055
991
|
|
1056
|
-
|
992
|
+
Set the option on a has one through association:
|
1057
993
|
|
1058
994
|
```ruby
|
1059
|
-
Person
|
1060
|
-
|
995
|
+
class Person
|
996
|
+
has_one :dog
|
997
|
+
has_one :veterinarian, through: :dog, disable_joins: true
|
1061
998
|
end
|
1062
999
|
```
|
1063
1000
|
|
1064
|
-
|
1001
|
+
Then instead of generating join SQL, two queries are used for `@person.veterinarian`:
|
1065
1002
|
|
1066
|
-
|
1003
|
+
```
|
1004
|
+
SELECT "dogs"."id" FROM "dogs" WHERE "dogs"."person_id" = ? [["person_id", 1]]
|
1005
|
+
SELECT "veterinarians".* FROM "veterinarians" WHERE "veterinarians"."dog_id" = ? [["dog_id", 1]]
|
1006
|
+
```
|
1067
1007
|
|
1068
|
-
|
1008
|
+
*Sarah Vessels*, *Eileen M. Uchitelle*
|
1069
1009
|
|
1070
|
-
|
1010
|
+
* `Arel::Visitors::Dot` now renders a complete set of properties when visiting
|
1011
|
+
`Arel::Nodes::SelectCore`, `SelectStatement`, `InsertStatement`, `UpdateStatement`, and
|
1012
|
+
`DeleteStatement`, which fixes #42026. Previously, some properties were omitted.
|
1071
1013
|
|
1072
|
-
*
|
1014
|
+
*Mike Dalessio*
|
1073
1015
|
|
1074
|
-
|
1016
|
+
* `Arel::Visitors::Dot` now supports `Arel::Nodes::Bin`, `Case`, `CurrentRow`, `Distinct`,
|
1017
|
+
`DistinctOn`, `Else`, `Except`, `InfixOperation`, `Intersect`, `Lock`, `NotRegexp`, `Quoted`,
|
1018
|
+
`Regexp`, `UnaryOperation`, `Union`, `UnionAll`, `When`, and `With`. Previously, these node
|
1019
|
+
types caused an exception to be raised by `Arel::Visitors::Dot#accept`.
|
1075
1020
|
|
1076
|
-
*
|
1021
|
+
*Mike Dalessio*
|
1077
1022
|
|
1078
|
-
* `
|
1023
|
+
* Optimize `remove_columns` to use a single SQL statement.
|
1079
1024
|
|
1080
|
-
|
1025
|
+
```ruby
|
1026
|
+
remove_columns :my_table, :col_one, :col_two
|
1027
|
+
```
|
1081
1028
|
|
1082
|
-
|
1029
|
+
Now results in the following SQL:
|
1083
1030
|
|
1084
|
-
|
1031
|
+
```sql
|
1032
|
+
ALTER TABLE "my_table" DROP COLUMN "col_one", DROP COLUMN "col_two"
|
1033
|
+
```
|
1085
1034
|
|
1086
|
-
*
|
1035
|
+
*Jon Dufresne*
|
1087
1036
|
|
1088
|
-
|
1037
|
+
* Ensure `has_one` autosave association callbacks get called once.
|
1089
1038
|
|
1090
|
-
|
1039
|
+
Change the `has_one` autosave callback to be non cyclic as well.
|
1040
|
+
By doing this the autosave callback are made more consistent for
|
1041
|
+
all 3 cases: `has_many`, `has_one`, and `belongs_to`.
|
1091
1042
|
|
1092
|
-
*
|
1043
|
+
*Petrik de Heus*
|
1093
1044
|
|
1094
|
-
*
|
1045
|
+
* Add option to disable joins for associations.
|
1095
1046
|
|
1096
|
-
|
1047
|
+
In a multiple database application, associations can't join across
|
1048
|
+
databases. When set, this option instructs Rails to generate 2 or
|
1049
|
+
more queries rather than generating joins for associations.
|
1097
1050
|
|
1098
|
-
|
1051
|
+
Set the option on a has many through association:
|
1099
1052
|
|
1100
|
-
|
1053
|
+
```ruby
|
1054
|
+
class Dog
|
1055
|
+
has_many :treats, through: :humans, disable_joins: true
|
1056
|
+
has_many :humans
|
1057
|
+
end
|
1058
|
+
```
|
1101
1059
|
|
1102
|
-
|
1060
|
+
Then instead of generating join SQL, two queries are used for `@dog.treats`:
|
1103
1061
|
|
1104
|
-
|
1062
|
+
```
|
1063
|
+
SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ? [["dog_id", 1]]
|
1064
|
+
SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?) [["human_id", 1], ["human_id", 2], ["human_id", 3]]
|
1065
|
+
```
|
1105
1066
|
|
1106
|
-
*
|
1067
|
+
*Eileen M. Uchitelle*, *Aaron Patterson*, *Lee Quarella*
|
1107
1068
|
|
1108
|
-
|
1069
|
+
* Add setting for enumerating column names in SELECT statements.
|
1109
1070
|
|
1110
|
-
|
1071
|
+
Adding a column to a PostgreSQL database, for example, while the application is running can
|
1072
|
+
change the result of wildcard `SELECT *` queries, which invalidates the result
|
1073
|
+
of cached prepared statements and raises a `PreparedStatementCacheExpired` error.
|
1111
1074
|
|
1112
|
-
|
1075
|
+
When enabled, Active Record will avoid wildcards and always include column names
|
1076
|
+
in `SELECT` queries, which will return consistent results and avoid prepared
|
1077
|
+
statement errors.
|
1113
1078
|
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
primary_shard_one:
|
1120
|
-
database: my_database_shard_one
|
1079
|
+
Before:
|
1080
|
+
|
1081
|
+
```ruby
|
1082
|
+
Book.limit(5)
|
1083
|
+
# SELECT * FROM books LIMIT 5
|
1121
1084
|
```
|
1122
1085
|
|
1123
|
-
|
1086
|
+
After:
|
1124
1087
|
|
1125
1088
|
```ruby
|
1126
|
-
|
1127
|
-
|
1089
|
+
# config/application.rb
|
1090
|
+
module MyApp
|
1091
|
+
class Application < Rails::Application
|
1092
|
+
config.active_record.enumerate_columns_in_select_statements = true
|
1093
|
+
end
|
1094
|
+
end
|
1128
1095
|
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1096
|
+
# or, configure per-model
|
1097
|
+
class Book < ApplicationRecord
|
1098
|
+
self.enumerate_columns_in_select_statements = true
|
1099
|
+
end
|
1133
1100
|
```
|
1134
1101
|
|
1135
|
-
Swap between shards in your controller / model code:
|
1136
|
-
|
1137
1102
|
```ruby
|
1138
|
-
|
1139
|
-
|
1140
|
-
end
|
1103
|
+
Book.limit(5)
|
1104
|
+
# SELECT id, author_id, name, format, status, language, etc FROM books LIMIT 5
|
1141
1105
|
```
|
1142
1106
|
|
1143
|
-
|
1107
|
+
*Matt Duszynski*
|
1144
1108
|
|
1145
|
-
|
1109
|
+
* Allow passing SQL as `on_duplicate` value to `#upsert_all` to make it possible to use raw SQL to update columns on conflict:
|
1146
1110
|
|
1147
|
-
|
1111
|
+
```ruby
|
1112
|
+
Book.upsert_all(
|
1113
|
+
[{ id: 1, status: 1 }, { id: 2, status: 1 }],
|
1114
|
+
on_duplicate: Arel.sql("status = GREATEST(books.status, EXCLUDED.status)")
|
1115
|
+
)
|
1116
|
+
```
|
1148
1117
|
|
1149
|
-
|
1118
|
+
*Vladimir Dementyev*
|
1150
1119
|
|
1151
|
-
|
1120
|
+
* Allow passing SQL as `returning` statement to `#upsert_all`:
|
1152
1121
|
|
1153
1122
|
```ruby
|
1154
|
-
|
1155
|
-
|
1123
|
+
Article.insert_all(
|
1124
|
+
[
|
1125
|
+
{ title: "Article 1", slug: "article-1", published: false },
|
1126
|
+
{ title: "Article 2", slug: "article-2", published: false }
|
1127
|
+
],
|
1128
|
+
returning: Arel.sql("id, (xmax = '0') as inserted, name as new_name")
|
1129
|
+
)
|
1156
1130
|
```
|
1157
1131
|
|
1158
|
-
|
1132
|
+
*Vladimir Dementyev*
|
1159
1133
|
|
1160
|
-
|
1161
|
-
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "development", name: "primary")
|
1162
|
-
db_config.name
|
1163
|
-
```
|
1134
|
+
* Deprecate `legacy_connection_handling`.
|
1164
1135
|
|
1165
1136
|
*Eileen M. Uchitelle*
|
1166
1137
|
|
1167
|
-
* Add
|
1138
|
+
* Add attribute encryption support.
|
1168
1139
|
|
1169
|
-
|
1170
|
-
|
1140
|
+
Encrypted attributes are declared at the model level. These
|
1141
|
+
are regular Active Record attributes backed by a column with
|
1142
|
+
the same name. The system will transparently encrypt these
|
1143
|
+
attributes before saving them into the database and will
|
1144
|
+
decrypt them when retrieving their values.
|
1171
1145
|
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
rails db:drop:animals
|
1179
|
-
rails db:migrate
|
1180
|
-
rails db:migrate:primary
|
1181
|
-
rails db:migrate:animals
|
1146
|
+
|
1147
|
+
```ruby
|
1148
|
+
class Person < ApplicationRecord
|
1149
|
+
encrypts :name
|
1150
|
+
encrypts :email_address, deterministic: true
|
1151
|
+
end
|
1182
1152
|
```
|
1183
1153
|
|
1184
|
-
|
1185
|
-
|
1154
|
+
You can learn more in the [Active Record Encryption
|
1155
|
+
guide](https://edgeguides.rubyonrails.org/active_record_encryption.html).
|
1186
1156
|
|
1187
|
-
|
1188
|
-
rails db:schema:dump
|
1189
|
-
rails db:schema:dump:primary
|
1190
|
-
rails db:schema:dump:animals
|
1191
|
-
rails db:schema:load
|
1192
|
-
rails db:schema:load:primary
|
1193
|
-
rails db:schema:load:animals
|
1194
|
-
rails db:structure:dump
|
1195
|
-
rails db:structure:dump:primary
|
1196
|
-
rails db:structure:dump:animals
|
1197
|
-
rails db:structure:load
|
1198
|
-
rails db:structure:load:primary
|
1199
|
-
rails db:structure:load:animals
|
1200
|
-
rails db:test:prepare
|
1201
|
-
rails db:test:prepare:primary
|
1202
|
-
rails db:test:prepare:animals
|
1203
|
-
```
|
1157
|
+
*Jorge Manrubia*
|
1204
1158
|
|
1205
|
-
|
1159
|
+
* Changed Arel predications `contains` and `overlaps` to use
|
1160
|
+
`quoted_node` so that PostgreSQL arrays are quoted properly.
|
1206
1161
|
|
1207
|
-
*
|
1162
|
+
*Bradley Priest*
|
1208
1163
|
|
1209
|
-
|
1164
|
+
* Add mode argument to record level `strict_loading!`.
|
1210
1165
|
|
1211
|
-
|
1166
|
+
This argument can be used when enabling strict loading for a single record
|
1167
|
+
to specify that we only want to raise on n plus one queries.
|
1212
1168
|
|
1213
1169
|
```ruby
|
1214
|
-
|
1215
|
-
has_many :projects, strict_loading: true
|
1216
|
-
end
|
1170
|
+
developer.strict_loading!(mode: :n_plus_one_only)
|
1217
1171
|
|
1218
|
-
|
1219
|
-
|
1220
|
-
# => ActiveRecord::StrictLoadingViolationError: The projects association is marked as strict_loading and cannot be lazily loaded.
|
1172
|
+
developer.projects.to_a # Does not raise
|
1173
|
+
developer.projects.first.client # Raises StrictLoadingViolationError
|
1221
1174
|
```
|
1222
1175
|
|
1223
|
-
|
1176
|
+
Previously, enabling strict loading would cause any lazily loaded
|
1177
|
+
association to raise an error. Using `n_plus_one_only` mode allows us to
|
1178
|
+
lazily load belongs_to, has_many, and other associations that are fetched
|
1179
|
+
through a single query.
|
1224
1180
|
|
1225
|
-
*
|
1181
|
+
*Dinah Shi*
|
1226
1182
|
|
1227
|
-
|
1183
|
+
* Fix Float::INFINITY assignment to datetime column with postgresql adapter.
|
1228
1184
|
|
1229
|
-
|
1185
|
+
Before:
|
1230
1186
|
|
1231
1187
|
```ruby
|
1232
|
-
|
1233
|
-
|
1234
|
-
# => ActiveRecord::StrictLoadingViolationError: Developer is marked as strict_loading and AuditLog cannot be lazily loaded.
|
1235
|
-
```
|
1188
|
+
# With this config
|
1189
|
+
ActiveRecord::Base.time_zone_aware_attributes = true
|
1236
1190
|
|
1237
|
-
|
1191
|
+
# and the following schema:
|
1192
|
+
create_table "postgresql_infinities" do |t|
|
1193
|
+
t.datetime "datetime"
|
1194
|
+
end
|
1238
1195
|
|
1239
|
-
|
1196
|
+
# This test fails
|
1197
|
+
record = PostgresqlInfinity.create!(datetime: Float::INFINITY)
|
1198
|
+
assert_equal Float::INFINITY, record.datetime # record.datetime gets nil
|
1199
|
+
```
|
1240
1200
|
|
1241
|
-
|
1201
|
+
After this commit, `record.datetime` gets `Float::INFINITY` as expected.
|
1242
1202
|
|
1243
|
-
*
|
1203
|
+
*Shunichi Ikegami*
|
1244
1204
|
|
1245
|
-
|
1205
|
+
* Type cast enum values by the original attribute type.
|
1246
1206
|
|
1247
|
-
|
1207
|
+
The notable thing about this change is that unknown labels will no longer match 0 on MySQL.
|
1248
1208
|
|
1249
1209
|
```ruby
|
1250
|
-
class
|
1251
|
-
|
1252
|
-
add_column :posts, :title, :string, if_not_exists: true
|
1253
|
-
end
|
1210
|
+
class Book < ActiveRecord::Base
|
1211
|
+
enum :status, { proposed: 0, written: 1, published: 2 }
|
1254
1212
|
end
|
1255
1213
|
```
|
1256
1214
|
|
1215
|
+
Before:
|
1216
|
+
|
1257
1217
|
```ruby
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1218
|
+
# SELECT `books`.* FROM `books` WHERE `books`.`status` = 'prohibited' LIMIT 1
|
1219
|
+
Book.find_by(status: :prohibited)
|
1220
|
+
# => #<Book id: 1, status: "proposed", ...> (for mysql2 adapter)
|
1221
|
+
# => ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for type integer: "prohibited" (for postgresql adapter)
|
1222
|
+
# => nil (for sqlite3 adapter)
|
1263
1223
|
```
|
1264
1224
|
|
1265
|
-
|
1266
|
-
|
1267
|
-
* Regexp-escape table name for MS SQL Server.
|
1268
|
-
|
1269
|
-
Add `Regexp.escape` to one method in ActiveRecord, so that table names with regular expression characters in them work as expected. Since MS SQL Server uses "[" and "]" to quote table and column names, and those characters are regular expression characters, methods like `pluck` and `select` fail in certain cases when used with the MS SQL Server adapter.
|
1270
|
-
|
1271
|
-
*Larry Reid*
|
1272
|
-
|
1273
|
-
* Store advisory locks on their own named connection.
|
1225
|
+
After:
|
1274
1226
|
|
1275
|
-
|
1227
|
+
```ruby
|
1228
|
+
# SELECT `books`.* FROM `books` WHERE `books`.`status` IS NULL LIMIT 1
|
1229
|
+
Book.find_by(status: :prohibited)
|
1230
|
+
# => nil (for all adapters)
|
1231
|
+
```
|
1276
1232
|
|
1277
|
-
|
1233
|
+
*Ryuta Kamizono*
|
1278
1234
|
|
1279
|
-
|
1235
|
+
* Fixtures for `has_many :through` associations now load timestamps on join tables.
|
1280
1236
|
|
1281
|
-
|
1237
|
+
Given this fixture:
|
1282
1238
|
|
1283
|
-
|
1239
|
+
```yml
|
1240
|
+
### monkeys.yml
|
1241
|
+
george:
|
1242
|
+
name: George the Monkey
|
1243
|
+
fruits: apple
|
1284
1244
|
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
database: blog_development
|
1289
|
-
pool: 5
|
1290
|
-
schema_cache_path: tmp/schema/main.yml
|
1245
|
+
### fruits.yml
|
1246
|
+
apple:
|
1247
|
+
name: apple
|
1291
1248
|
```
|
1292
1249
|
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1250
|
+
If the join table (`fruit_monkeys`) contains `created_at` or `updated_at` columns,
|
1251
|
+
these will now be populated when loading the fixture. Previously, fixture loading
|
1252
|
+
would crash if these columns were required, and leave them as null otherwise.
|
1296
1253
|
|
1297
|
-
|
1298
|
-
|
1299
|
-
*Eileen M. Uchitelle*, *John Crepezzi*
|
1300
|
-
|
1301
|
-
* Deprecate `#default_hash` and it's alias `#[]` on database configurations.
|
1254
|
+
*Alex Ghiculescu*
|
1302
1255
|
|
1303
|
-
|
1256
|
+
* Allow applications to configure the thread pool for async queries.
|
1304
1257
|
|
1305
|
-
|
1258
|
+
Some applications may want one thread pool per database whereas others want to use
|
1259
|
+
a single global thread pool for all queries. By default, Rails will set `async_query_executor`
|
1260
|
+
to `nil` which will not initialize any executor. If `load_async` is called and no executor
|
1261
|
+
has been configured, the query will be executed in the foreground.
|
1306
1262
|
|
1307
|
-
|
1263
|
+
To create one thread pool for all database connections to use applications can set
|
1264
|
+
`config.active_record.async_query_executor` to `:global_thread_pool` and optionally define
|
1265
|
+
`config.active_record.global_executor_concurrency`. This defaults to 4. For applications that want
|
1266
|
+
to have a thread pool for each database connection, `config.active_record.async_query_executor` can
|
1267
|
+
be set to `:multi_thread_pool`. The configuration for each thread pool is set in the database
|
1268
|
+
configuration.
|
1308
1269
|
|
1309
|
-
*
|
1270
|
+
*Eileen M. Uchitelle*
|
1310
1271
|
|
1311
|
-
*
|
1272
|
+
* Allow new syntax for `enum` to avoid leading `_` from reserved options.
|
1312
1273
|
|
1313
1274
|
Before:
|
1314
1275
|
|
1315
1276
|
```ruby
|
1316
|
-
|
1277
|
+
class Book < ActiveRecord::Base
|
1278
|
+
enum status: [ :proposed, :written ], _prefix: true, _scopes: false
|
1279
|
+
enum cover: [ :hard, :soft ], _suffix: true, _default: :hard
|
1280
|
+
end
|
1317
1281
|
```
|
1318
1282
|
|
1319
1283
|
After:
|
1320
1284
|
|
1321
1285
|
```ruby
|
1322
|
-
|
1286
|
+
class Book < ActiveRecord::Base
|
1287
|
+
enum :status, [ :proposed, :written ], prefix: true, scopes: false
|
1288
|
+
enum :cover, [ :hard, :soft ], suffix: true, default: :hard
|
1289
|
+
end
|
1323
1290
|
```
|
1324
1291
|
|
1325
|
-
*
|
1326
|
-
|
1327
|
-
* Ensure `:reading` connections always raise if a write is attempted.
|
1328
|
-
|
1329
|
-
Now Rails will raise an `ActiveRecord::ReadOnlyError` if any connection on the reading handler attempts to make a write. If your reading role needs to write you should name the role something other than `:reading`.
|
1330
|
-
|
1331
|
-
*Eileen M. Uchitelle*
|
1332
|
-
|
1333
|
-
* Deprecate `"primary"` as the `connection_specification_name` for `ActiveRecord::Base`.
|
1334
|
-
|
1335
|
-
`"primary"` has been deprecated as the `connection_specification_name` for `ActiveRecord::Base` in favor of using `"ActiveRecord::Base"`. This change affects calls to `ActiveRecord::Base.connection_handler.retrieve_connection` and `ActiveRecord::Base.connection_handler.remove_connection`. If you're calling these methods with `"primary"`, please switch to `"ActiveRecord::Base"`.
|
1292
|
+
*Ryuta Kamizono*
|
1336
1293
|
|
1337
|
-
|
1294
|
+
* Add `ActiveRecord::Relation#load_async`.
|
1338
1295
|
|
1339
|
-
|
1340
|
-
support for casting floats using a database columns' precision value.
|
1296
|
+
This method schedules the query to be performed asynchronously from a thread pool.
|
1341
1297
|
|
1342
|
-
|
1298
|
+
If the result is accessed before a background thread had the opportunity to perform
|
1299
|
+
the query, it will be performed in the foreground.
|
1343
1300
|
|
1344
|
-
|
1345
|
-
|
1346
|
-
ActionController::ConditionalGet to ensure that when collection cache versioning
|
1347
|
-
is enabled, requests using ConditionalGet don't return the same ETag header
|
1348
|
-
after a collection is modified.
|
1301
|
+
This is useful for queries that can be performed long enough before their result will be
|
1302
|
+
needed, or for controllers which need to perform several independent queries.
|
1349
1303
|
|
1350
|
-
|
1304
|
+
```ruby
|
1305
|
+
def index
|
1306
|
+
@categories = Category.some_complex_scope.load_async
|
1307
|
+
@posts = Post.some_complex_scope.load_async
|
1308
|
+
end
|
1309
|
+
```
|
1351
1310
|
|
1352
|
-
|
1311
|
+
Active Record logs will also include timing info for the duration of how long
|
1312
|
+
the main thread had to wait to access the result. This timing is useful to know
|
1313
|
+
whether or not it's worth to load the query asynchronously.
|
1353
1314
|
|
1354
|
-
|
1355
|
-
|
1315
|
+
```
|
1316
|
+
DEBUG -- : Category Load (62.1ms) SELECT * FROM `categories` LIMIT 50
|
1317
|
+
DEBUG -- : ASYNC Post Load (64ms) (db time 126.1ms) SELECT * FROM `posts` LIMIT 100
|
1318
|
+
```
|
1356
1319
|
|
1357
|
-
|
1320
|
+
The duration in the first set of parens is how long the main thread was blocked
|
1321
|
+
waiting for the results, and the second set of parens with "db time" is how long
|
1322
|
+
the entire query took to execute.
|
1358
1323
|
|
1359
|
-
*
|
1324
|
+
*Jean Boussier*
|
1360
1325
|
|
1361
|
-
|
1326
|
+
* Implemented `ActiveRecord::Relation#excluding` method.
|
1362
1327
|
|
1363
|
-
|
1328
|
+
This method excludes the specified record (or collection of records) from
|
1329
|
+
the resulting relation:
|
1364
1330
|
|
1365
1331
|
```ruby
|
1366
|
-
|
1367
|
-
|
1332
|
+
Post.excluding(post)
|
1333
|
+
Post.excluding(post_one, post_two)
|
1368
1334
|
```
|
1369
1335
|
|
1370
|
-
|
1336
|
+
Also works on associations:
|
1371
1337
|
|
1372
1338
|
```ruby
|
1373
|
-
|
1374
|
-
|
1375
|
-
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(@db_config.env_name, @db_config.spec_name, config)
|
1339
|
+
post.comments.excluding(comment)
|
1340
|
+
post.comments.excluding(comment_one, comment_two)
|
1376
1341
|
```
|
1377
1342
|
|
1378
|
-
|
1379
|
-
|
1380
|
-
* Remove `:connection_id` from the `sql.active_record` notification.
|
1343
|
+
This is short-hand for `Post.where.not(id: post.id)` (for a single record)
|
1344
|
+
and `Post.where.not(id: [post_one.id, post_two.id])` (for a collection).
|
1381
1345
|
|
1382
|
-
*
|
1346
|
+
*Glen Crawford*
|
1383
1347
|
|
1384
|
-
*
|
1348
|
+
* Skip optimised #exist? query when #include? is called on a relation
|
1349
|
+
with a having clause.
|
1385
1350
|
|
1386
|
-
|
1351
|
+
Relations that have aliased select values AND a having clause that
|
1352
|
+
references an aliased select value would generate an error when
|
1353
|
+
#include? was called, due to an optimisation that would generate
|
1354
|
+
call #exists? on the relation instead, which effectively alters
|
1355
|
+
the select values of the query (and thus removes the aliased select
|
1356
|
+
values), but leaves the having clause intact. Because the having
|
1357
|
+
clause is then referencing an aliased column that is no longer
|
1358
|
+
present in the simplified query, an ActiveRecord::InvalidStatement
|
1359
|
+
error was raised.
|
1387
1360
|
|
1388
|
-
|
1361
|
+
A sample query affected by this problem:
|
1389
1362
|
|
1390
|
-
|
1391
|
-
|
1363
|
+
```ruby
|
1364
|
+
Author.select('COUNT(*) as total_posts', 'authors.*')
|
1365
|
+
.joins(:posts)
|
1366
|
+
.group(:id)
|
1367
|
+
.having('total_posts > 2')
|
1368
|
+
.include?(Author.first)
|
1369
|
+
```
|
1392
1370
|
|
1393
|
-
This change
|
1394
|
-
|
1371
|
+
This change adds an addition check to the condition that skips the
|
1372
|
+
simplified #exists? query, which simply checks for the presence of
|
1373
|
+
a having clause.
|
1395
1374
|
|
1396
|
-
|
1375
|
+
Fixes #41417.
|
1397
1376
|
|
1398
|
-
*
|
1377
|
+
*Michael Smart*
|
1399
1378
|
|
1400
|
-
|
1379
|
+
* Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
|
1380
|
+
without Rails knowledge (e.g., if app gets killed during long-running query or due to Rack::Timeout), app won't end
|
1381
|
+
up in perpetual crash state for being inconsistent with PostgreSQL.
|
1401
1382
|
|
1402
|
-
*
|
1383
|
+
*wbharding*, *Martin Tepper*
|
1403
1384
|
|
1404
|
-
|
1385
|
+
* Add ability to apply `scoping` to `all_queries`.
|
1405
1386
|
|
1406
|
-
|
1387
|
+
Some applications may want to use the `scoping` method but previously it only
|
1388
|
+
worked on certain types of queries. This change allows the `scoping` method to apply
|
1389
|
+
to all queries for a model in a block.
|
1407
1390
|
|
1408
|
-
|
1391
|
+
```ruby
|
1392
|
+
Post.where(blog_id: post.blog_id).scoping(all_queries: true) do
|
1393
|
+
post.update(title: "a post title") # adds `posts.blog_id = 1` to the query
|
1394
|
+
end
|
1395
|
+
```
|
1409
1396
|
|
1410
|
-
*Eileen M. Uchitelle
|
1397
|
+
*Eileen M. Uchitelle*
|
1411
1398
|
|
1412
|
-
*
|
1399
|
+
* `ActiveRecord::Calculations.calculate` called with `:average`
|
1400
|
+
(aliased as `ActiveRecord::Calculations.average`) will now use column-based
|
1401
|
+
type casting. This means that floating-point number columns will now be
|
1402
|
+
aggregated as `Float` and decimal columns will be aggregated as `BigDecimal`.
|
1413
1403
|
|
1414
|
-
|
1404
|
+
Integers are handled as a special case returning `BigDecimal` always
|
1405
|
+
(this was the case before already).
|
1415
1406
|
|
1416
|
-
|
1407
|
+
```ruby
|
1408
|
+
# With the following schema:
|
1409
|
+
create_table "measurements" do |t|
|
1410
|
+
t.float "temperature"
|
1411
|
+
end
|
1417
1412
|
|
1418
|
-
|
1413
|
+
# Before:
|
1414
|
+
Measurement.average(:temperature).class
|
1415
|
+
# => BigDecimal
|
1419
1416
|
|
1420
|
-
|
1417
|
+
# After:
|
1418
|
+
Measurement.average(:temperature).class
|
1419
|
+
# => Float
|
1420
|
+
```
|
1421
1421
|
|
1422
|
-
|
1422
|
+
Before this change, Rails just called `to_d` on average aggregates from the
|
1423
|
+
database adapter. This is not the case anymore. If you relied on that kind
|
1424
|
+
of magic, you now need to register your own `ActiveRecord::Type`
|
1425
|
+
(see `ActiveRecord::Attributes::ClassMethods` for documentation).
|
1423
1426
|
|
1424
|
-
*
|
1427
|
+
*Josua Schmid*
|
1425
1428
|
|
1426
|
-
|
1429
|
+
* PostgreSQL: introduce `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type`.
|
1427
1430
|
|
1428
|
-
|
1431
|
+
This setting controls what native type Active Record should use when you call `datetime` in
|
1432
|
+
a migration or schema. It takes a symbol which must correspond to one of the configured
|
1433
|
+
`NATIVE_DATABASE_TYPES`. The default is `:timestamp`, meaning `t.datetime` in a migration
|
1434
|
+
will create a "timestamp without time zone" column. To use "timestamp with time zone",
|
1435
|
+
change this to `:timestamptz` in an initializer.
|
1429
1436
|
|
1430
|
-
|
1437
|
+
You should run `bin/rails db:migrate` to rebuild your schema.rb if you change this.
|
1431
1438
|
|
1432
|
-
*
|
1439
|
+
*Alex Ghiculescu*
|
1433
1440
|
|
1434
|
-
|
1441
|
+
* PostgreSQL: handle `timestamp with time zone` columns correctly in `schema.rb`.
|
1435
1442
|
|
1436
|
-
|
1443
|
+
Previously they dumped as `t.datetime :column_name`, now they dump as `t.timestamptz :column_name`,
|
1444
|
+
and are created as `timestamptz` columns when the schema is loaded.
|
1437
1445
|
|
1438
|
-
*
|
1446
|
+
*Alex Ghiculescu*
|
1439
1447
|
|
1440
|
-
*
|
1441
|
-
|
1448
|
+
* Removing trailing whitespace when matching columns in
|
1449
|
+
`ActiveRecord::Sanitization.disallow_raw_sql!`.
|
1442
1450
|
|
1443
|
-
|
1451
|
+
*Gannon McGibbon*, *Adrian Hirt*
|
1444
1452
|
|
1445
|
-
|
1446
|
-
has_secure_token :auth_token
|
1447
|
-
```
|
1453
|
+
* Expose a way for applications to set a `primary_abstract_class`.
|
1448
1454
|
|
1449
|
-
|
1455
|
+
Multiple database applications that use a primary abstract class that is not
|
1456
|
+
named `ApplicationRecord` can now set a specific class to be the `primary_abstract_class`.
|
1450
1457
|
|
1451
1458
|
```ruby
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1459
|
+
class PrimaryApplicationRecord
|
1460
|
+
self.primary_abstract_class
|
1461
|
+
end
|
1455
1462
|
```
|
1456
1463
|
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1464
|
+
When an application boots it automatically connects to the primary or first database in the
|
1465
|
+
database configuration file. In a multiple database application that then call `connects_to`
|
1466
|
+
needs to know that the default connection is the same as the `ApplicationRecord` connection.
|
1467
|
+
However, some applications have a differently named `ApplicationRecord`. This prevents Active
|
1468
|
+
Record from opening duplicate connections to the same database.
|
1460
1469
|
|
1461
|
-
*Eileen Uchitelle*, *John Crepezzi*
|
1470
|
+
*Eileen M. Uchitelle*, *John Crepezzi*
|
1462
1471
|
|
1463
|
-
*
|
1472
|
+
* Support hash config for `structure_dump_flags` and `structure_load_flags` flags.
|
1473
|
+
Now that Active Record supports multiple databases configuration,
|
1474
|
+
we need a way to pass specific flags for dump/load databases since
|
1475
|
+
the options are not the same for different adapters.
|
1476
|
+
We can use in the original way:
|
1464
1477
|
|
1465
|
-
|
1478
|
+
```ruby
|
1479
|
+
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-defaults', '--skip-add-drop-table']
|
1480
|
+
# or
|
1481
|
+
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = '--no-defaults --skip-add-drop-table'
|
1482
|
+
```
|
1466
1483
|
|
1467
|
-
|
1484
|
+
And also use it passing a hash, with one or more keys, where the key
|
1485
|
+
is the adapter
|
1468
1486
|
|
1469
|
-
|
1487
|
+
```ruby
|
1488
|
+
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
|
1489
|
+
mysql2: ['--no-defaults', '--skip-add-drop-table'],
|
1490
|
+
postgres: '--no-tablespaces'
|
1491
|
+
}
|
1492
|
+
```
|
1470
1493
|
|
1471
|
-
|
1494
|
+
*Gustavo Gonzalez*
|
1472
1495
|
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1496
|
+
* Connection specification now passes the "url" key as a configuration for the
|
1497
|
+
adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
|
1498
|
+
urls with the "jdbc" prefix were passed to the Active Record Adapter, others
|
1499
|
+
are assumed to be adapter specification urls.
|
1477
1500
|
|
1478
|
-
|
1501
|
+
Fixes #41137.
|
1479
1502
|
|
1480
|
-
|
1503
|
+
*Jonathan Bracy*
|
1481
1504
|
|
1482
|
-
|
1505
|
+
* Allow to opt-out of `strict_loading` mode on a per-record base.
|
1483
1506
|
|
1484
|
-
|
1507
|
+
This is useful when strict loading is enabled application wide or on a
|
1508
|
+
model level.
|
1485
1509
|
|
1486
|
-
|
1510
|
+
```ruby
|
1511
|
+
class User < ApplicationRecord
|
1512
|
+
has_many :bookmarks
|
1513
|
+
has_many :articles, strict_loading: true
|
1514
|
+
end
|
1487
1515
|
|
1488
|
-
|
1516
|
+
user = User.first
|
1517
|
+
user.articles # => ActiveRecord::StrictLoadingViolationError
|
1518
|
+
user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy>
|
1489
1519
|
|
1490
|
-
|
1520
|
+
user.strict_loading!(true) # => true
|
1521
|
+
user.bookmarks # => ActiveRecord::StrictLoadingViolationError
|
1491
1522
|
|
1492
|
-
|
1523
|
+
user.strict_loading!(false) # => false
|
1524
|
+
user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy>
|
1525
|
+
user.articles.strict_loading!(false) # => #<ActiveRecord::Associations::CollectionProxy>
|
1526
|
+
```
|
1493
1527
|
|
1494
|
-
|
1528
|
+
*Ayrton De Craene*
|
1495
1529
|
|
1496
|
-
|
1530
|
+
* Add `FinderMethods#sole` and `#find_sole_by` to find and assert the
|
1531
|
+
presence of exactly one record.
|
1497
1532
|
|
1498
|
-
|
1533
|
+
Used when you need a single row, but also want to assert that there aren't
|
1534
|
+
multiple rows matching the condition; especially for when database
|
1535
|
+
constraints aren't enough or are impractical.
|
1499
1536
|
|
1500
|
-
|
1537
|
+
```ruby
|
1538
|
+
Product.where(["price = %?", price]).sole
|
1539
|
+
# => ActiveRecord::RecordNotFound (if no Product with given price)
|
1540
|
+
# => #<Product ...> (if one Product with given price)
|
1541
|
+
# => ActiveRecord::SoleRecordExceeded (if more than one Product with given price)
|
1501
1542
|
|
1502
|
-
|
1543
|
+
user.api_keys.find_sole_by(key: key)
|
1544
|
+
# as above
|
1545
|
+
```
|
1503
1546
|
|
1504
|
-
*
|
1547
|
+
*Asherah Connor*
|
1505
1548
|
|
1506
|
-
|
1549
|
+
* Makes `ActiveRecord::AttributeMethods::Query` respect the getter overrides defined in the model.
|
1507
1550
|
|
1508
|
-
|
1551
|
+
Before:
|
1509
1552
|
|
1510
|
-
|
1553
|
+
```ruby
|
1554
|
+
class User
|
1555
|
+
def admin
|
1556
|
+
false # Overriding the getter to always return false
|
1557
|
+
end
|
1558
|
+
end
|
1511
1559
|
|
1512
|
-
|
1560
|
+
user = User.first
|
1561
|
+
user.update(admin: true)
|
1513
1562
|
|
1514
|
-
|
1563
|
+
user.admin # false (as expected, due to the getter overwrite)
|
1564
|
+
user.admin? # true (not expected, returned the DB column value)
|
1565
|
+
```
|
1515
1566
|
|
1516
|
-
|
1567
|
+
After this commit, `user.admin?` above returns false, as expected.
|
1517
1568
|
|
1518
|
-
|
1569
|
+
Fixes #40771.
|
1519
1570
|
|
1520
|
-
*
|
1571
|
+
*Felipe*
|
1521
1572
|
|
1522
|
-
|
1573
|
+
* Allow delegated_type to be specified primary_key and foreign_key.
|
1523
1574
|
|
1524
|
-
|
1575
|
+
Since delegated_type assumes that the foreign_key ends with `_id`,
|
1576
|
+
`singular_id` defined by it does not work when the foreign_key does
|
1577
|
+
not end with `id`. This change fixes it by taking into account
|
1578
|
+
`primary_key` and `foreign_key` in the options.
|
1525
1579
|
|
1526
|
-
*
|
1580
|
+
*Ryota Egusa*
|
1527
1581
|
|
1528
|
-
*
|
1582
|
+
* Expose an `invert_where` method that will invert all scope conditions.
|
1529
1583
|
|
1530
|
-
|
1584
|
+
```ruby
|
1585
|
+
class User
|
1586
|
+
scope :active, -> { where(accepted: true, locked: false) }
|
1587
|
+
end
|
1531
1588
|
|
1532
|
-
|
1589
|
+
User.active
|
1590
|
+
# ... WHERE `accepted` = 1 AND `locked` = 0
|
1533
1591
|
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1592
|
+
User.active.invert_where
|
1593
|
+
# ... WHERE NOT (`accepted` = 1 AND `locked` = 0)
|
1594
|
+
```
|
1537
1595
|
|
1538
|
-
*
|
1596
|
+
*Kevin Deisz*
|
1539
1597
|
|
1540
|
-
*
|
1598
|
+
* Restore possibility of passing `false` to :polymorphic option of `belongs_to`.
|
1541
1599
|
|
1542
|
-
|
1600
|
+
Previously, passing `false` would trigger the option validation logic
|
1601
|
+
to throw an error saying :polymorphic would not be a valid option.
|
1543
1602
|
|
1544
|
-
*
|
1603
|
+
*glaszig*
|
1545
1604
|
|
1546
|
-
|
1605
|
+
* Remove deprecated `database` kwarg from `connected_to`.
|
1547
1606
|
|
1548
|
-
*
|
1607
|
+
*Eileen M. Uchitelle*, *John Crepezzi*
|
1549
1608
|
|
1550
|
-
|
1609
|
+
* Allow adding nonnamed expression indexes to be revertible.
|
1551
1610
|
|
1552
|
-
|
1611
|
+
Previously, the following code would raise an error, when executed while rolling back,
|
1612
|
+
and the index name should be specified explicitly. Now, the index name is inferred
|
1613
|
+
automatically.
|
1553
1614
|
|
1554
|
-
|
1615
|
+
```ruby
|
1616
|
+
add_index(:items, "to_tsvector('english', description)")
|
1617
|
+
```
|
1555
1618
|
|
1556
|
-
|
1619
|
+
Fixes #40732.
|
1557
1620
|
|
1558
|
-
|
1621
|
+
*fatkodima*
|
1559
1622
|
|
1560
|
-
|
1623
|
+
* Only warn about negative enums if a positive form that would cause conflicts exists.
|
1561
1624
|
|
1562
|
-
|
1625
|
+
Fixes #39065.
|
1563
1626
|
|
1564
|
-
|
1627
|
+
*Alex Ghiculescu*
|
1565
1628
|
|
1566
|
-
|
1629
|
+
* Add option to run `default_scope` on all queries.
|
1567
1630
|
|
1568
|
-
|
1631
|
+
Previously, a `default_scope` would only run on select or insert queries. In some cases, like non-Rails tenant sharding solutions, it may be desirable to run `default_scope` on all queries in order to ensure queries are including a foreign key for the shard (i.e. `blog_id`).
|
1569
1632
|
|
1570
|
-
|
1633
|
+
Now applications can add an option to run on all queries including select, insert, delete, and update by adding an `all_queries` option to the default scope definition.
|
1571
1634
|
|
1572
|
-
|
1635
|
+
```ruby
|
1636
|
+
class Article < ApplicationRecord
|
1637
|
+
default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true
|
1638
|
+
end
|
1639
|
+
```
|
1573
1640
|
|
1574
|
-
*
|
1641
|
+
*Eileen M. Uchitelle*
|
1575
1642
|
|
1576
|
-
*
|
1643
|
+
* Add `where.associated` to check for the presence of an association.
|
1577
1644
|
|
1578
|
-
|
1645
|
+
```ruby
|
1646
|
+
# Before:
|
1647
|
+
account.users.joins(:contact).where.not(contact_id: nil)
|
1579
1648
|
|
1580
|
-
|
1649
|
+
# After:
|
1650
|
+
account.users.where.associated(:contact)
|
1651
|
+
```
|
1581
1652
|
|
1582
|
-
|
1653
|
+
Also mirrors `where.missing`.
|
1583
1654
|
|
1584
|
-
*
|
1655
|
+
*Kasper Timm Hansen*
|
1585
1656
|
|
1586
|
-
* Allow
|
1657
|
+
* Allow constructors (`build_association` and `create_association`) on
|
1658
|
+
`has_one :through` associations.
|
1587
1659
|
|
1588
|
-
*
|
1660
|
+
*Santiago Perez Perret*
|
1589
1661
|
|
1590
1662
|
|
1591
|
-
Please check [6-
|
1663
|
+
Please check [6-1-stable](https://github.com/rails/rails/blob/6-1-stable/activerecord/CHANGELOG.md) for previous changes.
|