rails--rails/activerecord/CHANGELOG.md

134 lines
3.9 KiB
Markdown
Raw Normal View History

* Add `FinderMethods#sole` and `#find_sole_by` to find and assert the
presence of exactly one record.
Used when you need a single row, but also want to assert that there aren't
multiple rows matching the condition; especially for when database
constraints aren't enough or are impractical.
```ruby
Product.where(["price = %?", price]).sole
# => ActiveRecord::RecordNotFound (if no Product with given price)
# => #<Product ...> (if one Product with given price)
# => ActiveRecord::SoleRecordExceeded (if more than one Product with given price)
2020-12-31 00:02:34 +00:00
user.api_keys.find_sole_by(key: key)
# as above
```
*Asherah Connor*
* Makes `ActiveRecord::AttributeMethods::Query` respect the getter overrides defined in the model.
Before:
```ruby
class User
def admin
false # Overriding the getter to always return false
end
end
user = User.first
user.update(admin: true)
user.admin # false (as expected, due to the getter overwrite)
user.admin? # true (not expected, returned the DB column value)
```
After this commit, `user.admin?` above returns false, as expected.
Fixes #40771.
*Felipe*
* Allow delegated_type to be specified primary_key and foreign_key.
Since delegated_type assumes that the foreign_key ends with `_id`,
`singular_id` defined by it does not work when the foreign_key does
not end with `id`. This change fixes it by taking into account
`primary_key` and `foreign_key` in the options.
*Ryota Egusa*
* Expose an `invert_where` method that will invert all scope conditions.
```ruby
class User
scope :active, -> { where(accepted: true, locked: false) }
end
User.active
# ... WHERE `accepted` = 1 AND `locked` = 0
User.active.invert_where
# ... WHERE NOT (`accepted` = 1 AND `locked` = 0)
```
*Kevin Deisz*
* Restore possibility of passing `false` to :polymorphic option of `belongs_to`.
Previously, passing `false` would trigger the option validation logic
to throw an error saying :polymorphic would not be a valid option.
*glaszig*
* Remove deprecated `database` kwarg from `connected_to`.
*Eileen M. Uchitelle*, *John Crepezzi*
* Allow adding nonnamed expression indexes to be revertible.
Fixes #40732.
Previously, the following code would raise an error, when executed while rolling back,
and the index name should be specified explicitly. Now, the index name is inferred
automatically.
```ruby
add_index(:items, "to_tsvector('english', description)")
```
*fatkodima*
* Only warn about negative enums if a positive form that would cause conflicts exists.
Fixes #39065.
*Alex Ghiculescu*
Add option for `default_scope` to run on all queries This change allows for applications to optionally run a `default_scope` on `update` and `delete` queries. Default scopes already ran on select and insert queries. Applications can now run a set default scope on all queries for a model by setting a `all_queries` option: ```ruby class Article < ApplicationRecord default_scope -> { where(blog_id: 1) }, all_queries: true end ``` Using the default scope in this way is useful for applications that need to query by more than the primary key by default. An example of this would be in an application using a sharding strategy like Vitess like. For Rails sharding, we route connections first and then query the database. However, Vitess and other solutions use a parameter in the query to figure out how to route the queries. By extending `default_scope` to apply to all queries we can allow applications to optionally apply additional constraints to all queries. Note that this only works with `where` queries as it does not make sense to select a record by primary key with an order. With this change we're allowing apps to select with a primary key and an additional key. To make this change dynamic for routing queries in a tenant sharding strategy applications can use the `Current` API or parameters in a request to route queries: ```ruby class Article < ApplicationRecord default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true end ``` In order to achieve this I created a new object when default scopes are created. This allows us to store both the scope itself and whether we should run this on all queries. I chose not to implement an `on:` option that takes an array of actions because there is no simple or clear way to turn off the default scope for create/select. It also doesn't really make sense to only have a default scope for delete queries. The decision to use `all_queries` here allows for the implementation to be more flexible than it was without creating a mess in an application.
2020-11-19 22:20:45 +00:00
* Add option to run `default_scope` on all queries.
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 (ie `blog_id`).
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.
```ruby
class Article < ApplicationRecord
default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true
end
```
*Eileen M. Uchitelle*
* Add `where.associated` to check for the presence of an association.
```ruby
# Before:
account.users.joins(:contact).where.not(contact_id: nil)
# After:
account.users.where.associated(:contact)
```
Also mirrors `where.missing`.
*Kasper Timm Hansen*
* Allow constructors (`build_association` and `create_association`) on
`has_one :through` associations.
*Santiago Perez Perret*
2020-12-02 23:37:26 +00:00
Please check [6-1-stable](https://github.com/rails/rails/blob/6-1-stable/activerecord/CHANGELOG.md) for previous changes.