mongoid_paranoia 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NjFjZDkxZDIzNmM0MzRjMDNiODYyNmRkOGZjNWNiMzljZmI1NGU2Yg==
5
- data.tar.gz: !binary |-
6
- NjAxNjc2MjRiYjAxNWE5ZTc5M2UyYTRiNTQ4ZmZmODRmMzJhYjY5YQ==
2
+ SHA1:
3
+ metadata.gz: deac1371595d42d09d10aab1039561adb1190da7
4
+ data.tar.gz: b29cbcc347078b464c218646b58780a8f50bb3bf
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- YjBiYmQ2Zjc3MjEyZjAzZTVkNTM2ZDQ4NWI4NzYwM2YzMWIzODRjY2NmYmNl
10
- ZDIxZmVjNDE1NTI0ZTYzOTBmNWI2NGE0YzQ4ZDVhOTA5NjhhZGMwNDgwMmFh
11
- MGFhZDNhYTkwZTQ0ZTc3ZTNlNGNiOWE3MThmMWY1NTNkOGNiMzA=
12
- data.tar.gz: !binary |-
13
- NjkzMTE1N2UxMDY1ZWEyYWJmNjA0Njg1Zjk0MWYxMmRkZjExZDEyNWQzZjE2
14
- YzA0ZmUyNzRlZjc3YjRiM2M0NTI3ZTE2MzQ2NTNjOWJiMGExZTJiMWI4ZmZm
15
- Zjc1MGM1MTU2YTgxZjNiOGY2NGExOGI4OTdlMjY5YjBjNWVkMWY=
6
+ metadata.gz: 6b0dc3130837783326de78218f63c4f807c2c09cf45de8f52038dec7eb12667488362db029954a789c79377f9266d4ff78d247ed76097ba4348389b28354218e
7
+ data.tar.gz: 45a65478ef3edab1351c4834b52afed11c26f117721ad5c444b94439ebe159cdb6fad6a31cf31254b2eaaaaeef80be352541b26f4525caf161605d95dc75afe6
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,110 +1,124 @@
1
- # Paranoid Documents for Mongoid 4 [![Build Status](https://travis-ci.org/simi/mongoid-paranoia.png?branch=master)](https://travis-ci.org/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/simi/mongoid-paranoia/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` (hyphenated).
8
- The owner of `mongoid-paranoia` (hyphenated) is not accepting enhancements and has declined our requests
9
- to share maintenance of the gem.
10
-
11
- ## Installation
12
-
13
- Add this line to your application's Gemfile:
14
-
15
- ```ruby
16
- gem 'mongoid_paranoia'
17
- ```
18
-
19
- ## Changes in 4.0
20
-
21
- ### Uniqueness validator is not overriden
22
-
23
- #### Old syntax:
24
- ```ruby
25
- validates_uniqueness_of :title
26
- validates :title, :uniqueness => true
27
- ```
28
-
29
- #### New syntax:
30
- ```ruby
31
- validates :title, uniqueness: { conditions: -> { where(deleted_at: nil) } }
32
- ```
33
-
34
- ## Usage
35
-
36
- ```ruby
37
- class Person
38
- include Mongoid::Document
39
- include Mongoid::Paranoia
40
- end
41
-
42
- person.delete # Sets the deleted_at field to the current time, ignoring callbacks.
43
- person.delete! # Permanently deletes the document, ignoring callbacks.
44
- person.destroy # Sets the deleted_at field to the current time, firing callbacks.
45
- person.destroy! # Permanently deletes the document, firing callbacks.
46
- person.restore # Brings the "deleted" document back to life.
47
- ```
48
-
49
- 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.
50
-
51
- ```ruby
52
- Person.deleted # Returns documents that have been "flagged" as deleted.
53
- ```
54
-
55
- You can also access all documents (both deleted and non-deleted) at any time by using the `unscoped` class method:
56
-
57
- ```ruby
58
- Person.unscoped.all # Returns all documents, both deleted and non-deleted
59
- ```
60
-
61
- ### Callbacks ([@zhouguangming](https://github.com/zhouguangming))
62
-
63
- `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.
64
-
65
- ```ruby
66
- class User
67
- include Mongoid::Document
68
- include Mongoid::Paranoia
69
-
70
- before_restore :before_restore_action
71
- after_restore :after_restore_action
72
- around_restore :around_restore_action
73
-
74
- private
75
-
76
- def before_restore_action
77
- puts "BEFORE"
78
- end
79
-
80
- def after_restore_action
81
- puts "AFTER"
82
- end
83
-
84
- def around_restore_action
85
- puts "AROUND - BEFORE"
86
- yield # restoring
87
- puts "AROUND - AFTER"
88
- end
89
- end
90
- ```
91
-
92
- ## TODO
93
- - get rid of [monkey_patches.rb](https://github.com/simi/mongoid-paranoia/blob/master/lib/mongoid/paranoia/monkey_patches.rb)
94
- - [review persisted? behaviour](https://github.com/simi/mongoid-paranoia/issues/2)
95
-
96
- ## Authors
97
-
98
- * original [Mongoid](https://github.com/mongoid/mongoid) implementation by [@durran](https://github.com/durran)
99
- * extracted from [Mongoid](https://github.com/mongoid/mongoid) by [@simi](https://github.com/simi)
100
- * [documentation improvements](https://github.com/simi/mongoid-paranoia/pull/3) by awesome [@loopj](https://github.com/loopj)
101
- * [latest mongoid support, restore_callback support](https://github.com/simi/mongoid-paranoia/pull/8) by fabulous [@zhouguangming](https://github.com/zhouguangming)
102
-
103
-
104
- ## Contributing
105
-
106
- 1. Fork it
107
- 2. Create your feature branch (`git checkout -b my-new-feature`)
108
- 3. Commit your changes (`git commit -am 'Add some feature'`)
109
- 4. Push to the branch (`git push origin my-new-feature`)
110
- 5. Create new Pull Request
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 +1 @@
1
- require "mongoid/paranoia"
1
+ require "mongoid/paranoia"
@@ -1,154 +1,208 @@
1
- # encoding: utf-8
2
- require 'mongoid/paranoia/monkey_patches'
3
- require 'active_support'
4
- require 'active_support/deprecation'
5
-
6
- module Mongoid
7
-
8
- # Include this module to get soft deletion of root level documents.
9
- # This will add a deleted_at field to the +Document+, managed automatically.
10
- # Potentially incompatible with unique indices. (if collisions with deleted items)
11
- #
12
- # @example Make a document paranoid.
13
- # class Person
14
- # include Mongoid::Document
15
- # include Mongoid::Paranoia
16
- # end
17
- module Paranoia
18
- include Mongoid::Persistable::Deletable
19
- extend ActiveSupport::Concern
20
-
21
- included do
22
- field :deleted_at, type: Time
23
- self.paranoid = true
24
-
25
- default_scope -> { where(deleted_at: nil) }
26
- scope :deleted, -> { ne(deleted_at: nil) }
27
- define_model_callbacks :restore
28
- end
29
-
30
- # Delete the paranoid +Document+ from the database completely. This will
31
- # run the destroy callbacks.
32
- #
33
- # @example Hard destroy the document.
34
- # document.destroy!
35
- #
36
- # @return [ true, false ] If the operation succeeded.
37
- #
38
- # @since 1.0.0
39
- def destroy!
40
- run_callbacks(:destroy) { delete! }
41
- end
42
-
43
- # Override the persisted method to allow for the paranoia gem.
44
- # If a paranoid record is selected, then we only want to check
45
- # if it's a new record, not if it is "destroyed"
46
- #
47
- # @example
48
- # document.persisted?
49
- #
50
- # @return [ true, false ] If the operation succeeded.
51
- #
52
- # @since 4.0.0
53
- def persisted?
54
- !new_record?
55
- end
56
-
57
- # Delete the +Document+, will set the deleted_at timestamp and not actually
58
- # delete it.
59
- #
60
- # @example Soft remove the document.
61
- # document.remove
62
- #
63
- # @param [ Hash ] options The database options.
64
- #
65
- # @return [ true ] True.
66
- #
67
- # @since 1.0.0
68
- def remove_with_paranoia(options = {})
69
- cascade!
70
- time = self.deleted_at = Time.now
71
- paranoid_collection.find(atomic_selector).
72
- update({ "$set" => { paranoid_field => time }})
73
- @destroyed = true
74
- true
75
- end
76
- alias_method_chain :remove, :paranoia
77
- alias :delete :remove
78
-
79
- # Delete the paranoid +Document+ from the database completely.
80
- #
81
- # @example Hard delete the document.
82
- # document.delete!
83
- #
84
- # @return [ true, false ] If the operation succeeded.
85
- #
86
- # @since 1.0.0
87
- def delete!
88
- remove_without_paranoia
89
- end
90
-
91
- # Determines if this document is destroyed.
92
- #
93
- # @example Is the document destroyed?
94
- # person.destroyed?
95
- #
96
- # @return [ true, false ] If the document is destroyed.
97
- #
98
- # @since 1.0.0
99
- def destroyed?
100
- (@destroyed ||= false) || !!deleted_at
101
- end
102
- alias :deleted? :destroyed?
103
-
104
- # Restores a previously soft-deleted document. Handles this by removing the
105
- # deleted_at flag.
106
- #
107
- # @example Restore the document from deleted state.
108
- # document.restore
109
- #
110
- # TODO: @return [ Time ] The time the document had been deleted.
111
- #
112
- # @since 1.0.0
113
- def restore
114
- run_callbacks(:restore) do
115
- paranoid_collection.find(atomic_selector).
116
- update({ "$unset" => { paranoid_field => true }})
117
- attributes.delete("deleted_at")
118
- @destroyed = false
119
- true
120
- end
121
- end
122
-
123
- # Returns a string representing the documents's key suitable for use in URLs.
124
- def to_param
125
- new_record? ? nil : to_key.join('-')
126
- end
127
-
128
- private
129
-
130
- # Get the collection to be used for paranoid operations.
131
- #
132
- # @example Get the paranoid collection.
133
- # document.paranoid_collection
134
- #
135
- # @return [ Collection ] The root collection.
136
- #
137
- # @since 2.3.1
138
- def paranoid_collection
139
- embedded? ? _root.collection : self.collection
140
- end
141
-
142
- # Get the field to be used for paranoid operations.
143
- #
144
- # @example Get the paranoid field.
145
- # document.paranoid_field
146
- #
147
- # @return [ String ] The deleted at field.
148
- #
149
- # @since 2.3.1
150
- def paranoid_field
151
- embedded? ? "#{atomic_position}.deleted_at" : "deleted_at"
152
- end
153
- end
154
- end
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
+ 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
+ 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.
197
+ #
198
+ # @return [ Object ] Update result.
199
+ def 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