aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/builder/belongs_to.rb
Commit message (Collapse)AuthorAgeFilesLines
* Fix conflicts `counter_cache` with `touch: true` by optimistic locking.bogdanvlviv2017-12-121-3/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ``` # 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.
* Merge pull request #29765 from lugray/fix_counter_cacheRafael França2017-07-241-3/+1
|\ | | | | Fix `counter_cache` double increment
| * Add test for fixed `counter_cache` double incrementLisa Ugray2017-07-191-3/+1
| | | | | | | | | | | | | | | | | | | | | | When an `after_create` callback did `update_attributes` on a record with multiple `belongs_to` associations with counter caches, even numbered associations would have their counters double-incremented. Fixes to `ActiveModel::Dirty` in 020abad fixed this. This adds regression tests for this bug fixed incidentally in the other commit, which also removed the need for the workaround using @_after_create_counter_called.
* | 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 the default block only when necessaryRyuta Kamizono2017-03-201-1/+1
| | | | Follow up of #28453.
* Add :default option to belongs_to (#28453)George Claghorn2017-03-171-1/+8
| | | | | | | | | | | 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 }
* Deprecate the behavior of AR::Dirty inside of after_(create|update|save) ↵Sean Griffin2016-11-011-14/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | callbacks We pretty frequently get bug reports that "dirty is broken inside of after callbacks". Intuitively they are correct. You'd expect `Model.after_save { puts changed? }; model.save` to do the same thing as `model.save; puts model.changed?`, but it does not. However, changing this goes much farther than just making the behavior more intuitive. There are a _ton_ of places inside of AR that can be drastically simplified with this change. Specifically, autosave associations, timestamps, touch, counter cache, and just about anything else in AR that works with callbacks have code to try to avoid "double save" bugs which we will be able to flat out remove with this change. We introduce two new sets of methods, both with names that are meant to be more explicit than dirty. The first set maintains the old behavior, and their names are meant to center that they are about changes that occurred during the save that just happened. They are equivalent to `previous_changes` when called outside of after callbacks, or once the deprecation cycle moves. The second set is the new behavior. Their names imply that they are talking about changes from the database representation. The fact that this is what we really care about became clear when looking at `BelongsTo.touch_record` when tests were failing. I'm unsure that this set of methods should be in the public API. Outside of after callbacks, they are equivalent to the existing methods on dirty. Dirty itself is not deprecated, nor are the methods inside of it. They will only emit the warning when called inside of after callbacks. The scope of this breakage is pretty large, but the migration path is simple. Given how much this can improve our codebase, and considering that it makes our API more intuitive, I think it's worth doing.
* Fix counter_cache double increment bugTom Kadwill2016-04-281-0/+2
|
* Define `:foreign_type` as a valid option in `SingularAssociation`yui-knk2016-01-191-1/+1
| | | | | `:foreign_type` is a valid option for `belongs_to` and `has_one` so remove this to `SingularAssociation`.
* Make sure we touch all the parents when touch_later.Arthur Neves2015-12-061-2/+1
| | | | | | | | | | | | | | | | | | | | The problem was that when saving an object, we would call touch_later on the parent which wont be saved immediteally, and it wont call any callbacks. That was working one level up because we were calling touch, during the touch_later commit phase. However that still didnt solve the problem when you have a 3+ levels of parents to be touched, as calling touch would affect the parent, but it would be too late to run callbacks on its grand-parent. The solution for this, is instead, call touch_later upwards when the first touch_later is called. So we make sure all the timestamps are updated without relying on callbacks. This also removed the hard dependency BelongsTo builder had with the TouchLater module. So we can still have the old behaviour if TouchLater module is not included. [fixes 5f5e6d924973003c105feb711cefdb726f312768] [related #19324]
* Update belongs_to.rbEhsan Yousefi2015-11-081-2/+1
| | | There is no need to to assign reflection name to a variable, because it's called once.
* docs, add missing `:nodoc: for `Associations::Builder`. [ci skip]Yves Senn2015-10-131-1/+1
| | | | | | This class is only used internally. We should keep it out of public documentation. This patch adds nodoc for `ActiveRecord::Associations::Builder` and everything nested within.
* Fix counter_cache for polymorphic associationsStefan Kanev2015-07-191-4/+12
| | | | | | | | | | | | | | Also removes a false positive test that depends on the fixed bug: At this time, counter_cache does not work with polymorphic relationships (which is a bug). The test was added to make sure that no StaleObjectError is raised when the car is destroyed. No such error is currently raised because the lock version is not incremented by appending a wheel to the car. Furthermore, `assert_difference` succeeds because `car.wheels.count` does not check the counter cache, but the collection size. The test will fail if it is replaced with `car.wheels_count || 0`.
* Batch touch parent recordsArthur Neves2015-04-081-6/+7
| | | | | | | | | | [fixes #18606] Make belongs_to use touch over touch_later when running the callbacks. Add more tests and small method rename Thanks Jeremy for the feedback.
* Require `belongs_to` by default.Josef Šimánek2015-02-211-1/+19
| | | | Deprecate `required` option in favor of `optional` for belongs_to.
* Remove support to activerecord-deprecated_findersRafael Mendonça França2015-01-021-4/+2
|
* Merge pull request #12450 from iantropov/masterRafael Mendonça França2014-06-271-0/+5
|\ | | | | | | | | | | | | | | | | Fix bug, when ':dependent => :destroy' violates foreign key constraints Conflicts: activerecord/CHANGELOG.md activerecord/lib/active_record/associations/builder/association.rb activerecord/lib/active_record/associations/builder/has_one.rb
| * Fix bug, when ':dependent => :destroy' option violates foreign key ↵Ivan Antropov2013-10-261-0/+4
| | | | | | | | constraints, issue #12380
* | Prevented belongs_to: touch propagating up if there are no changes being savedBrock Trappitt2014-05-211-1/+1
| |
* | Hide BelongsToAssociation#increment_counters and #decrement_countersJean Boussier2014-04-151-1/+0
| |
* | Use inheritance chain instead of callbacks to increment counter caches after ↵Jean Boussier2014-04-141-16/+0
| | | | | | | | destroy
* | Use inheritance chain instead of callbacks to increment counter caches after ↵Jean Boussier2014-04-141-12/+1
| | | | | | | | create
* | Make counter cache decrementation on destroy idempotentJean Boussier2014-04-131-4/+5
| |
* | On destroying do not touch destroyed belongs to association.Paul Nikitochkin2013-12-231-1/+1
| | | | | | | | Fixes: #13445
* | Revert the whole refactoring in the association builder classes.Rafael Mendonça França2013-12-111-2/+4
| | | | | | | | This is to get activerecord-deprecated_finders work again
* | Bring back the valid_options class accessorRafael Mendonça França2013-12-111-1/+1
| | | | | | | | It is need in activerecord-deprecated_finders
* | polymorphic belongs_to association with touch: true updates old record correctlySeverin Schoepke2013-12-051-1/+7
| | | | | | | | | | | | | | | | | | Example: Given you have a comments model with a polymorphic commentable association (e.g. books and songs) with the touch option set. Every time you update a comment its commentable should be touched. This was working when you changed attributes on the comment or when you moved the comment from one book to another. However, it was not working when moving a comment from a book to a song. This is now fixed.
* | Raise `ArgumentError` when `has_one` is used with `counter_cache`Godfrey Chan2013-11-291-1/+1
| | | | | | | | | | | | | | | | | | Previously, the `has_one` macro incorrectly accepts the `counter_cache` option due to a bug, although that options was never supported nor functional on `has_one` and `has_one ... through` relationships. It now correctly raises an `ArgumentError` when passed that option. For reference, this bug was introduced in 52f8e4b9.
* | Method visibility will not make difference hereRafael Mendonça França2013-10-091-2/+0
| |
* | Move macro to class levelRafael Mendonça França2013-10-091-1/+1
| |
* | Make valid_options a class methodRafael Mendonça França2013-10-091-1/+1
| |
* | Push define_accessors to class level since we don't need anythig fromRafael Mendonça França2013-10-081-2/+2
| | | | | | | | the instance
* | Move add_counter_cache_methods to class levelRafael Mendonça França2013-10-081-2/+2
| |
* | we can define callbacks without a builder instanceAaron Patterson2013-10-021-3/+3
| |
* | push methods that don't depend on the instance to the classAaron Patterson2013-10-021-4/+4
| |
* | decouple belongs_to callback definition from the builder instance.Aaron Patterson2013-10-021-4/+4
| | | | | | | | All the information is on the reflection, so just get it there.
* | valid_options doesn't depend on the instance, so push it to the classAaron Patterson2013-10-021-1/+1
| |
* | association builder is no longer needed for counter cache, so remove itAaron Patterson2013-10-021-7/+6
| |
* | push constructable? on to the reflectionAaron Patterson2013-10-021-6/+2
| |
* | name is on the reflection, so just use the reflectionAaron Patterson2013-10-021-2/+2
|/
* remove dependency on @model when defining callbacksAaron Patterson2013-08-011-5/+5
|
* extract more mutations to the callerAaron Patterson2013-08-011-7/+6
|
* separate some mutations from reflection constructionAaron Patterson2013-08-011-1/+5
|
* #11288: Removed duplicated touchingPaul Nikitochkin2013-07-051-1/+1
| | | | | | if belongs to model with touch option on touch Closes #11288
* stop adding a new method for touch callbacksAaron Patterson2013-06-111-29/+21
|
* push the touch method outside the evalAaron Patterson2013-06-111-13/+34
|
* remove unused variableAaron Patterson2013-06-111-1/+0
|
* check whether the association is constructible rather than checking constantsAaron Patterson2013-06-111-3/+3
|