mongoid_paranoia 0.2.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +21 -21
- data/README.md +117 -124
- data/lib/mongoid-paranoia.rb +3 -1
- data/lib/mongoid/paranoia.rb +206 -208
- data/lib/mongoid/paranoia/configuration.rb +13 -11
- data/lib/mongoid/paranoia/monkey_patches.rb +114 -113
- data/lib/mongoid/paranoia/version.rb +7 -5
- data/lib/mongoid_paranoia.rb +3 -1
- data/perf/scope.rb +65 -64
- data/spec/app/models/address.rb +71 -71
- data/spec/app/models/appointment.rb +7 -7
- data/spec/app/models/author.rb +6 -6
- data/spec/app/models/fish.rb +8 -8
- data/spec/app/models/paranoid_phone.rb +25 -25
- data/spec/app/models/paranoid_post.rb +65 -65
- data/spec/app/models/person.rb +21 -21
- data/spec/app/models/phone.rb +11 -11
- data/spec/app/models/relations.rb +247 -247
- data/spec/app/models/tag.rb +6 -6
- data/spec/app/models/title.rb +4 -4
- data/spec/mongoid/configuration_spec.rb +19 -19
- data/spec/mongoid/document_spec.rb +21 -21
- data/spec/mongoid/nested_attributes_spec.rb +164 -164
- data/spec/mongoid/paranoia_spec.rb +887 -887
- data/spec/mongoid/scoping_spec.rb +55 -55
- data/spec/mongoid/validatable/uniqueness_spec.rb +74 -74
- data/spec/spec_helper.rb +43 -73
- metadata +30 -27
@@ -1,11 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Paranoia
|
5
|
+
class Configuration
|
6
|
+
attr_accessor :paranoid_field
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@paranoid_field = :deleted_at
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,113 +1,114 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
#
|
10
|
-
# In Mongoid
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
module
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
module
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Paranoia
|
5
|
+
module Document
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
# Indicates whether or not the document includes Mongoid::Paranoia.
|
10
|
+
# In Mongoid 3, this method was defined on all Mongoid::Documents.
|
11
|
+
# In Mongoid 4, it is no longer defined, hence we are shimming it here.
|
12
|
+
class_attribute :paranoid
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Mongoid::Document.include Mongoid::Paranoia::Document
|
19
|
+
|
20
|
+
module Mongoid
|
21
|
+
module Association
|
22
|
+
module Nested
|
23
|
+
class Many
|
24
|
+
# Destroy the child document, needs to do some checking for embedded
|
25
|
+
# relations and delay the destroy in case parent validation fails.
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
#
|
29
|
+
# @example Destroy the child.
|
30
|
+
# builder.destroy(parent, relation, doc)
|
31
|
+
#
|
32
|
+
# @param [ Document ] parent The parent document.
|
33
|
+
# @param [ Proxy ] relation The relation proxy.
|
34
|
+
# @param [ Document ] doc The doc to destroy.
|
35
|
+
#
|
36
|
+
# @since 3.0.10
|
37
|
+
def destroy(parent, relation, doc)
|
38
|
+
doc.flagged_for_destroy = true
|
39
|
+
if !doc.embedded? || parent.new_record? || doc.paranoid?
|
40
|
+
destroy_document(relation, doc)
|
41
|
+
else
|
42
|
+
parent.flagged_destroys.push(-> { destroy_document(relation, doc) })
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module Mongoid
|
51
|
+
module Association
|
52
|
+
module Embedded
|
53
|
+
class EmbedsMany
|
54
|
+
class Proxy < Association::Many
|
55
|
+
# Delete the supplied document from the target. This method is proxied
|
56
|
+
# in order to reindex the array after the operation occurs.
|
57
|
+
#
|
58
|
+
# @example Delete the document from the relation.
|
59
|
+
# person.addresses.delete(address)
|
60
|
+
#
|
61
|
+
# @param [ Document ] document The document to be deleted.
|
62
|
+
#
|
63
|
+
# @return [ Document, nil ] The deleted document or nil if nothing deleted.
|
64
|
+
#
|
65
|
+
# @since 2.0.0.rc.1
|
66
|
+
def delete(document)
|
67
|
+
execute_callback :before_remove, document
|
68
|
+
doc = _target.delete_one(document)
|
69
|
+
if doc && !_binding?
|
70
|
+
_unscoped.delete_one(doc) unless doc.paranoid?
|
71
|
+
if _assigning?
|
72
|
+
if doc.paranoid?
|
73
|
+
doc.destroy(suppress: true)
|
74
|
+
else
|
75
|
+
_base.add_atomic_pull(doc)
|
76
|
+
end
|
77
|
+
else
|
78
|
+
doc.delete(suppress: true)
|
79
|
+
unbind_one(doc)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
reindex
|
83
|
+
execute_callback :after_remove, document
|
84
|
+
doc
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
module Mongoid
|
93
|
+
module Association
|
94
|
+
module Embedded
|
95
|
+
class EmbedsMany
|
96
|
+
class Proxy < Association::Many
|
97
|
+
# For use only with Mongoid::Paranoia - will be removed in 4.0.
|
98
|
+
#
|
99
|
+
# @example Get the deleted documents from the relation.
|
100
|
+
# person.paranoid_phones.deleted
|
101
|
+
#
|
102
|
+
# @return [ Criteria ] The deleted documents.
|
103
|
+
#
|
104
|
+
# @since 3.0.10
|
105
|
+
def deleted
|
106
|
+
unscoped.deleted
|
107
|
+
end
|
108
|
+
# This class handles the behaviour for a document that embeds many other
|
109
|
+
# documents within in it as an array.
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
data/lib/mongoid_paranoia.rb
CHANGED
data/perf/scope.rb
CHANGED
@@ -1,64 +1,65 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
include Mongoid::
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
field :
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
n
|
41
|
-
n.times {|i|
|
42
|
-
n.times {|i|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
x.report(
|
51
|
-
x.report(
|
52
|
-
x.report(
|
53
|
-
x.report(
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
puts
|
58
|
-
|
59
|
-
|
60
|
-
x.report(
|
61
|
-
x.report(
|
62
|
-
x.report(
|
63
|
-
x.report(
|
64
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'mongoid'
|
5
|
+
require 'mongoid/paranoia'
|
6
|
+
require 'benchmark'
|
7
|
+
|
8
|
+
Mongoid.configure do |config|
|
9
|
+
config.connect_to('my_little_test')
|
10
|
+
end
|
11
|
+
|
12
|
+
class Model
|
13
|
+
include Mongoid::Document
|
14
|
+
field :text, type: String
|
15
|
+
|
16
|
+
index({ text: 'text' })
|
17
|
+
end
|
18
|
+
|
19
|
+
class ParanoidModel
|
20
|
+
include Mongoid::Document
|
21
|
+
include Mongoid::Paranoia
|
22
|
+
field :text, type: String
|
23
|
+
|
24
|
+
index({ text: 'text' })
|
25
|
+
end
|
26
|
+
|
27
|
+
class MetaParanoidModel
|
28
|
+
include Mongoid::Document
|
29
|
+
field :text, type: String
|
30
|
+
field :deleted_at, type: Time
|
31
|
+
default_scope -> { where(deleted_at: nil) }
|
32
|
+
|
33
|
+
index({ text: 'text' })
|
34
|
+
end
|
35
|
+
|
36
|
+
if ENV['FORCE']
|
37
|
+
Mongoid.purge!
|
38
|
+
::Mongoid::Tasks::Database.create_indexes
|
39
|
+
|
40
|
+
n = 50_000
|
41
|
+
n.times {|i| Model.create(text: "text #{i}") }
|
42
|
+
n.times {|i| ParanoidModel.create(text: "text #{i}") }
|
43
|
+
n.times {|i| MetaParanoidModel.create(text: "text #{i}") }
|
44
|
+
end
|
45
|
+
|
46
|
+
n = 100
|
47
|
+
|
48
|
+
puts 'text_search benchmark ***'
|
49
|
+
Benchmark.bm(20) do |x|
|
50
|
+
x.report('without') { n.times { Model.text_search('text').execute } }
|
51
|
+
x.report('with') { n.times { ParanoidModel.text_search('text').execute } }
|
52
|
+
x.report('meta') { n.times { MetaParanoidModel.text_search('text').execute } }
|
53
|
+
x.report('unscoped meta') { n.times { MetaParanoidModel.unscoped.text_search('text').execute } }
|
54
|
+
x.report('unscoped paranoid') { n.times { ParanoidModel.unscoped.text_search('text').execute } }
|
55
|
+
end
|
56
|
+
|
57
|
+
puts ''
|
58
|
+
puts 'Pluck all ids benchmark ***'
|
59
|
+
Benchmark.bm(20) do |x|
|
60
|
+
x.report('without') { n.times { Model.all.pluck(:id) } }
|
61
|
+
x.report('with') { n.times { ParanoidModel.all.pluck(:id) } }
|
62
|
+
x.report('meta') { n.times { MetaParanoidModel.all.pluck(:id) } }
|
63
|
+
x.report('unscoped meta') { n.times { MetaParanoidModel.unscoped.all.pluck(:id) } }
|
64
|
+
x.report('unscoped paranoid') { n.times { ParanoidModel.unscoped.all.pluck(:id) } }
|
65
|
+
end
|
data/spec/app/models/address.rb
CHANGED
@@ -1,71 +1,71 @@
|
|
1
|
-
class Address
|
2
|
-
include Mongoid::Document
|
3
|
-
|
4
|
-
field :_id, type: String, default: ->{ street.try(:parameterize) }
|
5
|
-
|
6
|
-
attr_accessor :mode
|
7
|
-
|
8
|
-
field :address_type
|
9
|
-
field :number, type: Integer
|
10
|
-
field :street
|
11
|
-
field :city
|
12
|
-
field :state
|
13
|
-
field :post_code
|
14
|
-
field :parent_title
|
15
|
-
field :services, type: Array
|
16
|
-
field :latlng, type: Array
|
17
|
-
field :map, type: Hash
|
18
|
-
field :move_in, type: DateTime
|
19
|
-
field :s, type: String, as: :suite
|
20
|
-
field :name, localize: true
|
21
|
-
|
22
|
-
embeds_one :code, validate: false
|
23
|
-
embeds_one :target, as: :targetable, validate: false
|
24
|
-
|
25
|
-
embedded_in :addressable, polymorphic: true do
|
26
|
-
def extension
|
27
|
-
"Testing"
|
28
|
-
end
|
29
|
-
def doctor?
|
30
|
-
title == "Dr"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
accepts_nested_attributes_for :code, :target
|
35
|
-
|
36
|
-
belongs_to :account
|
37
|
-
|
38
|
-
scope :without_postcode, -> {where(postcode: nil)}
|
39
|
-
scope :rodeo, -> {
|
40
|
-
where(street: "Rodeo Dr") do
|
41
|
-
def mansion?
|
42
|
-
all? { |address| address.street == "Rodeo Dr" }
|
43
|
-
end
|
44
|
-
end
|
45
|
-
}
|
46
|
-
|
47
|
-
validates_presence_of :street, on: :update
|
48
|
-
validates_format_of :street, with: /\D/, allow_nil: true
|
49
|
-
|
50
|
-
def set_parent=(set = false)
|
51
|
-
self.parent_title = addressable.title if set
|
52
|
-
end
|
53
|
-
|
54
|
-
def <=>(other)
|
55
|
-
street <=> other.street
|
56
|
-
end
|
57
|
-
|
58
|
-
class << self
|
59
|
-
def california
|
60
|
-
where(state: "CA")
|
61
|
-
end
|
62
|
-
|
63
|
-
def homes
|
64
|
-
where(address_type: "Home")
|
65
|
-
end
|
66
|
-
|
67
|
-
def streets
|
68
|
-
all.map(&:street)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
1
|
+
class Address
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :_id, type: String, default: ->{ street.try(:parameterize) }
|
5
|
+
|
6
|
+
attr_accessor :mode
|
7
|
+
|
8
|
+
field :address_type
|
9
|
+
field :number, type: Integer
|
10
|
+
field :street
|
11
|
+
field :city
|
12
|
+
field :state
|
13
|
+
field :post_code
|
14
|
+
field :parent_title
|
15
|
+
field :services, type: Array
|
16
|
+
field :latlng, type: Array
|
17
|
+
field :map, type: Hash
|
18
|
+
field :move_in, type: DateTime
|
19
|
+
field :s, type: String, as: :suite
|
20
|
+
field :name, localize: true
|
21
|
+
|
22
|
+
embeds_one :code, validate: false
|
23
|
+
embeds_one :target, as: :targetable, validate: false
|
24
|
+
|
25
|
+
embedded_in :addressable, polymorphic: true do
|
26
|
+
def extension
|
27
|
+
"Testing"
|
28
|
+
end
|
29
|
+
def doctor?
|
30
|
+
title == "Dr"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
accepts_nested_attributes_for :code, :target
|
35
|
+
|
36
|
+
belongs_to :account
|
37
|
+
|
38
|
+
scope :without_postcode, -> {where(postcode: nil)}
|
39
|
+
scope :rodeo, -> {
|
40
|
+
where(street: "Rodeo Dr") do
|
41
|
+
def mansion?
|
42
|
+
all? { |address| address.street == "Rodeo Dr" }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
}
|
46
|
+
|
47
|
+
validates_presence_of :street, on: :update
|
48
|
+
validates_format_of :street, with: /\D/, allow_nil: true
|
49
|
+
|
50
|
+
def set_parent=(set = false)
|
51
|
+
self.parent_title = addressable.title if set
|
52
|
+
end
|
53
|
+
|
54
|
+
def <=>(other)
|
55
|
+
street <=> other.street
|
56
|
+
end
|
57
|
+
|
58
|
+
class << self
|
59
|
+
def california
|
60
|
+
where(state: "CA")
|
61
|
+
end
|
62
|
+
|
63
|
+
def homes
|
64
|
+
where(address_type: "Home")
|
65
|
+
end
|
66
|
+
|
67
|
+
def streets
|
68
|
+
all.map(&:street)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|