mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Make CollectionAssociation first/last with integer fetch with query
When first or last is called with an integer on an unloaded association, the entire collection is loaded. This differs surprisingly from the behavior of Relation#first/last, which translate the call into a limit query. For large collections this can make a big difference in performance. Change CollectionAssociation#fetch_first_or_last_using_find? to make this kind of call delegate to Relation.
This commit is contained in:
parent
c27fde2616
commit
8875e28a50
3 changed files with 11 additions and 6 deletions
|
@ -1,3 +1,8 @@
|
|||
* `CollectionAssociation#first`/`#last` (e.g. `has_many`) use a `LIMIT`ed
|
||||
query to fetch results rather than loading the entire collection.
|
||||
|
||||
*Lann Martin*
|
||||
|
||||
* Re-use `order` argument pre-processing for `reorder`.
|
||||
|
||||
*Paul Nikitochkin*
|
||||
|
|
|
@ -528,15 +528,13 @@ module ActiveRecord
|
|||
# * target already loaded
|
||||
# * owner is new record
|
||||
# * target contains new or changed record(s)
|
||||
# * the first arg is an integer (which indicates the number of records to be returned)
|
||||
def fetch_first_or_last_using_find?(args)
|
||||
if args.first.is_a?(Hash)
|
||||
true
|
||||
else
|
||||
!(loaded? ||
|
||||
owner.new_record? ||
|
||||
target.any? { |record| record.new_record? || record.changed? } ||
|
||||
args.first.kind_of?(Integer))
|
||||
target.any? { |record| record.new_record? || record.changed? })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1414,15 +1414,17 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_calling_first_or_last_with_integer_on_association_should_load_association
|
||||
def test_calling_first_or_last_with_integer_on_association_should_not_load_association
|
||||
firm = companies(:first_firm)
|
||||
firm.clients.create(:name => 'Foo')
|
||||
assert !firm.clients.loaded?
|
||||
|
||||
assert_queries 1 do
|
||||
assert_queries 2 do
|
||||
firm.clients.first(2)
|
||||
firm.clients.last(2)
|
||||
end
|
||||
|
||||
assert firm.clients.loaded?
|
||||
assert !firm.clients.loaded?
|
||||
end
|
||||
|
||||
def test_calling_many_should_count_instead_of_loading_association
|
||||
|
|
Loading…
Reference in a new issue