mongoid_paranoia 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43d1da1cdc376721364043d5031170e7958fffcb759f9c0e64990a51ba0f5480
4
- data.tar.gz: b5d1105826ee2edfa11a1b1432230200986ddb8d55b844dc80487c27ccb7cc48
3
+ metadata.gz: 1a91dadeb276e443e5060c0365961ca55f0a64e52dc6d98ec9d1f8c27323e4c9
4
+ data.tar.gz: 71acb61e9ac0c78c37b9e70c9985bcfbbd778364b0e4394ae087dbfc3c260955
5
5
  SHA512:
6
- metadata.gz: 306b10fc581eb21195661f6303bf76316854c1cfb5be09c33443b51b4fa865851d4b4c819b7402d7e269684358f62773adbaca4003c7c0b87ef856a9ddcb608e
7
- data.tar.gz: 1466019a022ce6a6a419d49794ba6c9a00121183dacbe982519174e2b6cf155261e44245bff87711e6333f42cc0a86352dbe4f4ef180f86a3cd8717073c54b6b
6
+ metadata.gz: 3c1516b87ec542acbd708b0d5aca3a372b2cdc16123df093223d2159eb8b4a8c2c13720b4bd8492ada399e58308a49e5ba1895273fb18bac2bd784978e4f282c
7
+ data.tar.gz: 71eb2a17add46c46f97f6b5fab35907765c6ba1e97ebc24016e0314feee8d0bf9ac0964e3e45910d260ea3b1abb4e9492ac4928181a6307772347f919f16a463
data/LICENSE CHANGED
@@ -1,22 +1,22 @@
1
- Copyright (c) 2013 Josef Šimánek
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1
+ Copyright (c) 2013 Josef Šimánek
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
22
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,117 +1,117 @@
1
- # Paranoid Documents for Mongoid
2
- [![Build Status](https://travis-ci.org/simi/mongoid_paranoia.svg?branch=master)](https://travis-ci.org/simi/mongoid_paranoia) [![Gem Version](https://img.shields.io/gem/v/mongoid_paranoia.svg)](https://rubygems.org/gems/mongoid_paranoia) [![Gitter chat](https://badges.gitter.im/simi/mongoid_paranoia.svg)](https://gitter.im/simi/mongoid_paranoia)
3
-
4
- `Mongoid::Paranoia` enables a "soft delete" of Mongoid documents. Instead of being removed from the database, paranoid docs are flagged with a `deleted_at` timestamp and are ignored from queries by default.
5
-
6
- The `Mongoid::Paranoia` functionality was originally supported in Mongoid itself, but was dropped from version 4.0.0 onwards. This gem was extracted from the [Mongoid 3.0.0-stable branch](https://github.com/mongoid/mongoid/tree/3.0.0-stable). This gem should not be used with Mongoid versions 3.x and prior. Current master branch targeted on Mongoid 6.0. With release 0.3.0 Mongoid 4 and 5 versions will be dropped.
7
-
8
- **Caution:** This repo/gem `mongoid_paranoia` (underscored) is different than [mongoid-paranoia](https://github.com/haihappen/mongoid-paranoia) (hyphenated). The goal of `mongoid-paranoia` (hyphenated) is to stay API compatible and it only accepts security fixes.
9
-
10
- ## Installation
11
-
12
- Add this line to your application's Gemfile:
13
-
14
- ```ruby
15
- gem 'mongoid_paranoia'
16
- ```
17
-
18
- ## Usage
19
-
20
- ```ruby
21
- class Person
22
- include Mongoid::Document
23
- include Mongoid::Paranoia
24
- end
25
-
26
- person.delete # Sets the deleted_at field to the current time, ignoring callbacks.
27
- person.delete! # Permanently deletes the document, ignoring callbacks.
28
- person.destroy # Sets the deleted_at field to the current time, firing callbacks.
29
- person.destroy! # Permanently deletes the document, firing callbacks.
30
- person.restore # Brings the "deleted" document back to life.
31
- person.restore(:recursive => true) # Brings "deleted" associated documents back to life recursively
32
- ```
33
-
34
- The documents that have been "flagged" as deleted (soft deleted) can be accessed at any time by calling the deleted class method on the class.
35
-
36
- ```ruby
37
- Person.deleted # Returns documents that have been "flagged" as deleted.
38
- ```
39
-
40
- You can also access all documents (both deleted and non-deleted) at any time by using the `unscoped` class method:
41
-
42
- ```ruby
43
- Person.unscoped.all # Returns all documents, both deleted and non-deleted
44
- ```
45
-
46
- You can also configure the paranoid field naming on a global basis. Within the context of a Rails app this is done via an initializer.
47
-
48
- ```ruby
49
- # config/initializers/mongoid_paranoid.rb
50
-
51
- Mongoid::Paranoia.configure do |c|
52
- c.paranoid_field = :myFieldName
53
- end
54
- ```
55
-
56
- ### Validations
57
- #### You need override uniqueness validates
58
-
59
- ```ruby
60
- validates :title, uniqueness: { conditions: -> { where(deleted_at: nil) } }
61
- ```
62
-
63
- ### Callbacks
64
-
65
- #### Restore
66
- `before_restore`, `after_restore` and `around_restore` callbacks are added to your model. They work similarly to the `before_destroy`, `after_destroy` and `around_destroy` callbacks.
67
-
68
- #### Remove
69
- `before_remove`, `after_remove` and `around_remove` are added to your model. They are called when record is deleted permanently .
70
-
71
- #### Example
72
- ```ruby
73
- class User
74
- include Mongoid::Document
75
- include Mongoid::Paranoia
76
-
77
- before_restore :before_restore_action
78
- after_restore :after_restore_action
79
- around_restore :around_restore_action
80
-
81
- private
82
-
83
- def before_restore_action
84
- puts "BEFORE"
85
- end
86
-
87
- def after_restore_action
88
- puts "AFTER"
89
- end
90
-
91
- def around_restore_action
92
- puts "AROUND - BEFORE"
93
- yield # restoring
94
- puts "AROUND - AFTER"
95
- end
96
- end
97
- ```
98
-
99
- ## TODO
100
- - get rid of [monkey_patches.rb](https://github.com/simi/mongoid_paranoia/blob/master/lib/mongoid/paranoia/monkey_patches.rb)
101
- - [review persisted? behaviour](https://github.com/simi/mongoid_paranoia/issues/2)
102
-
103
- ## Authors
104
-
105
- * original [Mongoid](https://github.com/mongoid/mongoid) implementation by [@durran](https://github.com/durran)
106
- * extracted from [Mongoid](https://github.com/mongoid/mongoid) by [@simi](https://github.com/simi)
107
- * [documentation improvements](https://github.com/simi/mongoid_paranoia/pull/3) by awesome [@loopj](https://github.com/loopj)
108
- * [latest mongoid support, restore_callback support](https://github.com/simi/mongoid_paranoia/pull/8) by fabulous [@zhouguangming](https://github.com/zhouguangming)
109
-
110
-
111
- ## Contributing
112
-
113
- 1. Fork it
114
- 2. Create your feature branch (`git checkout -b my-new-feature`)
115
- 3. Commit your changes (`git commit -am 'Add some feature'`)
116
- 4. Push to the branch (`git push origin my-new-feature`)
117
- 5. Create new Pull Request
1
+ # Paranoid Documents for Mongoid
2
+ [![Build Status](https://travis-ci.org/simi/mongoid_paranoia.svg?branch=master)](https://travis-ci.org/simi/mongoid_paranoia) [![Gem Version](https://img.shields.io/gem/v/mongoid_paranoia.svg)](https://rubygems.org/gems/mongoid_paranoia) [![Gitter chat](https://badges.gitter.im/simi/mongoid_paranoia.svg)](https://gitter.im/simi/mongoid_paranoia)
3
+
4
+ `Mongoid::Paranoia` enables a "soft delete" of Mongoid documents. Instead of being removed from the database, paranoid docs are flagged with a `deleted_at` timestamp and are ignored from queries by default.
5
+
6
+ The `Mongoid::Paranoia` functionality was originally supported in Mongoid itself, but was dropped from version 4.0.0 onwards. This gem was extracted from the [Mongoid 3.0.0-stable branch](https://github.com/mongoid/mongoid/tree/3.0.0-stable). This gem should not be used with Mongoid versions 3.x and prior. Current master branch targeted on Mongoid 6.0. With release 0.3.0 Mongoid 4 and 5 versions will be dropped.
7
+
8
+ **Caution:** This repo/gem `mongoid_paranoia` (underscored) is different than [mongoid-paranoia](https://github.com/haihappen/mongoid-paranoia) (hyphenated). The goal of `mongoid-paranoia` (hyphenated) is to stay API compatible and it only accepts security fixes.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'mongoid_paranoia'
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```ruby
21
+ class Person
22
+ include Mongoid::Document
23
+ include Mongoid::Paranoia
24
+ end
25
+
26
+ person.delete # Sets the deleted_at field to the current time, ignoring callbacks.
27
+ person.delete! # Permanently deletes the document, ignoring callbacks.
28
+ person.destroy # Sets the deleted_at field to the current time, firing callbacks.
29
+ person.destroy! # Permanently deletes the document, firing callbacks.
30
+ person.restore # Brings the "deleted" document back to life.
31
+ person.restore(:recursive => true) # Brings "deleted" associated documents back to life recursively
32
+ ```
33
+
34
+ The documents that have been "flagged" as deleted (soft deleted) can be accessed at any time by calling the deleted class method on the class.
35
+
36
+ ```ruby
37
+ Person.deleted # Returns documents that have been "flagged" as deleted.
38
+ ```
39
+
40
+ You can also access all documents (both deleted and non-deleted) at any time by using the `unscoped` class method:
41
+
42
+ ```ruby
43
+ Person.unscoped.all # Returns all documents, both deleted and non-deleted
44
+ ```
45
+
46
+ You can also configure the paranoid field naming on a global basis. Within the context of a Rails app this is done via an initializer.
47
+
48
+ ```ruby
49
+ # config/initializers/mongoid_paranoid.rb
50
+
51
+ Mongoid::Paranoia.configure do |c|
52
+ c.paranoid_field = :myFieldName
53
+ end
54
+ ```
55
+
56
+ ### Validations
57
+ #### You need override uniqueness validates
58
+
59
+ ```ruby
60
+ validates :title, uniqueness: { conditions: -> { where(deleted_at: nil) } }
61
+ ```
62
+
63
+ ### Callbacks
64
+
65
+ #### Restore
66
+ `before_restore`, `after_restore` and `around_restore` callbacks are added to your model. They work similarly to the `before_destroy`, `after_destroy` and `around_destroy` callbacks.
67
+
68
+ #### Remove
69
+ `before_remove`, `after_remove` and `around_remove` are added to your model. They are called when record is deleted permanently .
70
+
71
+ #### Example
72
+ ```ruby
73
+ class User
74
+ include Mongoid::Document
75
+ include Mongoid::Paranoia
76
+
77
+ before_restore :before_restore_action
78
+ after_restore :after_restore_action
79
+ around_restore :around_restore_action
80
+
81
+ private
82
+
83
+ def before_restore_action
84
+ puts "BEFORE"
85
+ end
86
+
87
+ def after_restore_action
88
+ puts "AFTER"
89
+ end
90
+
91
+ def around_restore_action
92
+ puts "AROUND - BEFORE"
93
+ yield # restoring
94
+ puts "AROUND - AFTER"
95
+ end
96
+ end
97
+ ```
98
+
99
+ ## TODO
100
+ - get rid of [monkey_patches.rb](https://github.com/simi/mongoid_paranoia/blob/master/lib/mongoid/paranoia/monkey_patches.rb)
101
+ - [review persisted? behaviour](https://github.com/simi/mongoid_paranoia/issues/2)
102
+
103
+ ## Authors
104
+
105
+ * original [Mongoid](https://github.com/mongoid/mongoid) implementation by [@durran](https://github.com/durran)
106
+ * extracted from [Mongoid](https://github.com/mongoid/mongoid) by [@simi](https://github.com/simi)
107
+ * [documentation improvements](https://github.com/simi/mongoid_paranoia/pull/3) by awesome [@loopj](https://github.com/loopj)
108
+ * [latest mongoid support, restore_callback support](https://github.com/simi/mongoid_paranoia/pull/8) by fabulous [@zhouguangming](https://github.com/zhouguangming)
109
+
110
+
111
+ ## Contributing
112
+
113
+ 1. Fork it
114
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
115
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
116
+ 4. Push to the branch (`git push origin my-new-feature`)
117
+ 5. Create new Pull Request
@@ -1 +1,3 @@
1
- require "mongoid/paranoia"
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongoid/paranoia'
@@ -1,203 +1,206 @@
1
- # encoding: utf-8
2
- require 'mongoid/paranoia/monkey_patches'
3
- require 'mongoid/paranoia/configuration'
4
- require 'active_support'
5
- require 'active_support/deprecation'
6
-
7
- module Mongoid
8
-
9
- # Include this module to get soft deletion of root level documents.
10
- # This will add a deleted_at field to the +Document+, managed automatically.
11
- # Potentially incompatible with unique indices. (if collisions with deleted items)
12
- #
13
- # @example Make a document paranoid.
14
- # class Person
15
- # include Mongoid::Document
16
- # include Mongoid::Paranoia
17
- # end
18
- module Paranoia
19
- include Mongoid::Persistable::Deletable
20
- extend ActiveSupport::Concern
21
-
22
- class << self
23
- attr_accessor :configuration
24
- end
25
-
26
- def self.configuration
27
- @configuration ||= Configuration.new
28
- end
29
-
30
- def self.reset
31
- @configuration = Configuration.new
32
- end
33
-
34
- # Allow the paranoid +Document+ to use an alternate field name for deleted_at.
35
- #
36
- # @example
37
- # Mongoid::Paranoia.configure do |c|
38
- # c.paranoid_field = :myFieldName
39
- # end
40
- def self.configure
41
- yield(configuration)
42
- end
43
-
44
- included do
45
- field Paranoia.configuration.paranoid_field, as: :deleted_at, type: Time
46
-
47
- self.paranoid = true
48
-
49
- default_scope -> { where(deleted_at: nil) }
50
- scope :deleted, -> { ne(deleted_at: nil) }
51
- define_model_callbacks :restore
52
- define_model_callbacks :remove
53
- end
54
-
55
- # Delete the paranoid +Document+ from the database completely. This will
56
- # run the destroy callbacks.
57
- #
58
- # @example Hard destroy the document.
59
- # document.destroy!
60
- #
61
- # @return [ true, false ] If the operation succeeded.
62
- #
63
- # @since 1.0.0
64
- def destroy!
65
- run_callbacks(:destroy) do
66
- run_callbacks(:remove) do
67
- delete!
68
- end
69
- end
70
- end
71
-
72
- # Override the persisted method to allow for the paranoia gem.
73
- # If a paranoid record is selected, then we only want to check
74
- # if it's a new record, not if it is "destroyed"
75
- #
76
- # @example
77
- # document.persisted?
78
- #
79
- # @return [ true, false ] If the operation succeeded.
80
- #
81
- # @since 4.0.0
82
- def persisted?
83
- !new_record?
84
- end
85
-
86
- # Delete the +Document+, will set the deleted_at timestamp and not actually
87
- # delete it.
88
- #
89
- # @example Soft remove the document.
90
- # document.remove
91
- #
92
- # @param [ Hash ] options The database options.
93
- #
94
- # @return [ true ] True.
95
- #
96
- # @since 1.0.0
97
- alias orig_remove :remove
98
-
99
- def remove(_ = {})
100
- return false unless catch(:abort) { apply_delete_dependencies! }
101
- time = self.deleted_at = Time.now
102
- _paranoia_update('$set' => { paranoid_field => time })
103
- @destroyed = true
104
- true
105
- end
106
-
107
- alias delete :remove
108
-
109
- # Delete the paranoid +Document+ from the database completely.
110
- #
111
- # @example Hard delete the document.
112
- # document.delete!
113
- #
114
- # @return [ true, false ] If the operation succeeded.
115
- #
116
- # @since 1.0.0
117
- def delete!
118
- orig_remove
119
- end
120
-
121
- # Determines if this document is destroyed.
122
- #
123
- # @example Is the document destroyed?
124
- # person.destroyed?
125
- #
126
- # @return [ true, false ] If the document is destroyed.
127
- #
128
- # @since 1.0.0
129
- def destroyed?
130
- (@destroyed ||= false) || !!deleted_at
131
- end
132
- alias :deleted? :destroyed?
133
-
134
- # Restores a previously soft-deleted document. Handles this by removing the
135
- # deleted_at flag.
136
- #
137
- # @example Restore the document from deleted state.
138
- # document.restore
139
- #
140
- # For resoring associated documents use :recursive => true
141
- # @example Restore the associated documents from deleted state.
142
- # document.restore(:recursive => true)
143
- #
144
- # TODO: @return [ Time ] The time the document had been deleted.
145
- #
146
- # @since 1.0.0
147
- def restore(opts = {})
148
- run_callbacks(:restore) do
149
- _paranoia_update("$unset" => { paranoid_field => true })
150
- attributes.delete("deleted_at")
151
- @destroyed = false
152
- restore_relations if opts[:recursive]
153
- true
154
- end
155
- end
156
-
157
- # Returns a string representing the documents's key suitable for use in URLs.
158
- def to_param
159
- new_record? ? nil : to_key.join('-')
160
- end
161
-
162
- def restore_relations
163
- self.relations.each_pair do |name, association|
164
- next unless association.dependent == :destroy
165
- relation = self.send(name)
166
- if relation.present? && relation.paranoid?
167
- Array.wrap(relation).each do |doc|
168
- doc.restore(:recursive => true)
169
- end
170
- end
171
- end
172
- end
173
-
174
- private
175
-
176
- # Get the collection to be used for paranoid operations.
177
- #
178
- # @example Get the paranoid collection.
179
- # document.paranoid_collection
180
- #
181
- # @return [ Collection ] The root collection.
182
- def paranoid_collection
183
- embedded? ? _root.collection : self.collection
184
- end
185
-
186
- # Get the field to be used for paranoid operations.
187
- #
188
- # @example Get the paranoid field.
189
- # document.paranoid_field
190
- #
191
- # @return [ String ] The deleted at field.
192
- def paranoid_field
193
- field = Paranoia.configuration.paranoid_field
194
- embedded? ? "#{atomic_position}.#{field}" : field
195
- end
196
-
197
- # @return [ Object ] Update result.
198
- #
199
- def _paranoia_update(value)
200
- paranoid_collection.find(atomic_selector).update_one(value)
201
- end
202
- end
203
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongoid/paranoia/monkey_patches'
4
+ require 'mongoid/paranoia/configuration'
5
+ require 'active_support'
6
+ require 'active_support/deprecation'
7
+
8
+ module Mongoid
9
+ # Include this module to get soft deletion of root level documents.
10
+ # This will add a deleted_at field to the +Document+, managed automatically.
11
+ # Potentially incompatible with unique indices. (if collisions with deleted items)
12
+ #
13
+ # @example Make a document paranoid.
14
+ # class Person
15
+ # include Mongoid::Document
16
+ # include Mongoid::Paranoia
17
+ # end
18
+ module Paranoia
19
+ include Mongoid::Persistable::Deletable
20
+ extend ActiveSupport::Concern
21
+
22
+ class << self
23
+ def configuration
24
+ @configuration ||= Configuration.new
25
+ end
26
+
27
+ def reset
28
+ @configuration = Configuration.new
29
+ end
30
+
31
+ # Allow the paranoid +Document+ to use an alternate field name for deleted_at.
32
+ #
33
+ # @example
34
+ # Mongoid::Paranoia.configure do |c|
35
+ # c.paranoid_field = :myFieldName
36
+ # end
37
+ def configure
38
+ yield(configuration)
39
+ end
40
+ end
41
+
42
+ included do
43
+ field Paranoia.configuration.paranoid_field, as: :deleted_at, type: Time
44
+
45
+ self.paranoid = true
46
+
47
+ default_scope -> { where(deleted_at: nil) }
48
+ scope :deleted, -> { ne(deleted_at: nil) }
49
+ define_model_callbacks :restore
50
+ define_model_callbacks :remove
51
+ end
52
+
53
+ # Delete the paranoid +Document+ from the database completely. This will
54
+ # run the destroy callbacks.
55
+ #
56
+ # @example Hard destroy the document.
57
+ # document.destroy!
58
+ #
59
+ # @return [ true, false ] If the operation succeeded.
60
+ #
61
+ # @since 1.0.0
62
+ def destroy!
63
+ run_callbacks(:destroy) do
64
+ run_callbacks(:remove) do
65
+ delete!
66
+ end
67
+ end
68
+ end
69
+
70
+ # Override the persisted method to allow for the paranoia gem.
71
+ # If a paranoid record is selected, then we only want to check
72
+ # if it's a new record, not if it is "destroyed"
73
+ #
74
+ # @example
75
+ # document.persisted?
76
+ #
77
+ # @return [ true, false ] If the operation succeeded.
78
+ #
79
+ # @since 4.0.0
80
+ def persisted?
81
+ !new_record?
82
+ end
83
+
84
+ # Delete the +Document+, will set the deleted_at timestamp and not actually
85
+ # delete it.
86
+ #
87
+ # @example Soft remove the document.
88
+ # document.remove
89
+ #
90
+ # @param [ Hash ] options The database options.
91
+ #
92
+ # @return [ true ] True.
93
+ #
94
+ # @since 1.0.0
95
+ alias orig_remove :remove
96
+
97
+ def remove(_ = {})
98
+ return false unless catch(:abort) do
99
+ if respond_to?(:apply_destroy_dependencies!)
100
+ apply_destroy_dependencies!
101
+ else
102
+ apply_delete_dependencies!
103
+ end
104
+ end
105
+ time = self.deleted_at = Time.now
106
+ _paranoia_update('$set' => { paranoid_field => time })
107
+ @destroyed = true
108
+ true
109
+ end
110
+
111
+ alias delete :remove
112
+
113
+ # Delete the paranoid +Document+ from the database completely.
114
+ #
115
+ # @example Hard delete the document.
116
+ # document.delete!
117
+ #
118
+ # @return [ true, false ] If the operation succeeded.
119
+ #
120
+ # @since 1.0.0
121
+ def delete!
122
+ orig_remove
123
+ end
124
+
125
+ # Determines if this document is destroyed.
126
+ #
127
+ # @example Is the document destroyed?
128
+ # person.destroyed?
129
+ #
130
+ # @return [ true, false ] If the document is destroyed.
131
+ #
132
+ # @since 1.0.0
133
+ def destroyed?
134
+ (@destroyed ||= false) || !!deleted_at
135
+ end
136
+ alias deleted? destroyed?
137
+
138
+ # Restores a previously soft-deleted document. Handles this by removing the
139
+ # deleted_at flag.
140
+ #
141
+ # @example Restore the document from deleted state.
142
+ # document.restore
143
+ #
144
+ # For resoring associated documents use :recursive => true
145
+ # @example Restore the associated documents from deleted state.
146
+ # document.restore(:recursive => true)
147
+ #
148
+ # TODO: @return [ Time ] The time the document had been deleted.
149
+ #
150
+ # @since 1.0.0
151
+ def restore(opts = {})
152
+ run_callbacks(:restore) do
153
+ _paranoia_update('$unset' => { paranoid_field => true })
154
+ attributes.delete('deleted_at')
155
+ @destroyed = false
156
+ restore_relations if opts[:recursive]
157
+ true
158
+ end
159
+ end
160
+
161
+ # Returns a string representing the documents's key suitable for use in URLs.
162
+ def to_param
163
+ new_record? ? nil : to_key.join('-')
164
+ end
165
+
166
+ def restore_relations
167
+ relations.each_pair do |name, association|
168
+ next unless association.dependent == :destroy
169
+ relation = send(name)
170
+ next unless relation.present? && relation.paranoid?
171
+ Array.wrap(relation).each do |doc|
172
+ doc.restore(recursive: true)
173
+ end
174
+ end
175
+ end
176
+
177
+ private
178
+
179
+ # Get the collection to be used for paranoid operations.
180
+ #
181
+ # @example Get the paranoid collection.
182
+ # document.paranoid_collection
183
+ #
184
+ # @return [ Collection ] The root collection.
185
+ def paranoid_collection
186
+ embedded? ? _root.collection : collection
187
+ end
188
+
189
+ # Get the field to be used for paranoid operations.
190
+ #
191
+ # @example Get the paranoid field.
192
+ # document.paranoid_field
193
+ #
194
+ # @return [ String ] The deleted at field.
195
+ def paranoid_field
196
+ field = Paranoia.configuration.paranoid_field
197
+ embedded? ? "#{atomic_position}.#{field}" : field
198
+ end
199
+
200
+ # @return [ Object ] Update result.
201
+ #
202
+ def _paranoia_update(value)
203
+ paranoid_collection.find(atomic_selector).update_one(value)
204
+ end
205
+ end
206
+ end