mirror of https://github.com/rails/rails
Allow unscoping of preload and eager_load associations
Adds the ability to unscope preload and eager_load associations. This is the same functionality as `unscope(:includes)` which may chose to use eager_loading or preloading based on the overall query complexity. In cases where the type of association loading is explicit (eager_load and preload), this allows for unscoping the explicit association loading. This is helpful when taking an existing query and performing an aggregate when has_many associations have explicitly asked for eager_load or preload. In the example below, unscoping the two has_many associations removes the extra preload query and eager_load join. query.eager_load!(:has_many_association1) query.preload!(:has_many_association2) query.unscope(:eager_load, :preload).group(:id).select(:id) There are also cases where depending on the aggregation and select the explict preload fails when the select does not include the preload association key. This issue led me to write this fix.
This commit is contained in:
parent
aab04ec39c
commit
e2c720fbb8
|
@ -1,3 +1,15 @@
|
|||
* Allow unscoping of preload and eager_load associations
|
||||
|
||||
Added the ability to unscope preload and eager_load associations just like
|
||||
includes, joins, etc. See ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES
|
||||
for the full list of supported unscopable scopes.
|
||||
|
||||
```ruby
|
||||
query.unscope(:eager_load, :preload).group(:id).select(:id)
|
||||
```
|
||||
|
||||
*David Morehouse*
|
||||
|
||||
* Clear locking column on #dup
|
||||
|
||||
This change fixes not to duplicate locking_column like id and timestamps.
|
||||
|
|
|
@ -569,7 +569,8 @@ module ActiveRecord
|
|||
|
||||
VALID_UNSCOPING_VALUES = Set.new([:where, :select, :group, :order, :lock,
|
||||
:limit, :offset, :joins, :left_outer_joins, :annotate,
|
||||
:includes, :from, :readonly, :having, :optimizer_hints])
|
||||
:includes, :eager_load, :preload, :from, :readonly,
|
||||
:having, :optimizer_hints])
|
||||
|
||||
# Removes an unwanted relation that is already defined on a chain of relations.
|
||||
# This is useful when passing around chains of relations and would like to
|
||||
|
|
|
@ -402,6 +402,20 @@ class DefaultScopingTest < ActiveRecord::TestCase
|
|||
assert_equal expected, received
|
||||
end
|
||||
|
||||
def test_unscope_eager_load
|
||||
expected = Developer.all.collect(&:name)
|
||||
received = Developer.eager_load(:projects).select(:id).unscope(:eager_load, :select)
|
||||
assert_equal expected, received.collect(&:name)
|
||||
assert_equal false, received.first.projects.loaded?
|
||||
end
|
||||
|
||||
def test_unscope_preloads
|
||||
expected = Developer.all.collect(&:name)
|
||||
received = Developer.preload(:projects).select(:id).unscope(:preload, :select)
|
||||
assert_equal expected, received.collect(&:name)
|
||||
assert_equal false, received.first.projects.loaded?
|
||||
end
|
||||
|
||||
def test_unscope_having
|
||||
expected = DeveloperOrderedBySalary.all.collect(&:name)
|
||||
received = DeveloperOrderedBySalary.having("name IN ('Jamis', 'David')").unscope(:having).collect(&:name)
|
||||
|
|
Loading…
Reference in New Issue