aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/belongs_to_association.rb
Commit message (Collapse)AuthorAgeFilesLines
* Refactor counter cache to extract `decrement_counters_before_last_save` on ↵Ryuta Kamizono2018-09-271-11/+25
| | | | the belongs_to association
* Revert "Remove `counter_cache_target` which is no longer called"Ryuta Kamizono2018-09-261-1/+10
| | | | | | | | This reverts commit 376ffe0ea2e59dc51461122210729c05a10fb443. Since 38fae1f, `association.increment_counters` is called without inflated parent target if inverse_of is disabled. In that case, that commit would cause extra queries to inflate parent.
* Remove `counter_cache_target` which is no longer calledRyuta Kamizono2018-09-261-10/+1
| | | | | `counter_cache_target` is called only when updated counter cache in replacing target, but it was already removed at #33913.
* Don't update counter cache unless the record is actually savedRyuta Kamizono2018-09-191-16/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a 4th attempt to make counter cache transactional completely. Past attempts: #9236, #14849, #23357. All existing counter cache issues (increment/decrement twice, lost increment) are caused due to updating counter cache on the outside of the record saving transaction by assigning belongs_to record, even though assigning that doesn't cause the record saving. We have the `@_after_replace_counter_called` guard condition to mitigate double increment/decrement issues, but we can't completely prevent that inconsistency as long as updating counter cache on the outside of the transaction, since saving the record is not always happened after that. We already have handling counter cache after create/update/destroy, https://github.com/rails/rails/blob/1b90f614b1b3d06b7f02a8b9ea6cd84f15d58643/activerecord/lib/active_record/counter_cache.rb#L162-L189 https://github.com/rails/rails/blob/1b90f614b1b3d06b7f02a8b9ea6cd84f15d58643/activerecord/lib/active_record/associations/builder/belongs_to.rb#L33-L59 so just removing assigning logic on the belongs_to association makes counter cache transactional completely. Closes #14849. Closes #23357. Closes #31493. Closes #31494. Closes #32372. Closes #33113. Closes #33117 Closes #33129. Closes #33458.
* Extract `Relation#update_counters` for internal useRyuta Kamizono2018-07-301-7/+4
| | | | | | 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.
* Fix inconsistent touching behavior between assigning and unassigningRyuta Kamizono2018-05-271-1/+1
| | | | | | | | | | | On belongs_to with `touch: true` association, unassigned object is caused touching, but assigned object is not touched. And also, if primary key is customized, it will touch against the wrong target looked up by the customized key as primary key. This change ensures correctly touching consistently between assigning and unassigning.
* Fix `belongs_to_counter_cache_after_update` to respect polymorphic type changeRyuta Kamizono2018-05-271-0/+4
|
* Fix `different_target?` to respect custom primary key counterRyuta Kamizono2018-05-261-3/+6
|
* Eager loading won't mutate owner recordRyuta Kamizono2018-05-251-1/+3
| | | | | | | | | | | | | | | Since #31575, `BelongsToAssociation#target=` replaces owner record's foreign key to fix an inverse association bug. But the method is not only used for inverse association but also used for eager loading/preloading, it caused some public behavior changes (#32338, #32375). To avoid any side-effect in loading associations, I reverted the overriding `#target=`, then introduced `#inversed_from` to replace foreign key in `set_inverse_instance`. Closes #32375.
* Don't expose `SingularAssociation#replace` which is internal APIRyuta Kamizono2018-05-161-13/+12
| | | | | Originally `SingularAssociation#replace` abstract method is private, and doesn't intend to be called directly.
* Fix dependence on has_one/belongs_to relationshipsFernando Gorodscy2018-03-061-1/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | When a class has a belongs_to or has_one relationship with dependent: :destroy option enabled, objects of this class should not be deleted if it's dependents cannot be deleted. Example: class Parent has_one :child, dependent: :destroy end class Child belongs_to :parent, inverse_of: :child before_destroy { throw :abort } end c = Child.create p = Parent.create(child: c) p.destroy p.destroyed? # expected: false; actual: true; Fixes #32022
* Bugfix foreign key replacement in inverse associationBogdan Gusiev2017-12-271-7/+7
| | | | when model is added to collection association
* Fix conflicts `counter_cache` with `touch: true` by optimistic locking.bogdanvlviv2017-12-121-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ``` # create_table :posts do |t| # t.integer :comments_count, default: 0 # t.integer :lock_version # t.timestamps # end class Post < ApplicationRecord end # create_table :comments do |t| # t.belongs_to :post # end class Comment < ApplicationRecord belongs_to :post, touch: true, counter_cache: true end ``` Before: ``` post = Post.create! # => begin transaction INSERT INTO "posts" ("created_at", "updated_at", "lock_version") VALUES ("2017-12-11 21:27:11.387397", "2017-12-11 21:27:11.387397", 0) commit transaction comment = Comment.create!(post: post) # => begin transaction INSERT INTO "comments" ("post_id") VALUES (1) UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1, "lock_version" = COALESCE("lock_version", 0) + 1 WHERE "posts"."id" = 1 UPDATE "posts" SET "updated_at" = '2017-12-11 21:27:11.398330', "lock_version" = 1 WHERE "posts"."id" = 1 AND "posts"."lock_version" = 0 rollback transaction # => ActiveRecord::StaleObjectError: Attempted to touch a stale object: Post. Comment.take.destroy! # => begin transaction DELETE FROM "comments" WHERE "comments"."id" = 1 UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) - 1, "lock_version" = COALESCE("lock_version", 0) + 1 WHERE "posts"."id" = 1 UPDATE "posts" SET "updated_at" = '2017-12-11 21:42:47.785901', "lock_version" = 1 WHERE "posts"."id" = 1 AND "posts"."lock_version" = 0 rollback transaction # => ActiveRecord::StaleObjectError: Attempted to touch a stale object: Post. ``` After: ``` post = Post.create! # => begin transaction INSERT INTO "posts" ("created_at", "updated_at", "lock_version") VALUES ("2017-12-11 21:27:11.387397", "2017-12-11 21:27:11.387397", 0) commit transaction comment = Comment.create!(post: post) # => begin transaction INSERT INTO "comments" ("post_id") VALUES (1) UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1, "lock_version" = COALESCE("lock_version", 0) + 1, "updated_at" = '2017-12-11 21:37:09.802642' WHERE "posts"."id" = 1 commit transaction comment.destroy! # => begin transaction DELETE FROM "comments" WHERE "comments"."id" = 1 UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) - 1, "lock_version" = COALESCE("lock_version", 0) + 1, "updated_at" = '2017-12-11 21:39:02.685520' WHERE "posts"."id" = 1 commit transaction ``` Fixes #31199.
* Fix broken doc for Active Record [ci skip]Yoshiyuki Hirano2017-08-251-1/+1
|
* Use frozen-string-literal in ActiveRecordKir Shatrov2017-07-191-0/+2
|
* Revert "Merge pull request #29540 from kirs/rubocop-frozen-string"Matthew Draper2017-07-021-1/+0
| | | | | This reverts commit 3420a14590c0e6915d8b6c242887f74adb4120f9, reversing changes made to afb66a5a598ce4ac74ad84b125a5abf046dcf5aa.
* Enforce frozen string in RubocopKir Shatrov2017-07-011-0/+1
|
* Evaluate belongs_to :default option against the owner, not the associationGeorge Claghorn2017-04-271-1/+1
|
* Evaluate the default block only when necessaryRyuta Kamizono2017-03-201-2/+2
| | | | Follow up of #28453.
* Add :default option to belongs_to (#28453)George Claghorn2017-03-171-0/+4
| | | | | | | | | | | Use it to specify that an association should be initialized with a particular record before validation. For example: # Before belongs_to :account before_validation -> { self.account ||= Current.account } # After belongs_to :account, default: -> { Current.account }
* applies remaining conventions across the projectXavier Noria2016-08-061-1/+0
|
* Fix counter_cache double increment bugTom Kadwill2016-04-281-0/+1
|
* Make #increment! and #decrement! methods concurency safeBogdan Gusiev2015-10-051-27/+19
|
* raise ActiveModel::MissingAttributeError when trying to access a ↵Diego Carrion2015-06-161-1/+1
| | | | | | | | relationship without the foreign key attribute fixes regression reported on #20253 ActiveRecord::Base#[] was not used cause of 8b95420
* Improve consistency of counter caches updating in memorySean Griffin2015-01-261-0/+3
| | | | | | | | | | | | | | | | | When we made sure that the counter gets updated in memory, we only did it on the has many side. The has many side only does the update if the belongs to cannot. The belongs to side was updated to update the counter cache (if it is able). This means that we need to check if the belongs_to is able to update in memory on the has_many side. We also found an inconsistency where the reflection names were used to grab the association which should update the counter cache. Since reflection names are now strings, this means it was using a different instance than the one which would have the inverse instance set. Fixes #18689 [Sean Griffin & anthonynavarre]
* Improve the performance of reading belongs_to associationsSean Griffin2014-12-221-5/+6
| | | | | | | | | | | | `ActiveRecord::Base#[]` has overhead that was introduced in 4.2. The `foo["id"]` working with PKs other than ID isn't really a case that we want to support publicly, but deprecating was painful enough that we avoid it. `_read_attribute` was introduced as the faster alternative for use internally. By using that, we can save a lot of overhead. We also save some overhead by reading the attribute one fewer times in `stale_state`. Fixes #18151
* add has_one? method and reuse instead of checking macroeileencodes2014-06-091-1/+1
| | | | | | Instead of checking for `macro == :has_one` throughout the codebase we can create a `has_one?` method to match the `belongs_to?`, `polymorphic?` and other methods.
* Hide BelongsToAssociation#increment_counters and #decrement_countersJean Boussier2014-04-151-2/+2
|
* Use inheritance chain instead of callbacks to increment counter caches after ↵Jean Boussier2014-04-141-4/+14
| | | | create
* extract cache counter logic to one methodAaron Patterson2013-12-121-11/+10
|
* remove duplicate codeAaron Patterson2013-12-121-15/+6
|
* extract a method for updating without a record objectAaron Patterson2013-12-121-6/+10
|
* extract methods out of the cache update methodAaron Patterson2013-12-121-14/+22
|
* pull a nil check up one frameAaron Patterson2013-12-121-6/+10
|
* remove more nil checksAaron Patterson2013-12-121-6/+5
|
* remove nil checkAaron Patterson2013-12-121-6/+10
| | | | | calling replace_keys could possibly do a nil check twice, this commit reduces it to once.
* remove the nil check from set_inverse_instanceAaron Patterson2013-12-121-1/+1
| | | | | methods that call set_inverse_instance with a record will not have to pay the cost of a nil check on every call
* Remove useless comment and white spaces :scissors: [ci skip]Carlos Antonio da Silva2013-09-011-2/+2
|
* Adding a bang to method name of raise_on_type_mismatch.wangjohn2013-03-211-1/+1
|
* BELONGS TO ASSOCIATION | Typo fixlibin2013-02-251-1/+1
|
* improved different_target conditionsAngelo Capilleri2013-01-081-2/+5
|
* move dependency logic out of generated methodsJon Leighton2012-08-101-0/+5
|
* @stale_state should be nil when a model isn't saved.kennyj2012-04-131-1/+1
|
* Some refactor for association.kennyj2012-04-121-0/+5
| | | | | | | * Remove unused association_class method. * Remove a unnecessary assignment. * Move @updated to BelongsToAssociation that only reference this instance variable. * Reset @stale_state at the reset method. I think this place is right place.
* Fix belongs_to polymorphic with custom primary key on target.Jon Leighton2011-09-261-1/+5
| | | | Closes #3104.
* Don't find belongs_to target when the foreign_key is NULL. Fixes #2828Georg Friedrich2011-09-051-0/+4
|
* Fix exception if old and new targets are both nil. Fixes #1471.Jon Leighton2011-07-121-1/+1
|
* Rename target_klass to klassJon Leighton2011-02-211-1/+1
|
* Delegate Association#options to the reflection, and replace ↵Jon Leighton2011-02-211-1/+1
| | | | 'reflection.options' with 'options'. Also add through_options and source_options methods for through associations.
* Singular associations no longer use a proxy, so no need to check for the ↵Jon Leighton2011-02-211-1/+1
| | | | proxy type on assignment.