aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations
Commit message (Collapse)AuthorAgeFilesLines
* Use `try` only when we're unsure if the receiver would respond_to the methodAkira Matsuda2019-08-011-1/+1
|
* Merge pull request #36708 from ↵Kasper Timm Hansen2019-07-312-12/+11
|\ | | | | | | | | rails/has-one-polymorphic-touch-dont-cache-association-result-inside-create-transaction Polymorphic has_one touch: Don't cache association result inside crea…
| * Polymorphic has_one touch: Reset association cache result after create ↵Kasper Timm Hansen2019-07-312-12/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | transaction In case of a polymorphic association there's no automatic inverse_of to assign the inverse record. So to get the record there needs to be a query executed, however, if the query fires within the transaction that's trying to create the associated record, no record can be found. And worse, the nil result is cached on the association so after the transaction commits the record can't be found. That's what happens if touch is enabled on a polymorphic has_one association. Consider a Comment with a commentable association that needs to be touched. For `Comment.create(commentable: Post.new)`, the existing code essentially does `commentable.send(:comment)` within the create transaction for the comment and thus not finding the comment. Now we're purposefully clearing the cache in case we've tried accessing the association within the transaction and found no object. Before: ``` kaspth-imac 2.6.3 ~/code/rails/activerecord master *= ARCONN=postgresql bin/test test/cases/associations/has_one_associations_test.rb -n /commit/ Using postgresql Run options: -n /commit/ --seed 46022 D, [2019-07-19T03:30:37.864537 #96022] DEBUG -- : Chef Load (0.2ms) SELECT "chefs".* FROM "chefs" WHERE "chefs"."employable_id" = $1 AND "chefs"."employable_type" = $2 LIMIT $3 [["employable_id", 1], ["employable_type", "DrinkDesignerWithPolymorphicTouchChef"], ["LIMIT", 1]] D, [2019-07-19T03:30:37.865013 #96022] DEBUG -- : Chef Create (0.2ms) INSERT INTO "chefs" ("employable_id", "employable_type") VALUES ($1, $2) RETURNING "id" [["employable_id", 1], ["employable_type", "DrinkDesignerWithPolymorphicTouchChef"]] D, [2019-07-19T03:30:37.865201 #96022] DEBUG -- : TRANSACTION (0.1ms) RELEASE SAVEPOINT active_record_1 D, [2019-07-19T03:30:37.874136 #96022] DEBUG -- : TRANSACTION (0.1ms) ROLLBACK D, [2019-07-19T03:30:37.874323 #96022] DEBUG -- : TRANSACTION (0.1ms) ROLLBACK F Failure: HasOneAssociationsTest#test_polymorphic_has_one_with_touch_option_on_create_wont_cache_assocation_so_fetching_after_transaction_commit_works [/Users/kaspth/code/rails/activerecord/test/cases/associations/has_one_associations_test.rb:716]: --- expected +++ actual @@ -1 +1 @@ -#<Chef id: 1, employable_id: 1, employable_type: "DrinkDesignerWithPolymorphicTouchChef", department_id: nil, employable_list_type: nil, employable_list_id: nil> +nil ``` After: ``` kaspth-imac 2.6.3 ~/code/rails/activerecord master *= ARCONN=postgresql bin/test test/cases/associations/has_one_associations_test.rb -n /commit/ Using postgresql Run options: -n /commit/ --seed 46022 D, [2019-07-19T03:30:22.479387 #95973] DEBUG -- : Chef Create (0.3ms) INSERT INTO "chefs" ("employable_id", "employable_type") VALUES ($1, $2) RETURNING "id" [["employable_id", 1], ["employable_type", "DrinkDesignerWithPolymorphicTouchChef"]] D, [2019-07-19T03:30:22.479574 #95973] DEBUG -- : TRANSACTION (0.1ms) RELEASE SAVEPOINT active_record_1 D, [2019-07-19T03:30:22.482051 #95973] DEBUG -- : Chef Load (0.1ms) SELECT "chefs".* FROM "chefs" WHERE "chefs"."employable_id" = $1 AND "chefs"."employable_type" = $2 LIMIT $3 [["employable_id", 1], ["employable_type", "DrinkDesignerWithPolymorphicTouchChef"], ["LIMIT", 1]] D, [2019-07-19T03:30:22.482317 #95973] DEBUG -- : TRANSACTION (0.1ms) ROLLBACK D, [2019-07-19T03:30:22.482437 #95973] DEBUG -- : TRANSACTION (0.1ms) ROLLBACK . Finished in 0.088498s, 11.2997 runs/s, 22.5994 assertions/s. 1 runs, 2 assertions, 0 failures, 0 errors, 0 skips ``` Notice the select now fires after the commit.
* | Use match? where we don't need MatchDataAkira Matsuda2019-07-291-1/+1
| |
* | Merge pull request #36776 from ↵Rafael França2019-07-261-1/+1
|\ \ | |/ |/| | | | | giraffate/fix_join_middle_table_alias_when_using_HABTM Fix join middle table alias when using HABTM
| * Fix join middle table alias when using HABTMTakayuki Nakata2019-07-261-1/+1
| | | | | | | | | | | | | | | | In using HABTM, join middle table alias is combined with the associated models name without sort, while middle table name is combined with those models name with sort. Fixes #36742.
* | Merge pull request #36412 from robotdana/compact_blankRafael Mendonça França2019-07-251-1/+1
|\ \ | |/ |/| | | Add compact_blank shortcut for reject(&:blank?)
| * Use compact_blank throughout railsDana Sherson2019-06-051-1/+1
| |
* | Enable `Layout/EmptyLinesAroundAccessModifier` copRyuta Kamizono2019-06-135-6/+0
| | | | | | | | | | | | | | | | | | | | | | We sometimes say "✂️ newline after `private`" in a code review (e.g. https://github.com/rails/rails/pull/18546#discussion_r23188776, https://github.com/rails/rails/pull/34832#discussion_r244847195). Now `Layout/EmptyLinesAroundAccessModifier` cop have new enforced style `EnforcedStyle: only_before` (https://github.com/rubocop-hq/rubocop/pull/7059). That cop and enforced style will reduce the our code review cost.
* | Fix preloading on AR::Relation where records are duplicated by a joinBogdan Gusiev2019-06-061-1/+3
|/
* Merge pull request #36320 from XrXr/no-doc-prependRafael França2019-05-211-1/+1
|\ | | | | [CI skip] Put :nodoc: on method that raises NoMethodError
| * Put :nodoc: on method that raises NoMethodErrorAlan Wu2019-05-211-1/+1
| | | | | | | | | | This method is not intended to be used so I think we should remove it from the docs.
* | Fix eager loading associations with string joins not to raise NoMethodErrorRyuta Kamizono2019-05-151-2/+11
| | | | | | | | Fixes #34456.
* | Namespace association extension modules under the owner modelJean Boussier2019-05-021-2/+2
| |
* | Fix merging left_joins to maintain its own `join_type` contextRyuta Kamizono2019-04-271-9/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This fixes a regression for #35864. Usually, stashed joins (mainly eager loading) are performed as LEFT JOINs. But the case of merging joins/left_joins of different class, that (stashed) joins are performed as the same `join_type` as the parent context for now. Since #35864, both (joins/left_joins) stashed joins might be contained in `joins_values`, so each stashed joins should maintain its own `join_type` context. Fixes #36103.
* | Merge pull request #35869 from ↵Ryuta Kamizono2019-04-251-2/+34
|\ \ | | | | | | | | | | | | | | | abhaynikam/35866-add-touch-option-for-has-one-association Adds missing touch option to has_one association
| * | Adds touch option to has_one associationAbhay Nikam2019-04-251-2/+34
| | |
* | | Fix sliced IN clauses to be groupedRyuta Kamizono2019-04-241-7/+1
|/ / | | | | | | | | | | | | Follow up of #35838. And also this refactors `in_clause_length` handling is entirely integrated in Arel visitor.
* | Merge pull request #36070 from imechemi/fix-minor-api-docRyuta Kamizono2019-04-241-1/+1
|\ \ | | | | | | | | | | | | Minor API doc fix [ci skip]
| * | Fix rdoc rendering for push alias symbolTenzin Chemi2019-04-231-1/+1
| | |
* | | Rename local variable `n` to `name`Ryuta Kamizono2019-04-241-2/+2
|/ /
* | Make association builder methods privateRyuta Kamizono2019-04-246-0/+15
| |
* | Fix `automatic_inverse_of` not to be disabled if extension block is givenRyuta Kamizono2019-04-122-30/+10
| | | | | | | | | | | | | | | | If an association has a scope, `automatic_inverse_of` is to be disabled. But extension block is obviously not a scope. It should not be regarded as a scope. Fixes #28806.
* | Association loading isn't to be affected by scoping consistentlyRyuta Kamizono2019-04-051-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Follow-up of 5c71000, #29834, and #30271. Currently, preloading and eager loading are not to be affected by scoping, with the exception of `unscoped`. But non eager loaded association access is still affected by scoping. Although this is a breaking change, the association loading will work consistently whether preloaded / eager loaded or not. Before: ```ruby Post.where("1=0").scoping do Comment.find(1).post # => nil Comment.preload(:post).find(1).post # => #<Post id: 1, ...> Comment.eager_load(:post).find(1).post # => #<Post id: 1, ...> end ``` After: ```ruby Post.where("1=0").scoping do Comment.find(1).post # => #<Post id: 1, ...> Comment.preload(:post).find(1).post # => #<Post id: 1, ...> Comment.eager_load(:post).find(1).post # => #<Post id: 1, ...> end ``` Fixes #34638. Fixes #35398.
* | `preloaded_records` no longer includes `nil` since #35496Ryuta Kamizono2019-04-051-1/+0
| |
* | Merge pull request #35799 from leboshi/masterRyuta Kamizono2019-03-311-11/+4
|\ \ | | | | | | | | | Fix callbacks on has_many :through associations
| * | Fix callbacks on has_many :through associations (#33249)Ryan Kerr2019-03-301-10/+4
|/ / | | | | | | | | | | | | | | | | | | | | When adding a child record via a has_many :through association, build_through_record would previously build the join record, and then assign the child record and source_type option to it. Because the before_add and after_add callbacks are called as part of build, however, this caused the callbacks to receive incomplete records, specifically without the other end of the has_many :through association. Collecting all attributes before building the join record ensures the callbacks receive the fully constructed record.
* | Merge pull request #35496 from bogdan/right-preloadingRyuta Kamizono2019-03-283-64/+90
|\ \ | | | | | | Fix preloader to never reset associations in case they are already loaded
| * | Fix preloader to never reset associations in case they are already loadedBogdan Gusiev2019-03-073-64/+90
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch fixes the issue when association is preloaded with a custom preload scope which disposes the already preloaded target of the association by reseting it. When custom preload scope is used, the preloading is now performed into a separated Hash - #records_by_owner instead of the association. It removes the necessaty the reset the association after the preloading is complete so that reset of the preloaded association never happens. Preloading is still happening to the association when the preload scope is empty.
* | | Add Relation#annotate for SQL commentingMatt Yoho2019-03-211-1/+5
| |/ |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* | Merge pull request #35121 from utilum/warning_tried_to_create_proc_without_blockKasper Timm Hansen2019-03-101-2/+2
|\ \ | |/ |/| Ruby 2.7 warning: creating a Proc without a block
| * Ruby 2.7 warning: creating a Proc without a blockutilum2019-02-131-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As of [Revision 66772]( https://bugs.ruby-lang.org/projects/ruby-trunk/repository/trunk/revisions/66772) `Proc.new` without giving a block emits `warning: tried to create Proc object without a block`. This commit fixes cases where Rails test suit tickles this warning. See CI logs: https://travis-ci.org/rails/rails/jobs/487205819#L1161-L1190 https://travis-ci.org/rails/rails/jobs/487205821#L1154-1159 https://travis-ci.org/rails/rails/jobs/487205821#L1160-L1169 https://travis-ci.org/rails/rails/jobs/487205821#L1189 https://travis-ci.org/rails/rails/jobs/487254404#L1307-L1416 https://travis-ci.org/rails/rails/jobs/487254405#L1174-L1191
* | Fix preload with nested associationsRafael Mendonça França2019-02-261-1/+5
| | | | | | | | | | | | When the middle association doesn't have any records and the inner association is not an empty scope the owner will be `nil` so we can't try to reset the inverse association.
* | Merge pull request #35247 from bogdan/fix-source-reflection-reset-codeRyuta Kamizono2019-02-202-21/+10
|\ \ | | | | | | Fix reset of the source association when through association is loaded
| * | Fix reset of the source association when through association is loadedBogdan Gusiev2019-02-202-21/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | The special case happens when through association has a custom scope that is applied to the source association when loading. In this case, the soucre association would need to be reset after main association is loaded. See tests. The special case exists when a through association has
* | | Fix eager loading polymorphic association with mixed table conditionsRyuta Kamizono2019-02-181-6/+11
| | | | | | | | | | | | | | | | | | This fixes a bug that the `foreign_key` and the `foreign_type` are separated as different table conditions if a polymorphic association has a scope that joins another tables.
* | | Revert "Merge pull request #35127 from bogdan/counter-cache-loading"Ryuta Kamizono2019-02-132-11/+6
| |/ |/| | | | | | | | | | | | | | | | | | | | | | | This reverts commit eec3e28a1abf75676dcee58308ee5721bb53c325, reversing changes made to 5588fb4802328a2183f4a55c36d6703ee435f85c. Reason: Marking as loaded without actual loading is too greedy optimization. See more context #35239. Closes #35239. [Edouard CHIN & Ryuta Kamizono]
* | Merge pull request #35196 from gmcgibbon/clarify_collection_proxy_docsGannon McGibbon2019-02-112-11/+25
|\ \ | | | | | | Clarify collection proxy docs
| * | Clarify collection proxy docsGannon McGibbon2019-02-082-11/+25
| |/ | | | | | | | | | | | | | | | | The docs for `ActiveRecord::Associations::CollectionProxy` describe `ActiveRecord::Associations::Association`. I've moved them to association and rewrote collection proxy's docs to be more applicable to what the class actually does.` [ci skip]
* | Refactor to just use `Association#target=` in `associate_records_to_owner`Ryuta Kamizono2019-02-091-3/+2
| | | | | | | | | | | | | | | | | | | | | | `Association#target=` invokes `loaded!`, so we no longer need to call the `loaded!` explicitly. Since Preloader is private API, we don't guarantee that it behaves like older version as long as using Preloader directly. But this refactoring fortunately also fix the Preloader compatibility issue #35195. Closes #35195.
* | Merge pull request #35178 from bogdan/has-many-sizeRyuta Kamizono2019-02-081-2/+2
|\ \ | |/ |/| Bugfix has_many association #size when ids reader is cached and assoc…
| * Bugfix has_many association #size when ids reader is cached and association ↵Bogdan Gusiev2019-02-081-2/+2
| | | | | | | | is changed
* | Fix `CollectionProxy#concat` to return self by alias it to `#<<`Yuya Tanaka2019-02-062-33/+6
|/ | | | Formerly it was returning arguments (`records` array).
* Merge pull request #35127 from bogdan/counter-cache-loadingRyuta Kamizono2019-02-052-16/+13
|\ | | | | Bugfix association loading behavior when counter cache is zero
| * Bugfix association loading behavior when counter cache is zeroBogdan Gusiev2019-02-052-16/+13
| |
* | Ensure `StatementCache#execute` never raises `RangeError`Ryuta Kamizono2019-01-182-5/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | Since 31ffbf8d, finder methods no longer raise `RangeError`. So `StatementCache#execute` is the only place to raise the exception for finder queries. `StatementCache` is used for simple equality queries in the codebase. This means that if `StatementCache#execute` raises `RangeError`, the result could always be regarded as empty. So `StatementCache#execute` just return nil in that range error case, and treat that as empty in the caller side, then we can avoid catching the exception in much places.
* | Refs #28025 nullify *_type column on polymorphic associations on :nu… ↵Laerti2019-01-153-2/+9
|/ | | | | | (#28078) This PR addresses the issue described in #28025. On `dependent: :nullify` strategy only the foreign key of the relation is nullified. However on polymorphic associations the `*_type` column is not nullified leaving the record with a NULL `*_id` but the `*_type` column is present.
* Merge pull request #34806 from bogdan/reuse-find-targetRyuta Kamizono2018-12-274-30/+20
|\ | | | | | | Reuse AR::Association#find_target method
| * Reuse AR::Association#find_target methodBogdan Gusiev2018-12-274-29/+21
| |
* | Merge pull request #34609 from kamipo/delete_all_on_collection_proxyRyuta Kamizono2018-12-042-0/+3
|\ \ | | | | | | | | | Ensure that `delete_all` on collection proxy returns affected count