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 +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
|