aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/has_many_association.rb
Commit message (Collapse)AuthorAgeFilesLines
* Revert "Merge pull request #35127 from bogdan/counter-cache-loading"Ryuta Kamizono2019-02-131-9/+5
| | | | | | | | | | | | | 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 #35127 from bogdan/counter-cache-loadingRyuta Kamizono2019-02-051-14/+10
|\ | | | | Bugfix association loading behavior when counter cache is zero
| * Bugfix association loading behavior when counter cache is zeroBogdan Gusiev2019-02-051-14/+10
| |
* | Refs #28025 nullify *_type column on polymorphic associations on :nu… ↵Laerti2019-01-151-1/+1
|/ | | | | | (#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.
* Ensure that `delete_all` on collection proxy returns affected countRyuta Kamizono2018-12-041-0/+1
| | | | | | | Unlike the `Relation#delete_all`, `delete_all` on collection proxy doesn't return affected count. Since the `CollectionProxy` is a subclass of the `Relation`, this inconsistency is probably not intended, so it should return the count consistently.
* Rename union to intersectionFlorian Ebeling2018-11-061-1/+1
|
* Fix handling of duplicates for `replace` on has_many-throughFlorian Ebeling2018-11-061-0/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There was a bug in the handling of duplicates when assigning (replacing) associated records, which made the result dependent on whether a given record was associated already before being assigned anew. E.g. post.people = [person, person] post.people.count # => 2 while post.people = [person] post.people = [person, person] post.people.count # => 1 This change adds a test to provoke the former incorrect behavior, and fixes it. Cause of the bug was the handling of record collections as sets, and using `-` (difference) and `&` (union) operations on them indiscriminately. This temporary conversion to sets would eliminate duplicates. The fix is to decorate record collections for these operations, and only for the `has_many :through` case. It is done by counting occurrences, and use the record together with the occurrence number as element, in order to make them work well in sets. Given a, b = *Person.all then the collection used for finding the difference or union of records would be internally changed from [a, b, a] to [[a, 1], [b, 1], [a, 2]] for these operations. So a first occurrence and a second occurrence would be distinguishable, which is all that is necessary for this task. Fixes #33942.
* Merge pull request #27561 from fishbrain/count-all-in-has-many-associationRyuta Kamizono2018-01-031-1/+1
|\ | | | | | | Use `count(:all)` in HasManyAssociation#count_records
| * Use `count(:all)` in HasManyAssociation#count_recordsKlas Eskilson2017-02-071-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | Problem: Calling `count` on an association can cause invalid SQL queries to be created where the `SELECT COUNT(a, b, c)` function receives multiple columns. This will cause a `StatementInvalid` exception later on. Solution: Use `count(:all)`, which generates a `SELECT COUNT(*)...` query independently of the association. This also includes a test case that, before the fix, broke.
* | 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
| |
* | Prevent double firing the before save callback of new object when the parent ↵Ryuta Kamizono2017-04-211-6/+1
|/ | | | | | | | | | | | | | | | | | association saved in the callback Related #18155, #26661, 268a5bb, #27434, #27442, and #28599. Originally #18155 was introduced for preventing double insertion caused by the after save callback. But it was caused the before save issue (#26661). 268a5bb fixed #26661, but it was caused the performance regression (#27434). #27442 added new record to `target` before calling callbacks for fixing #27434. But it was caused double firing before save callback (#28599). We cannot add new object to `target` before saving the object. This is improving #18155 to only track callbacks after `save`. Fixes #28599.
* `self.` is not needed when calling its own instance methodAkira Matsuda2017-01-051-1/+1
| | | | Actually, private methods cannot be called with `self.`, so it's not just redundant, it's a bad habit in Ruby
* Merge pull request #26352 from kamipo/avoid_to_call_set_inverse_instance_twiceArthur Nogueira Neves2017-01-031-1/+0
|\ | | | | Avoid to call `set_inverse_instance` twice for `has_many` association
| * Avoid to call `set_inverse_instance` twice for `has_many` associationRyuta Kamizono2016-12-281-1/+0
| | | | | | | | | | `create`, `create!`, and `concat` in `has_many` association hits `set_inverse_instance` twice. It is enough to hit only once.
* | Remove deprecated i18n scopes in Active RecordRafael Mendonça França2016-12-291-8/+1
|/
* Fixes TypeError Exception when cache counter value equals nil (#26940)Daniel E. Garcia Shulman2016-11-021-1/+1
| | | | | | * Fixes TypeError when cache counter value equals nil * Test case for counter cache on unloaded has_many association
* fixes remaining RuboCop issues [Vipul A M, Xavier Noria]Xavier Noria2016-09-011-1/+1
|
* modernizes hash syntax in activerecordXavier Noria2016-08-061-2/+2
|
* Fixed unnecessary nesting in handle_dependencyHerman Hiddema2016-07-041-7/+5
| | | | | This nested if checked the same value as the containing case statement. Moved the code in the if/else into when/else in the containing case.
* Make #increment! and #decrement! methods concurency safeBogdan Gusiev2015-10-051-8/+2
|
* Clean up the implementation of AR::DirtySean Griffin2015-09-241-1/+1
| | | | | | | | | | | | | This moves a bit more of the logic required for dirty checking into the attribute objects. I had hoped to remove the `with_value_from_database` stuff, but unfortunately just calling `dup` on the attribute objects isn't enough, since the values might contain deeply nested data structures. I think this can be cleaned up further. This makes most dirty checking become lazy, and reduces the number of object allocations and amount of CPU time when assigning a value. This opens the door (but doesn't quite finish) to improving the performance of writes to a place comparable to 4.1
* `restrict_with_error` message will now respect owner’s human name in any ↵Ronak Jangir2015-09-121-1/+1
| | | | locale [kuboon & Ronak Jangir]
* HasManyAssociation: moved half of counter cache code to reflectionBogdan Gusiev2015-09-031-60/+9
| | | | | | | | | | | | | | | | | | Current implementation has a lot of utility methods that accept reflection call a lot of methods on it and exit. E.g. has_counter_cache?(reflection) It causes confusion and inability to cache result of the method even through it always returns the same result for the same reflection object. It can be done easier without access to the association context by moving code into reflection itself. e.g. reflection.has_counter_cache? Reflection is less complex object than association so moving code there automatically makes it simplier to understand.
* Merge pull request #19683 from tristang/require-option-for-counter-cacheRafael Mendonça França2015-08-131-1/+8
|\ | | | | | | Require explicit counter_cache option for has_many
| * Require explicit counter_cache option for has_manyTristan Gamilis2015-04-071-1/+8
| | | | | | | | | | | | | | | | | | | | Previously has_many associations assumed a counter_cache was to be used based on the presence of an appropriately named column. This is inconsistent, since the inverse belongs_to association will not make this assumption. See issues #19042 #8446. This commit checks for the presence of the counter_cache key in the options of either the has_many or belongs_to association as well as ensuring that the *_count column is present.
* | Deprecate and rename the keys for association restrict_dependent_destroyRoque Pinel2015-07-201-1/+8
|/ | | | | | | | | | | | | | | | | Previously `has_one` and `has_many` associations were using the `one` and `many` keys respectively. Both of these keys have special meaning in I18n (they are considered to be pluralizations) so by renaming them to `has_one` and `has_many` we make the messages more explicit and most importantly they don't clash with linguistical systems that need to validate translation keys (and their pluralizations). The `:'restrict_dependent_destroy.one'` key should be replaced with `:'restrict_dependent_destroy.has_one'`, and `:'restrict_dependent_destroy.many'` with `:'restrict_dependent_destroy.has_many'`. [Roque Pinel & Christopher Dell]
* Correct errors in counter cache updatingSean Griffin2015-02-031-1/+5
| | | | | | | | | | | The cache name should be converted to a string when given, not compared as a symbol. This edge case is already adequately covered by our tests, but was masked by another issue where we were incorrectly updating the counter cache twice. When paired with a bug where we didn't update the counter cache because we couldn't find a match with the name, this made it look like everything was working fine. Fixes #10865.
* Improve consistency of counter caches updating in memorySean Griffin2015-01-261-5/+15
| | | | | | | | | | | | | | | | | 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]
* Deprecate `false` as the way to halt AR callbacksclaudiob2015-01-021-1/+1
| | | | | | | | | | Before this commit, returning `false` in an ActiveRecord `before_` callback such as `before_create` would halt the callback chain. After this commit, the behavior is deprecated: will still work until the next release of Rails but will also display a deprecation warning. The preferred way to halt a callback chain is to explicitly `throw(:abort)`.
* Share foreign_key_present? implementation in _has_ associationsbrainopia2014-12-311-8/+1
|
* Improve the performance of reading attributesSean Griffin2014-11-181-1/+1
| | | | | | | We added a comparison to "id", and call to `self.class.primary_key` a *lot*. We also have performance hits from `&block` all over the place. We skip the check in a new method, in order to avoid breaking the behavior of `read_attribute`
* Don't expose these new APIs yet (added in 877ea78 / #16189)Godfrey Chan2014-08-161-1/+1
| | | | | | | WARNING: don't use them! They might change or go away between future beta/RC/ patch releases! Also added a CHANGELOG entry for this.
* Implement `_was` and `changes` for in-place mutations of AR attributesSean Griffin2014-08-161-1/+1
|
* Redefine macro checks for reflectionseileencodes2014-07-301-1/+1
| | | | | | | | | | | | | | Now that we define the macro on the reflection type we no longer need to check `macro == :what` on each type for `belongs_to?` or `has_one?` etc. These now default to false unless it's defined in the reflection class. Reuse existing belongs_to? method to check macros We don't need to do `:belongs_to == macro` anymore becasue we have a `belongs_to?` method. I didn't find this being used anywhere for `has_one?` or `collection?` since they were already fixed.
* Merge pull request #15266 from dv/use_counter_cache_for_empty_callGodfrey Chan2014-07-151-0/+8
|\ | | | | If a counter_cache exists, use it for #empty?
| * If a counter_cache exists, use it for #empty?David Verhasselt2014-06-101-0/+8
| |
* | Deprecate automatic counter caches on has_many :throughSean Griffin2014-06-261-1/+9
| | | | | | | | | | | | | | | | | | | | | | Reliant on https://github.com/rails/rails/pull/15747 but pulled to a separate PR to reduce noise. `has_many :through` associations have the undocumented behavior of automatically detecting counter caches. However, the way in which it does so is inconsistent with counter caches everywhere else, and doesn't actually work consistently. As with normal `has_many` associations, the user should specify the counter cache on the `belongs_to`, if they'd like it updated.
* | Always update counter caches in memory when adding recordsSean Griffin2014-06-161-0/+26
|/ | | | | | | | | | | Before, calling `size` would only work if it skipped the cache, and would return a different result from the cache, but only if: - The association was previously loaded - Or you called size previously - But only if the size was 0 when you called it This ensures that the counter is appropriately updated in memory.
* Merge pull request #15210 from arthurnn/fix_hbtm_reflectionArthur Neves2014-05-241-1/+2
| | | | | | | | | Fix habtm reflection Conflicts: activerecord/CHANGELOG.md activerecord/lib/active_record/counter_cache.rb activerecord/lib/active_record/reflection.rb activerecord/test/cases/reflection_test.rb
* remove count vareileencodes2014-05-131-4/+2
| | | | this change was unneccsary as nothing was gained from it
* rename delete_all_records to delete_or_nullify_all_recordseileencodes2014-05-131-1/+1
| | | | | | | Rename delete_all_records because this name better describes what the method is doing. We can then remove :all from the hm:t version and pull out the unoptimized call to load_target in delete_records and pass it directly.
* remove need for :all symboleileencodes2014-05-131-13/+6
| | | | | | Refactor delete_count method to only handle delete_all or nullify/nil cases and not destroy and switch to if/else rather than case statement. This refactoring allows removal of :all symbol usage.
* begin refactoring delete_records methodeileencodes2014-05-131-12/+25
| | | | | | | | | | | | | | Refactor by creating two methods delete_all_records and delete_records to be called by delete_all and delete (or destroy) respectively. This reduces the number of conditionals required to handle _how_ records get deleted. The new delete_count method handles how scope is applied to which delete action. A delete_all_records method also has to be called in has_many_through association because of how the methods are chained. This will be refactored later on.
* read_attribute is public, so we should just call itAaron Patterson2014-04-131-1/+1
|
* make tests pass on Ruby 2.2Aaron Patterson2014-03-131-4/+4
| | | | | | Apparently we've been using a buggy feature for the past 6 years: https://bugs.ruby-lang.org/issues/9593
* fix HABTM w/out primary key errors on destructionKevin Casey2014-02-021-1/+1
|
* Raise `RecordNotDestroyed` when children can't be replacedBrian Thomas Storti2013-11-251-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | Fixes #12812 Raise `ActiveRecord::RecordNotDestroyed` when a child marked with `dependent: destroy` can't be destroyed. The following code: ```ruby class Post < ActiveRecord::Base has_many :comments, dependent: :destroy end class Comment < ActiveRecord::Base before_destroy do return false end end post = Post.create!(comments: [Comment.create!]) post.comments = [Comment.create!] ```` would result in a `post` with two `comments`. With this commit, the same code would raise a `RecordNotDestroyed` exception, keeping the `post` with the same `comment`.