Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Make CollectionAssociation first/last with integer fetch with query #12137

Merged
merged 1 commit into from

3 participants

@lann

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.

@robin850
Collaborator

Thanks for your contribution! Could you please add a changelog entry ?

@lann lann 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.
8875e28
@lann

@robin850 Changelog updated.

@rafaelfranca rafaelfranca merged commit 8875e28 into from
@rafaelfranca

Make sense. Thanks

@lann lann deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 9, 2013
  1. @lann

    Make CollectionAssociation first/last with integer fetch with query

    lann authored lann committed
    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 page is out of date. Refresh to see the latest.
View
5 activerecord/CHANGELOG.md
@@ -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*
View
4 activerecord/lib/active_record/associations/collection_association.rb
@@ -528,15 +528,13 @@ def callbacks_for(callback_name)
# * 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
View
8 activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1414,15 +1414,17 @@ def test_blank_custom_primary_key_on_new_record_should_not_run_queries
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
Something went wrong with that request. Please try again.