aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation.rb
Commit message (Collapse)AuthorAgeFilesLines
* document update_counters on relation [ci skip]Guilherme Mansur2019-05-111-1/+13
|
* Remove useless `set_value` / `get_value` helper methodsRyuta Kamizono2019-04-221-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Those helper methods makes relation values access 15% slower. https://gist.github.com/kamipo/e64439f7a206e1c5b5c69d92d982828e Before (02b5b8cb): ``` Warming up -------------------------------------- #limit_value 237.074k i/100ms #limit_value = 1 222.052k i/100ms Calculating ------------------------------------- #limit_value 6.477M (± 2.9%) i/s - 32.479M in 5.019475s #limit_value = 1 5.297M (± 4.3%) i/s - 26.424M in 4.999933s ``` After (this change): ``` Warming up -------------------------------------- #limit_value 261.109k i/100ms #limit_value = 1 239.646k i/100ms Calculating ------------------------------------- #limit_value 7.412M (± 1.6%) i/s - 37.077M in 5.003345s #limit_value = 1 6.134M (± 1.0%) i/s - 30.675M in 5.000908s ```
* Revert "Deprecate `collection_cache_key` which is private API"Ryuta Kamizono2019-04-191-1/+1
| | | | | | | | | | | This reverts commit f656bb301a43fe441af0039e4fafe40a7faa62f8. Reason: Test in Action View expects the `collection_cache_key` working... https://github.com/rails/rails/blob/ff6b713f5e729859995f204093ad3f8e08f39ea8/actionview/test/activerecord/relation_cache_test.rb#L21 https://github.com/rails/rails/blob/ff6b713f5e729859995f204093ad3f8e08f39ea8/actionview/test/fixtures/project.rb#L6 https://buildkite.com/rails/rails/builds/60609#d19181fb-fe80-4d1e-891c-1109b540fb4b/981-1009
* Deprecate `collection_cache_key` which is private APIRyuta Kamizono2019-04-191-1/+3
| | | | | | | | | The `collection_cache_key` is private API for a long time, but I've maintained it in #35848 since it is mentioned in the doc (https://github.com/rails/rails/pull/35848#discussion_r272011475). The doc has removed at 1da9a7e4, so there is no longer a reason to maintain that private API.
* Add collection cache versioningLachlan Sylvester2019-04-161-15/+36
| | | | | | | | | | | | | | | Cache versioning enables the same cache key to be reused when the object being cached changes by moving the volatile part of the cache key out of the cache key and into a version that is embedded in the cache entry. This is already occurring when the object being cached is an `ActiveRecord::Base`, but when caching an `ActiveRecord::Relation` we are currently still putting the volatile information (max updated at and count) as part of the cache key. This PR moves the volatile part of the relations `cache_key` into the `cache_version` to support recycling cache keys for `ActiveRecord::Relation`s.
* There is no need to check `null_relation?` in `empty_scope?`Ryuta Kamizono2019-04-061-1/+1
| | | | `values[:extending]` includes `NullRelation` if `null_relation?`.
* Association loading isn't to be affected by null relation scopingRyuta Kamizono2019-04-061-2/+6
| | | | | | Follow up of #35868. Closes #19349.
* Refactor `Relation#cache_key` is moved from ↵Ryuta Kamizono2019-04-041-0/+45
| | | | | | | | | | | | `CollectionCacheKey#collection_cache_key` The implementation of `Relation#cache_key` depends on some internal relation methods (e.g. `apply_join_dependency`, `build_subquery`), but somehow that implementation exists on the model class (`collection_cache_key`), it sometimes bothers to me. This refactors that implementation moves to `Relation#cache_key`, then we can avoid `send` to call internal methods.
* Revert unused code and re-using query annotation for `update_all` and ↵Ryuta Kamizono2019-04-011-3/+0
| | | | | | | | | | | | | | | | `delete_all` This partly reverts #35617. #35617 includes unused code (for `InsertStatement`) and re-using query annotation for `update_all` and `delete_all`, which has not been discussed yet. If a relation has any annotation, I think it is mostly for SELECT query, so re-using annotation by default is not always desired behavior for me. We should discuss about desired behavior before publishing the implementation.
* Add Relation#annotate for SQL commentingMatt Yoho2019-03-211-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch has two main portions: 1. Add SQL comment support to Arel via Arel::Nodes::Comment. 2. Implement a Relation#annotate method on top of that. == Adding SQL comment support Adds a new Arel::Nodes::Comment node that represents an optional SQL comment and teachers the relevant visitors how to handle it. Comment nodes may be added to the basic CRUD statement nodes and set through any of the four (Select|Insert|Update|Delete)Manager objects. For example: manager = Arel::UpdateManager.new manager.table table manager.comment("annotation") manager.to_sql # UPDATE "users" /* annotation */ This new node type will be used by ActiveRecord::Relation to enable query annotation via SQL comments. == Implementing the Relation#annotate method Implements `ActiveRecord::Relation#annotate`, which accepts a comment string that will be appeneded to any queries generated by the relation. Some examples: relation = Post.where(id: 123).annotate("metadata string") relation.first # SELECT "posts".* FROM "posts" WHERE "posts"."id" = 123 # LIMIT 1 /* metadata string */ class Tag < ActiveRecord::Base scope :foo_annotated, -> { annotate("foo") } end Tag.foo_annotated.annotate("bar").first # SELECT "tags".* FROM "tags" LIMIT 1 /* foo */ /* bar */ Also wires up the plumbing so this works with `#update_all` and `#delete_all` as well. This feature is useful for instrumentation and general analysis of queries generated at runtime.
* update_at/on note for ActiveRecord::Relation.update_all (#35461)Orhan Toy2019-03-191-2/+4
| | | | | | * update_at/on note for ActiveRecord::Relation.update_all * Verbatim updated_at/on
* Support Optimizer HintsRyuta Kamizono2019-03-161-1/+1
| | | | | | | | | | | | | | | | | | We as Arm Treasure Data are using Optimizer Hints with a monkey patch (https://gist.github.com/kamipo/4c8539f0ce4acf85075cf5a6b0d9712e), especially in order to use `MAX_EXECUTION_TIME` (refer #31129). Example: ```ruby class Job < ApplicationRecord default_scope { optimizer_hints("MAX_EXECUTION_TIME(50000) NO_INDEX_MERGE(jobs)") } end ``` Optimizer Hints is supported not only for MySQL but also for most databases (PostgreSQL on RDS, Oracle, SQL Server, etc), it is really helpful to turn heavy queries for large scale applications.
* [skip ci] Rails 5.1+ supports bigint primary keyYasuo Honda2019-03-131-1/+1
| | | | Follow up #35573
* Document int Primary Key with create_or_find_by (#35573)Alex Kitchens2019-03-121-0/+4
| | | | | This commit addresses the issue in https://github.com/rails/rails/issues/35543 by making note of the growing primary key issue with `create_or_find_by`.
* Ensure `update_all` series cares about optimistic lockingRyuta Kamizono2019-02-251-10/+15
| | | | | | Incrementing the lock version invalidates any other process's optimistic lock, which is the desired outcome: the record no longer looks the same as it did when they loaded it.
* Introduce delete_by and destroy_by methods to ActiveRecord::RelationAbhay Nikam2019-02-191-0/+26
|
* Deprecate using class level querying methods if the receiver scope regarded ↵Ryuta Kamizono2019-02-151-5/+38
| | | | | | | | | | as leaked This deprecates using class level querying methods if the receiver scope regarded as leaked, since #32380 and #35186 may cause that silently leaking information when people upgrade the app. We need deprecation first before making those.
* Revert "Merge pull request #35186 from ↵Ryuta Kamizono2019-02-151-11/+2
| | | | | | | | | | | | kamipo/fix_leaking_scope_on_relation_create" This reverts commit b67d5c6dedbf033515a96a95d24d085bf99a0d07, reversing changes made to 2e018361c7c51e36d1d98bf770b7456d78dee68b. Reason: #35186 may cause that silently leaking information when people upgrade the app. We need deprecation first before making this.
* Revert "Chaining named scope is no longer leaking to class level querying ↵Ryuta Kamizono2019-02-141-2/+2
| | | | | | | | | methods" This reverts #32380, since this may cause that silently leaking information when people upgrade the app. We need deprecation first before making this.
* Refactor extracting `current_scope_restoring_block` into the scoping classRyuta Kamizono2019-02-081-5/+1
| | | | Relation is not best place to do this.
* Fix `relation.create` to avoid leaking scope to initialization block and ↵Ryuta Kamizono2019-02-071-2/+15
| | | | | | | | | | | | | | | | | | | | callbacks `relation.create` populates scope attributes to new record by `scoping`, it is necessary to assign the scope attributes to the record and to find STI subclass from the scope attributes. But the effect of `scoping` is class global, it was caused undesired behavior that pollute all class level querying methods in initialization block and callbacks (`after_initialize`, `before_validation`, `before_save`, etc), which are user provided code. To avoid the leaking scope issue, restore the original current scope before initialization block and callbacks are invoked. Fixes #9894. Fixes #17577. Closes #31526.
* Refactor around scopingRyuta Kamizono2019-02-071-2/+9
| | | | | | Don't use `false` as special value to skip to find inherited scope, we could use `skip_inherited_scope = true`, and move `_scoping` back on Relation.
* Chaining named scope is no longer leaking to class level querying methodsRyuta Kamizono2019-02-061-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Active Record uses `scoping` to delegate to named scopes from relations for propagating the chaining source scope. It was needed to restore the source scope in named scopes, but it was caused undesired behavior that pollute all class level querying methods. Example: ```ruby class Topic < ActiveRecord::Base scope :toplevel, -> { where(parent_id: nil) } scope :children, -> { where.not(parent_id: nil) } scope :has_children, -> { where(id: Topic.children.select(:parent_id)) } end # Works as expected. Topic.toplevel.where(id: Topic.children.select(:parent_id)) # Doesn't work due to leaking `toplevel` to `Topic.children`. Topic.toplevel.has_children ``` Since #29301, the receiver in named scopes has changed from the model class to the chaining source scope, so the polluting class level querying methods is no longer required for that purpose. Fixes #14003.
* Refactor `bind_attribute` to expand an association to actual attributeRyuta Kamizono2019-01-111-0/+5
|
* #create_or_find_by/!: add more tests and fix docs (#34653)Bogdan2018-12-081-2/+2
| | | | | | | | * `#create_or_find_by/!`: add more tests * Fix docs of `create_or_find_by` This method uses `find_by!` internally.
* Move UPDATE/DELETE with JOIN handling to the Arel sideRyuta Kamizono2018-10-031-26/+12
|
* Handle UPDATE/DELETE with OFFSET in ArelRyuta Kamizono2018-10-011-2/+4
|
* Handle DELETE with LIMIT in ArelRyuta Kamizono2018-09-301-1/+4
| | | | | | | | | | | | | | | | | | MySQL supports DELETE with LIMIT and ORDER BY. https://dev.mysql.com/doc/refman/8.0/en/delete.html Before: ``` Post Destroy (1.0ms) DELETE FROM `posts` WHERE `posts`.`id` IN (SELECT `id` FROM (SELECT `posts`.`id` FROM `posts` WHERE `posts`.`author_id` = ? ORDER BY `posts`.`id` ASC LIMIT ?) __active_record_temp) [["author_id", 1], ["LIMIT", 1]] ``` After: ``` Post Destroy (0.4ms) DELETE FROM `posts` WHERE `posts`.`author_id` = ? ORDER BY `posts`.`id` ASC LIMIT ? [["author_id", 1], ["LIMIT", 1]] ```
* Extract `Arel.arel_node?` helper methodRyuta Kamizono2018-09-281-1/+1
|
* Make `update_counters` preparableRyuta Kamizono2018-09-281-9/+14
| | | | | | | | | | | | | | | | Before: ``` Topic Update All (0.4ms) UPDATE `topics` SET `topics`.`replies_count` = COALESCE(`topics`.`replies_count`, 0) + 1, `topics`.`updated_at` = '2018-09-27 18:34:05.068774' WHERE `topics`.`id` = ? [["id", 7]] ``` After: ``` Topic Update All (0.4ms) UPDATE `topics` SET `topics`.`replies_count` = COALESCE(`topics`.`replies_count`, 0) + ?, `topics`.`updated_at` = ? WHERE `topics`.`id` = ? [["replies_count", 1], ["updated_at", 2018-09-27 18:55:05 UTC], ["id", 7]] ```
* Make `update_all` preparableRyuta Kamizono2018-09-281-2/+14
| | | | | | | | | | | | | | Before: ``` Pet Update All (0.8ms) UPDATE `pets` LEFT OUTER JOIN `toys` ON `toys`.`pet_id` = `pets`.`pet_id` SET `pets`.`name` = 'Bob' WHERE `toys`.`name` = ? [["name", "Bone"]] ``` After: ``` Pet Update All (1.1ms) UPDATE `pets` LEFT OUTER JOIN `toys` ON `toys`.`pet_id` = `pets`.`pet_id` SET `pets`.`name` = ? WHERE `toys`.`name` = ? [["name", "Bob"], ["name", "Bone"]] ```
* Use table name qualified column name for update countersRyuta Kamizono2018-09-161-9/+7
| | | | | | | | | MySQL supports JOINs to UPDATE, so if column name isn't qualified by table name, it would cause an ambiguous error: ``` Mysql2::Error: Column 'integer' in field list is ambiguous: UPDATE `pets` INNER JOIN `toys` ON `toys`.`pet_id` = `pets`.`pet_id` SET `integer` = COALESCE(`integer`, 0) + 1 WHERE `toys`.`name` = ? ```
* Refactor object creation from relation to avoid pushing scope attributesRyuta Kamizono2018-09-111-24/+3
| | | | | | Pushing scope attributes was added at d4007d5 for fixing inheritance object creation. But it was not a better fix, since we could just pull that on demand in `Inheritance` module.
* Move `scoping` handling into klass level from relationRyuta Kamizono2018-09-111-4/+1
| | | | | I'd like to use this `scoping` handling on klass level to address unwanted internal scoping issues.
* Fixes #33610Darwin D Wu2018-09-111-7/+18
| | | | | | | | | | | | In order to avoid double assignments of nested_attributes for `has_many` relations during record initialization, nested_attributes in `create_with` should not be passed into `klass.new` and have them populate during `initialize_internals_callback` with scope attributes. However, `create_with` keys should always have precedence over where clauses, so if there are same keys in both `create_with` and `where_values_hash`, the value in `create_with` should be the one that's used.
* Just delegate `update` with ids on a relation to `klass.update`Ryuta Kamizono2018-08-311-2/+6
| | | | | | | | | | | | This restores an ability that `update` with ids on a relation which is described at https://github.com/rails/rails/issues/33470#issuecomment-411203013. I personally think that the `update` with two arguments on a relation is not a designed feature, since that is totally not using a relation state, and also is not documented. But removing any feature should not be suddenly happened in a stable version even if that is not documented.
* Avoid extra scoping when using `Relation#update`Ryuta Kamizono2018-07-311-0/+4
| | | | | | | | | | | | | | Since 9ac7dd4, class level `update`, `destroy`, and `delete` were placed in the `Persistence` module as class methods. But `Relation#update` without passing ids which was introduced at #11898 is not a class method, and it was caused the extra scoping regression #33470. I moved the relation method back into the `Relation` to fix the regression. Fixes #33470.
* Extract `Relation#bind_attribute` for internal useRyuta Kamizono2018-07-301-0/+6
| | | | To make it easier to construct boundable predicate.
* Extract `Relation#update_counters` for internal useRyuta Kamizono2018-07-301-0/+18
| | | | | | The target object for counter cache is not always determined by the primary key value on the model. I'd like to extract `update_couters` onto the `Relation` for the internal use.
* Rails guides are now served over httpsPaul McMahon2018-07-241-1/+1
| | | | | http links will be redirected to the https version, but still better to just directly link to the https version.
* Avoid extra scoping in delegating to klass methods in the `scope` blockRyuta Kamizono2018-07-191-2/+2
| | | | | | | | | | Since #29301, delegating to klass methods in the `scope` block would cause extra scoping by the receiver itself. The extra scoping would always override intermediate scoping like `unscoped` and caused the regression #33387. To keep the original scoping behavior, should avoid the extra scoping in the `scope` block. Fixes #33387.
* Ensure to calculate column aliases after all table aliases are constructedRyuta Kamizono2018-06-191-11/+11
| | | | | | | | | | | | | | | | | Currently, column aliases which is used for eager loading are calculated before constructing all table aliases in FROM clause. `JoinDependency#join_constraints` constructs table aliases for `joins` first, and then always re-constructs table aliases for eager loading. If both `joins` and eager loading are given a same table association, the re-construction would cause the discrepancy between column aliases and table aliases. To avoid the discrepancy, the column aliases should be calculated after all table aliases are constructed. Fixes #30603.
* Fix `touch` option to behave consistently with `Persistence#touch` methodRyuta Kamizono2018-06-181-4/+1
| | | | | | | | | | | | | | | | `touch` option was added to `increment!` (#27660) and `update_counters` (#26995). But that option behaves inconsistently with `Persistence#touch` method. If `touch` option is passed attribute names, it won't update update_at/on attributes unlike `Persistence#touch` method. Due to changed from `Persistence#touch` to `increment!` with `touch` option, #31405 has a regression that `counter_cache` with `touch` option which is passed attribute names won't update update_at/on attributes. I think that the inconsistency is not intended. To get back consistency, ensure that `touch` option updates update_at/on attributes.
* Fix typo in the `touch_all` doc [ci skip]Ryuta Kamizono2018-04-211-4/+4
|
* Merge pull request #31513 from fatkodima/relation-touch_allRafael França2018-04-201-0/+37
|\ | | | | Add `touch_all` method to `ActiveRecord::Relation`
| * Add `touch_all` method to `ActiveRecord::Relation`fatkodima2018-04-131-0/+37
| |
* | Don't expose `Relation#preload_associations` in the docRyuta Kamizono2018-04-201-1/+1
|/ | | | | | | The extracted method is used for `CollectionCacheAssociationLoading`, still not public API. [ci skip]
* don't check for immutability when setting skip_preloading as it doesn't ↵Lachlan Sylvester2018-04-121-2/+3
| | | | effect the arel and the arel may already be generated by fresh_when
* Deprecate accessibility of private/protected class methods in named scopeRyuta Kamizono2018-03-301-0/+2
|
* Bring back private class methods accessibility in named scopeRyuta Kamizono2018-03-271-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The receiver in a scope was changed from `klass` to `relation` itself for all scopes (named scope, default_scope, and association scope) behaves consistently. In addition. Before 5.2, if both an AR model class and a Relation instance have same named methods (e.g. `arel_attribute`, `predicate_builder`, etc), named scope doesn't respect relation instance information. For example: ```ruby class Post < ActiveRecord::Base has_many :comments1, class_name: "RecentComment1" has_many :comments2, class_name: "RecentComment2" end class RecentComment1 < ActiveRecord::Base self.table_name = "comments" default_scope { where(arel_attribute(:created_at).gteq(2.weeks.ago)) } end class RecentComment2 < ActiveRecord::Base self.table_name = "comments" default_scope { recent_updated } scope :recent_updated, -> { where(arel_attribute(:updated_at).gteq(2.weeks.ago)) } end ``` If eager loading `Post.eager_load(:comments1, :comments2).to_a`, `:comments1` (default_scope) respects aliased table name, but `:comments2` (using named scope) may not work correctly since named scope doesn't respect relation instance information. See also 801ccab. But this is a breaking change between releases without deprecation. I decided to bring back private class methods accessibility in named scope. Fixes #31740. Fixes #32331.