mongoid_paranoia 0.2.1 → 0.5.0

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
- SHA1:
3
- metadata.gz: 2edfadf14fc3b166efd190f331c5e86a75de4c20
4
- data.tar.gz: 988223f244d3537c149c7d354163031fbb658c5e
2
+ SHA256:
3
+ metadata.gz: ec456afdb66a1a23fdb5dc73db06b9dc6344932f8aa3c95b378ca60560aea474
4
+ data.tar.gz: b80b6cfaedfb9523b9dbfe791d586493eb4c9d3e65b7286d3cdc2010d8f9874e
5
5
  SHA512:
6
- metadata.gz: 37fb1381901fc197f18f79cbbfea5f8db627c94f8d9fa84da71a234878a69c4c9d6eec6e1ac6486f9fac4c59343556fc66ef186f0da5e92700396929b28534b7
7
- data.tar.gz: f69bd91ff7eeabf02d205608a4081967ec02f703b4b807489b251898d44786739023263f44a6c55e07e638d01abe0aafb9386b98da5af67cd44581065662671e
6
+ metadata.gz: 3aff3ad8f7f06f0a1498143baf6cf72d58c24b99b3a4f0bfb19fd314ec836625356291989293ddee2dc230d148dda65f84bc153660bd00566ba8bc727e21ee9f
7
+ data.tar.gz: 5322c2f12d84591a8e0bc3463faf1e82571f09c5877bc3a3f7bcfbf7c10c87e198bb8be2add2ab42c6e71341df77fdbe7dbe368ccc476d7e44c8f41839c283cb
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,124 +1,117 @@
1
- # Paranoid Documents for Mongoid 4 and 5 [![Build Status](https://travis-ci.org/simi/mongoid_paranoia.png?branch=master)](https://travis-ci.org/simi/mongoid_paranoia)[![Gitter chat](https://badges.gitter.im/simi/mongoid_paranoia.png)](https://gitter.im/simi/mongoid_paranoia)
2
-
3
- `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.
4
-
5
- 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.
6
-
7
- **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.
8
-
9
- ## Installation
10
-
11
- Add this line to your application's Gemfile:
12
-
13
- ```ruby
14
- gem 'mongoid_paranoia'
15
- ```
16
-
17
- ## Changes in 4.0
18
-
19
- ### Uniqueness validator is not overriden
20
-
21
- #### Old syntax:
22
- ```ruby
23
- validates_uniqueness_of :title
24
- validates :title, :uniqueness => true
25
- ```
26
-
27
- #### New syntax:
28
- ```ruby
29
- validates :title, uniqueness: { conditions: -> { where(deleted_at: nil) } }
30
- ```
31
-
32
- ## Usage
33
-
34
- ```ruby
35
- class Person
36
- include Mongoid::Document
37
- include Mongoid::Paranoia
38
- end
39
-
40
- person.delete # Sets the deleted_at field to the current time, ignoring callbacks.
41
- person.delete! # Permanently deletes the document, ignoring callbacks.
42
- person.destroy # Sets the deleted_at field to the current time, firing callbacks.
43
- person.destroy! # Permanently deletes the document, firing callbacks.
44
- person.restore # Brings the "deleted" document back to life.
45
- person.restore(:recursive => true) # Brings "deleted" associated documents back to life recursively
46
- ```
47
-
48
- 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.
49
-
50
- ```ruby
51
- Person.deleted # Returns documents that have been "flagged" as deleted.
52
- ```
53
-
54
- You can also access all documents (both deleted and non-deleted) at any time by using the `unscoped` class method:
55
-
56
- ```ruby
57
- Person.unscoped.all # Returns all documents, both deleted and non-deleted
58
- ```
59
-
60
- 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.
61
-
62
- ```ruby
63
- # config/initializers/mongoid_paranoid.rb
64
-
65
- Mongoid::Paranoia.configure do |c|
66
- c.paranoid_field = :myFieldName
67
- end
68
- ```
69
-
70
- ### Callbacks
71
-
72
- #### Restore
73
- `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.
74
-
75
- #### Remove
76
- `before_remove`, `after_remove` and `around_remove` are added to your model. They are called when record is deleted permanently .
77
-
78
- #### Example
79
- ```ruby
80
- class User
81
- include Mongoid::Document
82
- include Mongoid::Paranoia
83
-
84
- before_restore :before_restore_action
85
- after_restore :after_restore_action
86
- around_restore :around_restore_action
87
-
88
- private
89
-
90
- def before_restore_action
91
- puts "BEFORE"
92
- end
93
-
94
- def after_restore_action
95
- puts "AFTER"
96
- end
97
-
98
- def around_restore_action
99
- puts "AROUND - BEFORE"
100
- yield # restoring
101
- puts "AROUND - AFTER"
102
- end
103
- end
104
- ```
105
-
106
- ## TODO
107
- - get rid of [monkey_patches.rb](https://github.com/simi/mongoid_paranoia/blob/master/lib/mongoid/paranoia/monkey_patches.rb)
108
- - [review persisted? behaviour](https://github.com/simi/mongoid_paranoia/issues/2)
109
-
110
- ## Authors
111
-
112
- * original [Mongoid](https://github.com/mongoid/mongoid) implementation by [@durran](https://github.com/durran)
113
- * extracted from [Mongoid](https://github.com/mongoid/mongoid) by [@simi](https://github.com/simi)
114
- * [documentation improvements](https://github.com/simi/mongoid_paranoia/pull/3) by awesome [@loopj](https://github.com/loopj)
115
- * [latest mongoid support, restore_callback support](https://github.com/simi/mongoid_paranoia/pull/8) by fabulous [@zhouguangming](https://github.com/zhouguangming)
116
-
117
-
118
- ## Contributing
119
-
120
- 1. Fork it
121
- 2. Create your feature branch (`git checkout -b my-new-feature`)
122
- 3. Commit your changes (`git commit -am 'Add some feature'`)
123
- 4. Push to the branch (`git push origin my-new-feature`)
124
- 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,208 +1,196 @@
1
- # encoding: utf-8
2
- require 'mongoid/compatibility'
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
-
10
- # Include this module to get soft deletion of root level documents.
11
- # This will add a deleted_at field to the +Document+, managed automatically.
12
- # Potentially incompatible with unique indices. (if collisions with deleted items)
13
- #
14
- # @example Make a document paranoid.
15
- # class Person
16
- # include Mongoid::Document
17
- # include Mongoid::Paranoia
18
- # end
19
- module Paranoia
20
- include Mongoid::Persistable::Deletable
21
- extend ActiveSupport::Concern
22
-
23
- class << self
24
- attr_accessor :configuration
25
- end
26
-
27
- def self.configuration
28
- @configuration ||= Configuration.new
29
- end
30
-
31
- def self.reset
32
- @configuration = Configuration.new
33
- end
34
-
35
- # Allow the paranoid +Document+ to use an alternate field name for deleted_at.
36
- #
37
- # @example
38
- # Mongoid::Paranoia.configure do |c|
39
- # c.paranoid_field = :myFieldName
40
- # end
41
- def self.configure
42
- yield(configuration)
43
- end
44
-
45
- included do
46
- field Paranoia.configuration.paranoid_field, as: :deleted_at, type: Time
47
-
48
- self.paranoid = true
49
-
50
- default_scope -> { where(deleted_at: nil) }
51
- scope :deleted, -> { ne(deleted_at: nil) }
52
- define_model_callbacks :restore
53
- define_model_callbacks :remove
54
- end
55
-
56
- # Delete the paranoid +Document+ from the database completely. This will
57
- # run the destroy callbacks.
58
- #
59
- # @example Hard destroy the document.
60
- # document.destroy!
61
- #
62
- # @return [ true, false ] If the operation succeeded.
63
- #
64
- # @since 1.0.0
65
- def destroy!
66
- run_callbacks(:destroy) do
67
- run_callbacks(:remove) do
68
- delete!
69
- end
70
- end
71
- end
72
-
73
- # Override the persisted method to allow for the paranoia gem.
74
- # If a paranoid record is selected, then we only want to check
75
- # if it's a new record, not if it is "destroyed"
76
- #
77
- # @example
78
- # document.persisted?
79
- #
80
- # @return [ true, false ] If the operation succeeded.
81
- #
82
- # @since 4.0.0
83
- def persisted?
84
- !new_record?
85
- end
86
-
87
- # Delete the +Document+, will set the deleted_at timestamp and not actually
88
- # delete it.
89
- #
90
- # @example Soft remove the document.
91
- # document.remove
92
- #
93
- # @param [ Hash ] options The database options.
94
- #
95
- # @return [ true ] True.
96
- #
97
- # @since 1.0.0
98
- def remove_with_paranoia(options = {})
99
- cascade!
100
- time = self.deleted_at = Time.now
101
- _paranoia_update("$set" => { paranoid_field => time })
102
- @destroyed = true
103
- true
104
- end
105
- alias_method_chain :remove, :paranoia
106
- alias :delete :remove
107
-
108
- # Delete the paranoid +Document+ from the database completely.
109
- #
110
- # @example Hard delete the document.
111
- # document.delete!
112
- #
113
- # @return [ true, false ] If the operation succeeded.
114
- #
115
- # @since 1.0.0
116
- def delete!
117
- remove_without_paranoia
118
- end
119
-
120
- # Determines if this document is destroyed.
121
- #
122
- # @example Is the document destroyed?
123
- # person.destroyed?
124
- #
125
- # @return [ true, false ] If the document is destroyed.
126
- #
127
- # @since 1.0.0
128
- def destroyed?
129
- (@destroyed ||= false) || !!deleted_at
130
- end
131
- alias :deleted? :destroyed?
132
-
133
- # Restores a previously soft-deleted document. Handles this by removing the
134
- # deleted_at flag.
135
- #
136
- # @example Restore the document from deleted state.
137
- # document.restore
138
- #
139
- # For resoring associated documents use :recursive => true
140
- # @example Restore the associated documents from deleted state.
141
- # document.restore(:recursive => true)
142
- #
143
- # TODO: @return [ Time ] The time the document had been deleted.
144
- #
145
- # @since 1.0.0
146
- def restore(opts = {})
147
- run_callbacks(:restore) do
148
- _paranoia_update("$unset" => { paranoid_field => true })
149
- attributes.delete("deleted_at")
150
- @destroyed = false
151
- restore_relations if opts[:recursive]
152
- true
153
- end
154
- end
155
-
156
- # Returns a string representing the documents's key suitable for use in URLs.
157
- def to_param
158
- new_record? ? nil : to_key.join('-')
159
- end
160
-
161
- def restore_relations
162
- self.relations.each_pair do |name, metadata|
163
- next unless metadata[:dependent] == :destroy
164
- relation = self.send(name)
165
- if relation.present? && relation.paranoid?
166
- Array.wrap(relation).each do |doc|
167
- doc.restore(:recursive => true)
168
- end
169
- end
170
- end
171
- end
172
-
173
- private
174
-
175
- # Get the collection to be used for paranoid operations.
176
- #
177
- # @example Get the paranoid collection.
178
- # document.paranoid_collection
179
- #
180
- # @return [ Collection ] The root collection.
181
- def paranoid_collection
182
- embedded? ? _root.collection : self.collection
183
- end
184
-
185
- # Get the field to be used for paranoid operations.
186
- #
187
- # @example Get the paranoid field.
188
- # document.paranoid_field
189
- #
190
- # @return [ String ] The deleted at field.
191
- def paranoid_field
192
- field = Paranoia.configuration.paranoid_field
193
- embedded? ? "#{atomic_position}.#{field}" : field
194
- end
195
-
196
- # Update value in the collection (compatibility layer for Mongoid 4/5).
197
- #
198
- # @return [ Object ] Update result.
199
- def _paranoia_update(value)
200
- query = paranoid_collection.find(atomic_selector)
201
- if Mongoid::Compatibility::Version.mongoid5?
202
- query.update_one(value)
203
- else
204
- query.update(value)
205
- end
206
- end
207
- end
208
- 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
+ # Override the persisted method to allow for the paranoia gem.
54
+ # If a paranoid record is selected, then we only want to check
55
+ # if it's a new record, not if it is "destroyed"
56
+ #
57
+ # @example
58
+ # document.persisted?
59
+ #
60
+ # @return [ true, false ] If the operation succeeded.
61
+ #
62
+ # @since 4.0.0
63
+ def persisted?
64
+ !new_record?
65
+ end
66
+
67
+ # Delete the +Document+, will set the deleted_at timestamp and not actually
68
+ # delete it.
69
+ #
70
+ # @example Soft remove the document.
71
+ # document.remove
72
+ #
73
+ # @param [ Hash ] options The database options.
74
+ #
75
+ # @return [ true ] True.
76
+ #
77
+ # @since 1.0.0
78
+ alias :orig_delete :delete
79
+
80
+ def remove(_ = {})
81
+ time = self.deleted_at = Time.now
82
+ _paranoia_update('$set' => { paranoid_field => time })
83
+ @destroyed = true
84
+ true
85
+ end
86
+
87
+ alias :delete :remove
88
+ alias :delete! :orig_delete
89
+
90
+ # Delete the paranoid +Document+ from the database completely. This will
91
+ # run the destroy and remove callbacks.
92
+ #
93
+ # @example Hard destroy the document.
94
+ # document.destroy!
95
+ #
96
+ # @return [ true, false ] If the operation succeeded.
97
+ #
98
+ # @since 1.0.0
99
+ def destroy!(options = {})
100
+ raise Errors::ReadonlyDocument.new(self.class) if readonly?
101
+ self.flagged_for_destroy = true
102
+ result = run_callbacks(:destroy) do
103
+ run_callbacks(:remove) do
104
+ if catch(:abort) { apply_destroy_dependencies! }
105
+ delete!(options || {})
106
+ else
107
+ false
108
+ end
109
+ end
110
+ end
111
+ self.flagged_for_destroy = false
112
+ result
113
+ end
114
+
115
+ # Determines if this document is destroyed.
116
+ #
117
+ # @example Is the document destroyed?
118
+ # person.destroyed?
119
+ #
120
+ # @return [ true, false ] If the document is destroyed.
121
+ #
122
+ # @since 1.0.0
123
+ def destroyed?
124
+ (@destroyed ||= false) || !!deleted_at
125
+ end
126
+ alias deleted? destroyed?
127
+
128
+ # Restores a previously soft-deleted document. Handles this by removing the
129
+ # deleted_at flag.
130
+ #
131
+ # @example Restore the document from deleted state.
132
+ # document.restore
133
+ #
134
+ # For resoring associated documents use :recursive => true
135
+ # @example Restore the associated documents from deleted state.
136
+ # document.restore(:recursive => true)
137
+ #
138
+ # TODO: @return [ Time ] The time the document had been deleted.
139
+ #
140
+ # @since 1.0.0
141
+ def restore(opts = {})
142
+ run_callbacks(:restore) do
143
+ _paranoia_update('$unset' => { paranoid_field => true })
144
+ attributes.delete('deleted_at')
145
+ @destroyed = false
146
+ restore_relations if opts[:recursive]
147
+ true
148
+ end
149
+ end
150
+
151
+ # Returns a string representing the documents's key suitable for use in URLs.
152
+ def to_param
153
+ new_record? ? nil : to_key.join('-')
154
+ end
155
+
156
+ def restore_relations
157
+ relations.each_pair do |name, association|
158
+ next unless association.dependent == :destroy
159
+ relation = send(name)
160
+ next unless relation.present? && relation.paranoid?
161
+ Array.wrap(relation).each do |doc|
162
+ doc.restore(recursive: true)
163
+ end
164
+ end
165
+ end
166
+
167
+ private
168
+
169
+ # Get the collection to be used for paranoid operations.
170
+ #
171
+ # @example Get the paranoid collection.
172
+ # document.paranoid_collection
173
+ #
174
+ # @return [ Collection ] The root collection.
175
+ def paranoid_collection
176
+ embedded? ? _root.collection : collection
177
+ end
178
+
179
+ # Get the field to be used for paranoid operations.
180
+ #
181
+ # @example Get the paranoid field.
182
+ # document.paranoid_field
183
+ #
184
+ # @return [ String ] The deleted at field.
185
+ def paranoid_field
186
+ field = Paranoia.configuration.paranoid_field
187
+ embedded? ? "#{atomic_position}.#{field}" : field
188
+ end
189
+
190
+ # @return [ Object ] Update result.
191
+ #
192
+ def _paranoia_update(value)
193
+ paranoid_collection.find(atomic_selector).update_one(value)
194
+ end
195
+ end
196
+ end