mongoid_paranoia 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/LICENSE +21 -21
- data/README.md +124 -110
- data/lib/mongoid-paranoia.rb +1 -1
- data/lib/mongoid/paranoia.rb +208 -154
- data/lib/mongoid/paranoia/configuration.rb +11 -0
- data/lib/mongoid/paranoia/monkey_patches.rb +113 -113
- data/lib/mongoid/paranoia/version.rb +5 -5
- data/lib/mongoid_paranoia.rb +1 -1
- data/perf/scope.rb +64 -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 -53
- data/spec/app/models/person.rb +21 -190
- data/spec/app/models/phone.rb +11 -11
- data/spec/app/models/relations.rb +247 -0
- data/spec/app/models/tag.rb +6 -6
- data/spec/app/models/title.rb +4 -4
- data/spec/mongoid/configuration_spec.rb +19 -0
- data/spec/mongoid/document_spec.rb +21 -21
- data/spec/mongoid/nested_attributes_spec.rb +164 -164
- data/spec/mongoid/paranoia_spec.rb +887 -751
- data/spec/mongoid/scoping_spec.rb +55 -55
- data/spec/mongoid/validatable/uniqueness_spec.rb +74 -74
- data/spec/spec_helper.rb +73 -80
- metadata +37 -19
@@ -1,113 +1,113 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
module Mongoid
|
3
|
-
module Paranoia
|
4
|
-
module Document
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
# Indicates whether or not the document includes Mongoid::Paranoia.
|
9
|
-
# In Mongoid 3, this method was defined on all Mongoid::Documents.
|
10
|
-
# In Mongoid 4, it is no longer defined, hence we are shimming it here.
|
11
|
-
class_attribute :paranoid
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
Mongoid::Document.send(:include, Mongoid::Paranoia::Document)
|
18
|
-
|
19
|
-
module Mongoid
|
20
|
-
module Relations
|
21
|
-
module Builders
|
22
|
-
module NestedAttributes
|
23
|
-
class Many < NestedBuilder
|
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
|
-
end
|
50
|
-
|
51
|
-
module Mongoid
|
52
|
-
module Relations
|
53
|
-
module Embedded
|
54
|
-
# This class handles the behaviour for a document that embeds many other
|
55
|
-
# documents within in it as an array.
|
56
|
-
class Many < Relations::Many
|
57
|
-
# Delete the supplied document from the target. This method is proxied
|
58
|
-
# in order to reindex the array after the operation occurs.
|
59
|
-
#
|
60
|
-
# @example Delete the document from the relation.
|
61
|
-
# person.addresses.delete(address)
|
62
|
-
#
|
63
|
-
# @param [ Document ] document The document to be deleted.
|
64
|
-
#
|
65
|
-
# @return [ Document, nil ] The deleted document or nil if nothing deleted.
|
66
|
-
#
|
67
|
-
# @since 2.0.0.rc.1
|
68
|
-
def delete(document)
|
69
|
-
execute_callback :before_remove, document
|
70
|
-
doc = target.delete_one(document)
|
71
|
-
if doc && !_binding?
|
72
|
-
_unscoped.delete_one(doc) unless doc.paranoid?
|
73
|
-
if _assigning?
|
74
|
-
if doc.paranoid?
|
75
|
-
doc.destroy(suppress: true)
|
76
|
-
else
|
77
|
-
base.add_atomic_pull(doc)
|
78
|
-
end
|
79
|
-
else
|
80
|
-
doc.delete(suppress: true)
|
81
|
-
unbind_one(doc)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
reindex
|
85
|
-
execute_callback :after_remove, document
|
86
|
-
doc
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
module Mongoid
|
94
|
-
module Relations
|
95
|
-
module Embedded
|
96
|
-
class Many < Relations::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
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Paranoia
|
4
|
+
module Document
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
# Indicates whether or not the document includes Mongoid::Paranoia.
|
9
|
+
# In Mongoid 3, this method was defined on all Mongoid::Documents.
|
10
|
+
# In Mongoid 4, it is no longer defined, hence we are shimming it here.
|
11
|
+
class_attribute :paranoid
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Mongoid::Document.send(:include, Mongoid::Paranoia::Document)
|
18
|
+
|
19
|
+
module Mongoid
|
20
|
+
module Relations
|
21
|
+
module Builders
|
22
|
+
module NestedAttributes
|
23
|
+
class Many < NestedBuilder
|
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
|
+
end
|
50
|
+
|
51
|
+
module Mongoid
|
52
|
+
module Relations
|
53
|
+
module Embedded
|
54
|
+
# This class handles the behaviour for a document that embeds many other
|
55
|
+
# documents within in it as an array.
|
56
|
+
class Many < Relations::Many
|
57
|
+
# Delete the supplied document from the target. This method is proxied
|
58
|
+
# in order to reindex the array after the operation occurs.
|
59
|
+
#
|
60
|
+
# @example Delete the document from the relation.
|
61
|
+
# person.addresses.delete(address)
|
62
|
+
#
|
63
|
+
# @param [ Document ] document The document to be deleted.
|
64
|
+
#
|
65
|
+
# @return [ Document, nil ] The deleted document or nil if nothing deleted.
|
66
|
+
#
|
67
|
+
# @since 2.0.0.rc.1
|
68
|
+
def delete(document)
|
69
|
+
execute_callback :before_remove, document
|
70
|
+
doc = target.delete_one(document)
|
71
|
+
if doc && !_binding?
|
72
|
+
_unscoped.delete_one(doc) unless doc.paranoid?
|
73
|
+
if _assigning?
|
74
|
+
if doc.paranoid?
|
75
|
+
doc.destroy(suppress: true)
|
76
|
+
else
|
77
|
+
base.add_atomic_pull(doc)
|
78
|
+
end
|
79
|
+
else
|
80
|
+
doc.delete(suppress: true)
|
81
|
+
unbind_one(doc)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
reindex
|
85
|
+
execute_callback :after_remove, document
|
86
|
+
doc
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
module Mongoid
|
94
|
+
module Relations
|
95
|
+
module Embedded
|
96
|
+
class Many < Relations::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
|
@@ -1,5 +1,5 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Paranoia
|
3
|
-
VERSION = '0.
|
4
|
-
end
|
5
|
-
end
|
1
|
+
module Mongoid
|
2
|
+
module Paranoia
|
3
|
+
VERSION = '0.2.0'
|
4
|
+
end
|
5
|
+
end
|
data/lib/mongoid_paranoia.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require "mongoid/paranoia"
|
1
|
+
require "mongoid/paranoia"
|
data/perf/scope.rb
CHANGED
@@ -1,64 +1,64 @@
|
|
1
|
-
require 'bundler/setup'
|
2
|
-
require 'mongoid'
|
3
|
-
require 'mongoid/paranoia'
|
4
|
-
require 'benchmark'
|
5
|
-
|
6
|
-
|
7
|
-
Mongoid.configure do |config|
|
8
|
-
config.connect_to('my_little_test')
|
9
|
-
end
|
10
|
-
|
11
|
-
class Model
|
12
|
-
include Mongoid::Document
|
13
|
-
field :text, type: String
|
14
|
-
|
15
|
-
index({ text: "text" })
|
16
|
-
end
|
17
|
-
|
18
|
-
class ParanoidModel
|
19
|
-
include Mongoid::Document
|
20
|
-
include Mongoid::Paranoia
|
21
|
-
field :text, type: String
|
22
|
-
|
23
|
-
index({ text: "text" })
|
24
|
-
end
|
25
|
-
|
26
|
-
class MetaParanoidModel
|
27
|
-
include Mongoid::Document
|
28
|
-
field :text, type: String
|
29
|
-
field :deleted_at, type: Time
|
30
|
-
default_scope -> { where(deleted_at: nil) }
|
31
|
-
|
32
|
-
index({ text: "text" })
|
33
|
-
end
|
34
|
-
|
35
|
-
if ENV['FORCE']
|
36
|
-
Mongoid.purge!
|
37
|
-
::Mongoid::Tasks::Database.create_indexes
|
38
|
-
|
39
|
-
n = 50_000
|
40
|
-
n.times {|i| Model.create(text: "text #{i}")}
|
41
|
-
n.times {|i| ParanoidModel.create(text: "text #{i}")}
|
42
|
-
n.times {|i| MetaParanoidModel.create(text: "text #{i}")}
|
43
|
-
end
|
44
|
-
|
45
|
-
n = 100
|
46
|
-
|
47
|
-
puts "text_search benchmark ***"
|
48
|
-
Benchmark.bm(20) do |x|
|
49
|
-
x.report("without") { n.times { Model.text_search("text").execute } }
|
50
|
-
x.report("with") { n.times { ParanoidModel.text_search("text").execute } }
|
51
|
-
x.report("meta") { n.times { MetaParanoidModel.text_search("text").execute } }
|
52
|
-
x.report("unscoped meta") { n.times { MetaParanoidModel.unscoped.text_search("text").execute } }
|
53
|
-
x.report("unscoped paranoid") { n.times { ParanoidModel.unscoped.text_search("text").execute } }
|
54
|
-
end
|
55
|
-
|
56
|
-
puts ""
|
57
|
-
puts "Pluck all ids benchmark ***"
|
58
|
-
Benchmark.bm(20) do |x|
|
59
|
-
x.report("without") { n.times { Model.all.pluck(:id) } }
|
60
|
-
x.report("with") { n.times { ParanoidModel.all.pluck(:id) } }
|
61
|
-
x.report("meta") { n.times { MetaParanoidModel.all.pluck(:id) } }
|
62
|
-
x.report("unscoped meta") { n.times { MetaParanoidModel.unscoped.all.pluck(:id) } }
|
63
|
-
x.report("unscoped paranoid") { n.times { ParanoidModel.unscoped.all.pluck(:id) } }
|
64
|
-
end
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'mongoid'
|
3
|
+
require 'mongoid/paranoia'
|
4
|
+
require 'benchmark'
|
5
|
+
|
6
|
+
|
7
|
+
Mongoid.configure do |config|
|
8
|
+
config.connect_to('my_little_test')
|
9
|
+
end
|
10
|
+
|
11
|
+
class Model
|
12
|
+
include Mongoid::Document
|
13
|
+
field :text, type: String
|
14
|
+
|
15
|
+
index({ text: "text" })
|
16
|
+
end
|
17
|
+
|
18
|
+
class ParanoidModel
|
19
|
+
include Mongoid::Document
|
20
|
+
include Mongoid::Paranoia
|
21
|
+
field :text, type: String
|
22
|
+
|
23
|
+
index({ text: "text" })
|
24
|
+
end
|
25
|
+
|
26
|
+
class MetaParanoidModel
|
27
|
+
include Mongoid::Document
|
28
|
+
field :text, type: String
|
29
|
+
field :deleted_at, type: Time
|
30
|
+
default_scope -> { where(deleted_at: nil) }
|
31
|
+
|
32
|
+
index({ text: "text" })
|
33
|
+
end
|
34
|
+
|
35
|
+
if ENV['FORCE']
|
36
|
+
Mongoid.purge!
|
37
|
+
::Mongoid::Tasks::Database.create_indexes
|
38
|
+
|
39
|
+
n = 50_000
|
40
|
+
n.times {|i| Model.create(text: "text #{i}")}
|
41
|
+
n.times {|i| ParanoidModel.create(text: "text #{i}")}
|
42
|
+
n.times {|i| MetaParanoidModel.create(text: "text #{i}")}
|
43
|
+
end
|
44
|
+
|
45
|
+
n = 100
|
46
|
+
|
47
|
+
puts "text_search benchmark ***"
|
48
|
+
Benchmark.bm(20) do |x|
|
49
|
+
x.report("without") { n.times { Model.text_search("text").execute } }
|
50
|
+
x.report("with") { n.times { ParanoidModel.text_search("text").execute } }
|
51
|
+
x.report("meta") { n.times { MetaParanoidModel.text_search("text").execute } }
|
52
|
+
x.report("unscoped meta") { n.times { MetaParanoidModel.unscoped.text_search("text").execute } }
|
53
|
+
x.report("unscoped paranoid") { n.times { ParanoidModel.unscoped.text_search("text").execute } }
|
54
|
+
end
|
55
|
+
|
56
|
+
puts ""
|
57
|
+
puts "Pluck all ids benchmark ***"
|
58
|
+
Benchmark.bm(20) do |x|
|
59
|
+
x.report("without") { n.times { Model.all.pluck(:id) } }
|
60
|
+
x.report("with") { n.times { ParanoidModel.all.pluck(:id) } }
|
61
|
+
x.report("meta") { n.times { MetaParanoidModel.all.pluck(:id) } }
|
62
|
+
x.report("unscoped meta") { n.times { MetaParanoidModel.unscoped.all.pluck(:id) } }
|
63
|
+
x.report("unscoped paranoid") { n.times { ParanoidModel.unscoped.all.pluck(:id) } }
|
64
|
+
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
|