diff --git a/lib/mongoid/paranoia.rb b/lib/mongoid/paranoia.rb index 2f8703c..279d714 100644 --- a/lib/mongoid/paranoia.rb +++ b/lib/mongoid/paranoia.rb @@ -46,6 +46,12 @@ def configure default_scope -> { where(deleted_at: nil) } scope :deleted, -> { ne(deleted_at: nil) } + scope :with_deleted, lambda { + msg = 'This scope requires Mongoid >= 9 and allow_scopes_to_unset_default_scope to be set to true' + raise msg unless Mongoid.try(:allow_scopes_to_unset_default_scope) + + criteria.remove_scoping(unscoped.where(deleted_at: nil)) + } define_model_callbacks :restore define_model_callbacks :remove end @@ -77,7 +83,7 @@ def persisted? # @since 1.0.0 alias orig_delete delete - def remove(_ = {}) + def remove(_ = {}) # rubocop:disable Naming/PredicateMethod time = self.deleted_at = Time.now _paranoia_update('$set' => { paranoid_field => time }) @destroyed = true diff --git a/perf/scope.rb b/perf/scope.rb index 60c4023..2e7a7f6 100644 --- a/perf/scope.rb +++ b/perf/scope.rb @@ -11,6 +11,7 @@ class Model include Mongoid::Document + field :text, type: String index({ text: 'text' }) @@ -19,6 +20,7 @@ class Model class ParanoidModel include Mongoid::Document include Mongoid::Paranoia + field :text, type: String index({ text: 'text' }) @@ -26,6 +28,7 @@ class ParanoidModel class MetaParanoidModel include Mongoid::Document + field :text, type: String field :deleted_at, type: Time default_scope -> { where(deleted_at: nil) } diff --git a/spec/mongoid/paranoia_spec.rb b/spec/mongoid/paranoia_spec.rb index c83499b..f8a5003 100644 --- a/spec/mongoid/paranoia_spec.rb +++ b/spec/mongoid/paranoia_spec.rb @@ -98,6 +98,36 @@ class ParanoidConfiguredReset end end + describe ".with_deleted" do + + let(:posts) do + 2.times.map { |i| ParanoidPost.create(title: "testing #{i}") } + end + + around do |example| + skip unless Mongoid.respond_to?(:allow_scopes_to_unset_default_scope=) + + original_value = Mongoid.allow_scopes_to_unset_default_scope + Mongoid.configure { |config| config.allow_scopes_to_unset_default_scope = true } + + example.run + + Mongoid.configure { |config| config.allow_scopes_to_unset_default_scope = original_value } + end + + before do + posts.first.destroy + end + + let(:with_deleted) do + ParanoidPost.with_deleted + end + + it "returns the deleted documents" do + expect(with_deleted).to eq(posts) + end + end + describe "#destroy!" do context "when the document is a root" do diff --git a/spec/mongoid/scoping_spec.rb b/spec/mongoid/scoping_spec.rb index ccf29d9..2b27b04 100644 --- a/spec/mongoid/scoping_spec.rb +++ b/spec/mongoid/scoping_spec.rb @@ -51,5 +51,31 @@ expect(criteria.selector).to eq({ "fresh" => true }) end end + + context "when chaining with_deleted" do + + let(:criteria) do + Fish.fresh.with_deleted + end + + if Mongoid.respond_to?(:allow_scopes_to_unset_default_scope=) + around do |example| + original_value = Mongoid.allow_scopes_to_unset_default_scope + Mongoid.configure { |config| config.allow_scopes_to_unset_default_scope = true } + + example.run + + Mongoid.configure { |config| config.allow_scopes_to_unset_default_scope = original_value } + end + + it "removes only deleted_at from the selector" do + expect(criteria.selector).to eq({ "fresh" => true }) + end + else + it "raises an error if the feature is not supported" do + expect { criteria.selector }.to raise_error(/requires Mongoid >= 9/) + end + end + end end end