Skip to content

Commit bdef211

Browse files
p-mongop
andauthored
MONGOID-5186 .with_scope should restore previous scope (#5127)
Co-authored-by: Oleg Pudeyev <code@olegp.name>
1 parent 7ad439b commit bdef211

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

docs/reference/queries.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,6 +1577,7 @@ To have Mongoid raise an error when a scope would overwrite an existing class
15771577
method, set the ``scope_overwrite_exception`` :ref:`configuration option
15781578
<configuration-options>` to ``true``.
15791579

1580+
15801581
Default Scopes
15811582
--------------
15821583

@@ -1705,6 +1706,35 @@ that would affect its visibility within the scoped association.
17051706
label.reload.bands # []
17061707

17071708

1709+
Runtime Default Scope Override
1710+
------------------------------
1711+
1712+
You can use the ``with_scope`` method to change the default scope in a block
1713+
at runtime:
1714+
1715+
.. code-block:: ruby
1716+
1717+
class Band
1718+
include Mongoid::Document
1719+
field :country, type: String
1720+
field :genres, type: Array
1721+
1722+
scope :english, ->{ where(country: "England") }
1723+
end
1724+
1725+
criteria = Band.with_scope(Band.english) do
1726+
Band.all
1727+
end
1728+
1729+
criteria
1730+
# =>
1731+
# #<Mongoid::Criteria
1732+
# selector: {"country"=>"England"}
1733+
# options: {}
1734+
# class: Band
1735+
# embedded: false>
1736+
1737+
17081738
Class Methods
17091739
-------------
17101740

lib/mongoid/scopable.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,12 @@ def with_default_scope
203203
#
204204
# @return [ Criteria ] The yielded criteria.
205205
def with_scope(criteria)
206+
previous = Threaded.current_scope(self)
206207
Threaded.set_current_scope(criteria, self)
207208
begin
208209
yield criteria
209210
ensure
210-
Threaded.set_current_scope(nil, self)
211+
Threaded.set_current_scope(previous, self)
211212
end
212213
end
213214

spec/mongoid/scopable_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,26 @@ class << Band
11261126
expect(Mongoid::Threaded.current_scope(Band)).to be_nil
11271127
end
11281128
end
1129+
1130+
context 'when nesting with_scope calls' do
1131+
let(:c1) { Band.where(active: true) }
1132+
let(:c2) { Band.where(active: false) }
1133+
1134+
it 'restores previous scope' do
1135+
Band.with_scope(c1) do |crit|
1136+
Band.with_scope(c2) do |crit2|
1137+
Mongoid::Threaded.current_scope(Band).selector.should == {
1138+
'active' => true,
1139+
'$and' => ['active' => false],
1140+
}
1141+
end
1142+
1143+
Mongoid::Threaded.current_scope(Band).selector.should == {
1144+
'active' => true,
1145+
}
1146+
end
1147+
end
1148+
end
11291149
end
11301150

11311151
describe ".without_default_scope" do

0 commit comments

Comments
 (0)