perpetuity 0.7.3 → 1.0.0.beta
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 +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile +3 -0
- data/README.md +18 -8
- data/lib/perpetuity.rb +4 -4
- data/lib/perpetuity/attribute.rb +9 -0
- data/lib/perpetuity/attribute_set.rb +4 -6
- data/lib/perpetuity/data_injectable.rb +1 -1
- data/lib/perpetuity/duplicator.rb +27 -0
- data/lib/perpetuity/mapper.rb +9 -14
- data/lib/perpetuity/version.rb +1 -1
- data/perpetuity.gemspec +0 -1
- data/spec/integration/associations_spec.rb +2 -6
- data/spec/integration/indexing_spec.rb +1 -1
- data/spec/integration/persistence_spec.rb +3 -2
- data/spec/integration/retrieval_spec.rb +5 -13
- data/spec/perpetuity/attribute_set_spec.rb +1 -1
- data/spec/perpetuity/attribute_spec.rb +6 -1
- data/spec/perpetuity/duplicator_spec.rb +35 -0
- data/spec/perpetuity/mapper_spec.rb +21 -2
- data/spec/perpetuity_spec.rb +2 -2
- data/spec/spec_helper.rb +8 -2
- data/spec/support/test_classes.rb +22 -26
- data/spec/support/test_classes/topic.rb +5 -0
- data/spec/support/test_classes/user.rb +1 -1
- metadata +7 -55
- data/lib/perpetuity/mongodb.rb +0 -230
- data/lib/perpetuity/mongodb/index.rb +0 -52
- data/lib/perpetuity/mongodb/nil_query.rb +0 -11
- data/lib/perpetuity/mongodb/query.rb +0 -33
- data/lib/perpetuity/mongodb/query_attribute.rb +0 -66
- data/lib/perpetuity/mongodb/query_expression.rb +0 -94
- data/lib/perpetuity/mongodb/query_intersection.rb +0 -16
- data/lib/perpetuity/mongodb/query_union.rb +0 -16
- data/lib/perpetuity/mongodb/serializer.rb +0 -174
- data/lib/perpetuity/validations.rb +0 -1
- data/lib/perpetuity/validations/length.rb +0 -36
- data/lib/perpetuity/validations/presence.rb +0 -14
- data/lib/perpetuity/validations/validation_set.rb +0 -28
- data/spec/integration/mongodb_spec.rb +0 -218
- data/spec/integration/validations_spec.rb +0 -17
- data/spec/perpetuity/mongodb/index_spec.rb +0 -44
- data/spec/perpetuity/mongodb/query_attribute_spec.rb +0 -58
- data/spec/perpetuity/mongodb/query_expression_spec.rb +0 -67
- data/spec/perpetuity/mongodb/query_intersection_spec.rb +0 -16
- data/spec/perpetuity/mongodb/query_spec.rb +0 -79
- data/spec/perpetuity/mongodb/query_union_spec.rb +0 -16
- data/spec/perpetuity/mongodb/serializer_spec.rb +0 -212
- data/spec/perpetuity/validations/length_spec.rb +0 -53
- data/spec/perpetuity/validations/presence_spec.rb +0 -30
- data/spec/perpetuity/validations_spec.rb +0 -87
@@ -1,52 +0,0 @@
|
|
1
|
-
module Perpetuity
|
2
|
-
class MongoDB
|
3
|
-
class Index
|
4
|
-
KEY_ORDERS = { 1 => :ascending, -1 => :descending }
|
5
|
-
attr_reader :collection, :attribute
|
6
|
-
|
7
|
-
def initialize klass, attribute, options={}
|
8
|
-
@collection = klass
|
9
|
-
@attribute = attribute
|
10
|
-
@unique = options.fetch(:unique) { false }
|
11
|
-
@order = options.fetch(:order) { :ascending }
|
12
|
-
@activated = false
|
13
|
-
end
|
14
|
-
|
15
|
-
def active?
|
16
|
-
@activated
|
17
|
-
end
|
18
|
-
|
19
|
-
def inactive?
|
20
|
-
!active?
|
21
|
-
end
|
22
|
-
|
23
|
-
def activate!
|
24
|
-
@activated = true
|
25
|
-
end
|
26
|
-
|
27
|
-
def unique?
|
28
|
-
@unique
|
29
|
-
end
|
30
|
-
|
31
|
-
def order
|
32
|
-
@order
|
33
|
-
end
|
34
|
-
|
35
|
-
def == other
|
36
|
-
hash == other.hash
|
37
|
-
end
|
38
|
-
|
39
|
-
def eql? other
|
40
|
-
self == other
|
41
|
-
end
|
42
|
-
|
43
|
-
def attribute_name
|
44
|
-
attribute.respond_to?(:name) ? attribute.name : attribute
|
45
|
-
end
|
46
|
-
|
47
|
-
def hash
|
48
|
-
"#{collection}/#{attribute_name}:#{unique?}:#{order}".hash
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'perpetuity/mongodb/query_attribute'
|
2
|
-
require 'perpetuity/mongodb/nil_query'
|
3
|
-
|
4
|
-
module Perpetuity
|
5
|
-
class MongoDB
|
6
|
-
class Query
|
7
|
-
attr_reader :query
|
8
|
-
def initialize &block
|
9
|
-
if block_given?
|
10
|
-
@query = block.call(self)
|
11
|
-
else
|
12
|
-
@query = NilQuery.new
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def to_db
|
17
|
-
@query.to_db
|
18
|
-
end
|
19
|
-
|
20
|
-
def negate
|
21
|
-
@query.negate
|
22
|
-
end
|
23
|
-
|
24
|
-
def method_missing missing_method
|
25
|
-
QueryAttribute.new missing_method
|
26
|
-
end
|
27
|
-
|
28
|
-
def == other
|
29
|
-
query == other.query
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'perpetuity/mongodb/query_expression'
|
2
|
-
|
3
|
-
module Perpetuity
|
4
|
-
class MongoDB
|
5
|
-
class QueryAttribute
|
6
|
-
attr_reader :name
|
7
|
-
|
8
|
-
def initialize name
|
9
|
-
@name = name
|
10
|
-
end
|
11
|
-
|
12
|
-
def == value
|
13
|
-
QueryExpression.new self, :equals, value
|
14
|
-
end
|
15
|
-
|
16
|
-
def < value
|
17
|
-
QueryExpression.new self, :less_than, value
|
18
|
-
end
|
19
|
-
|
20
|
-
def >= value
|
21
|
-
QueryExpression.new self, :gte, value
|
22
|
-
end
|
23
|
-
|
24
|
-
def > value
|
25
|
-
QueryExpression.new self, :greater_than, value
|
26
|
-
end
|
27
|
-
|
28
|
-
def <= value
|
29
|
-
QueryExpression.new self, :lte, value
|
30
|
-
end
|
31
|
-
|
32
|
-
def != value
|
33
|
-
QueryExpression.new self, :not_equal, value
|
34
|
-
end
|
35
|
-
alias :not_equal? :'!='
|
36
|
-
|
37
|
-
def =~ regexp
|
38
|
-
QueryExpression.new self, :matches, regexp
|
39
|
-
end
|
40
|
-
|
41
|
-
def in collection
|
42
|
-
QueryExpression.new self, :in, collection
|
43
|
-
end
|
44
|
-
|
45
|
-
def to_sym
|
46
|
-
name
|
47
|
-
end
|
48
|
-
|
49
|
-
def to_db
|
50
|
-
((self != false) & (self != nil)).to_db
|
51
|
-
end
|
52
|
-
|
53
|
-
def method_missing name
|
54
|
-
if name.to_s == 'id'
|
55
|
-
name = :"#{self.name}.__metadata__.#{name}"
|
56
|
-
elsif name.to_s == 'klass'
|
57
|
-
name = :"#{self.name}.__metadata__.class"
|
58
|
-
else
|
59
|
-
name = :"#{self.name}.#{name}"
|
60
|
-
end
|
61
|
-
|
62
|
-
self.class.new(name)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,94 +0,0 @@
|
|
1
|
-
require 'perpetuity/mongodb/query_union'
|
2
|
-
require 'perpetuity/mongodb/query_intersection'
|
3
|
-
|
4
|
-
module Perpetuity
|
5
|
-
class MongoDB
|
6
|
-
class QueryExpression
|
7
|
-
attr_accessor :attribute, :comparator, :negated, :value
|
8
|
-
|
9
|
-
def initialize attribute, comparator, value
|
10
|
-
@attribute = attribute
|
11
|
-
@comparator = comparator
|
12
|
-
@value = value
|
13
|
-
@negated = false
|
14
|
-
|
15
|
-
@attribute = @attribute.to_sym if @attribute.respond_to? :to_sym
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_db
|
19
|
-
public_send @comparator
|
20
|
-
end
|
21
|
-
|
22
|
-
def equals
|
23
|
-
if @negated
|
24
|
-
{ @attribute => { '$ne' => @value } }
|
25
|
-
else
|
26
|
-
{ @attribute => @value }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def function func
|
31
|
-
f = { func => @value }
|
32
|
-
|
33
|
-
if @negated
|
34
|
-
{ @attribute => { '$not' => f } }
|
35
|
-
else
|
36
|
-
{ @attribute => f }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def less_than
|
41
|
-
function '$lt'
|
42
|
-
end
|
43
|
-
|
44
|
-
def lte
|
45
|
-
function '$lte'
|
46
|
-
end
|
47
|
-
|
48
|
-
def greater_than
|
49
|
-
function '$gt'
|
50
|
-
end
|
51
|
-
|
52
|
-
def gte
|
53
|
-
function '$gte'
|
54
|
-
end
|
55
|
-
|
56
|
-
def not_equal
|
57
|
-
function '$ne'
|
58
|
-
end
|
59
|
-
|
60
|
-
def in
|
61
|
-
function '$in'
|
62
|
-
end
|
63
|
-
|
64
|
-
def matches
|
65
|
-
if @negated
|
66
|
-
{ @attribute => { '$not' => @value } }
|
67
|
-
else
|
68
|
-
{ @attribute => @value }
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def | other
|
73
|
-
QueryUnion.new(self, other)
|
74
|
-
end
|
75
|
-
|
76
|
-
def & other
|
77
|
-
QueryIntersection.new(self, other)
|
78
|
-
end
|
79
|
-
|
80
|
-
def negate
|
81
|
-
expr = dup
|
82
|
-
expr.negated = true
|
83
|
-
expr
|
84
|
-
end
|
85
|
-
|
86
|
-
def == other
|
87
|
-
attribute == other.attribute &&
|
88
|
-
comparator == other.comparator &&
|
89
|
-
value == other.value &&
|
90
|
-
negated == other.negated
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
@@ -1,174 +0,0 @@
|
|
1
|
-
require 'perpetuity/data_injectable'
|
2
|
-
require 'perpetuity/reference'
|
3
|
-
|
4
|
-
module Perpetuity
|
5
|
-
class MongoDB
|
6
|
-
class Serializer
|
7
|
-
include DataInjectable
|
8
|
-
|
9
|
-
attr_reader :mapper, :mapper_registry
|
10
|
-
|
11
|
-
def initialize(mapper)
|
12
|
-
@mapper = mapper
|
13
|
-
@class = mapper.mapped_class
|
14
|
-
@mapper_registry = mapper.mapper_registry
|
15
|
-
end
|
16
|
-
|
17
|
-
def attribute_for object, attribute_name
|
18
|
-
object.instance_variable_get("@#{attribute_name}")
|
19
|
-
end
|
20
|
-
|
21
|
-
def has_attribute? object, attribute_name
|
22
|
-
object.instance_variable_defined? "@#{attribute_name}"
|
23
|
-
end
|
24
|
-
|
25
|
-
def serialize object
|
26
|
-
attrs = mapper.attribute_set.map do |attrib|
|
27
|
-
next unless has_attribute? object, attrib.name
|
28
|
-
|
29
|
-
value = attribute_for object, attrib.name
|
30
|
-
|
31
|
-
serialized_value = if value.is_a? Reference
|
32
|
-
serialize_reference value
|
33
|
-
elsif value.is_a? Array
|
34
|
-
serialize_array(value, attrib.embedded?)
|
35
|
-
elsif mapper.data_source.can_serialize? value
|
36
|
-
value
|
37
|
-
elsif mapper_registry.has_mapper?(value.class)
|
38
|
-
serialize_with_foreign_mapper(value, attrib.embedded?)
|
39
|
-
else
|
40
|
-
marshal(value)
|
41
|
-
end
|
42
|
-
|
43
|
-
[attrib.name.to_s, serialized_value]
|
44
|
-
end
|
45
|
-
|
46
|
-
Hash[attrs.compact]
|
47
|
-
end
|
48
|
-
|
49
|
-
def serialize_changes changed, original
|
50
|
-
Hash[Array(serialize(changed)) - Array(serialize(original))]
|
51
|
-
end
|
52
|
-
|
53
|
-
def unserialize data
|
54
|
-
if data.is_a? Array
|
55
|
-
unserialize_object_array data
|
56
|
-
else
|
57
|
-
object = unserialize_object(data)
|
58
|
-
give_id_to object
|
59
|
-
object
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def unserialize_object data, klass=@class
|
64
|
-
if data.is_a? Hash
|
65
|
-
object = klass.allocate
|
66
|
-
data.each do |attr, value|
|
67
|
-
inject_attribute object, attr, unserialize_attribute(value)
|
68
|
-
end
|
69
|
-
object
|
70
|
-
else
|
71
|
-
unserialize_attribute data
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def unserialize_object_array objects
|
76
|
-
objects.map do |data|
|
77
|
-
object = unserialize_object data
|
78
|
-
give_id_to object
|
79
|
-
object
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def unserialize_attribute data
|
84
|
-
return data.map { |i| unserialize_attribute i } if data.is_a? Array
|
85
|
-
return data unless data.is_a? Hash
|
86
|
-
metadata = data.fetch("__metadata__", {})
|
87
|
-
marshaled = data.fetch("__marshaled__", false)
|
88
|
-
|
89
|
-
if marshaled
|
90
|
-
value = data.fetch("value")
|
91
|
-
return unmarshal(value)
|
92
|
-
end
|
93
|
-
|
94
|
-
if metadata.any?
|
95
|
-
klass = metadata['class'].split('::').inject(Kernel) do |scope, const_name|
|
96
|
-
scope.const_get(const_name)
|
97
|
-
end
|
98
|
-
id = metadata['id']
|
99
|
-
|
100
|
-
if id
|
101
|
-
Reference.new(klass, id)
|
102
|
-
else
|
103
|
-
unserialize_object(data, klass)
|
104
|
-
end
|
105
|
-
else
|
106
|
-
data
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def serialize_with_foreign_mapper value, embedded = false
|
111
|
-
if embedded
|
112
|
-
value_mapper = mapper_registry[value.class]
|
113
|
-
value_serializer = Serializer.new(value_mapper)
|
114
|
-
attr = value_serializer.serialize(value)
|
115
|
-
attr.merge '__metadata__' => { 'class' => value.class }
|
116
|
-
else
|
117
|
-
serialize_reference(value)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def serialize_array enum, embedded
|
122
|
-
enum.map do |value|
|
123
|
-
if value.is_a? Reference
|
124
|
-
serialize_reference value
|
125
|
-
elsif value.is_a? Array
|
126
|
-
serialize_array(value)
|
127
|
-
elsif mapper.data_source.can_serialize? value
|
128
|
-
value
|
129
|
-
elsif mapper_registry.has_mapper?(value.class)
|
130
|
-
if embedded
|
131
|
-
{
|
132
|
-
'__metadata__' => {
|
133
|
-
'class' => value.class.to_s
|
134
|
-
}
|
135
|
-
}.merge mapper_registry[value.class].serialize(value)
|
136
|
-
else
|
137
|
-
serialize_reference value
|
138
|
-
end
|
139
|
-
else
|
140
|
-
marshal value
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def serialize_reference value
|
146
|
-
if value.is_a? Reference
|
147
|
-
reference = value
|
148
|
-
else
|
149
|
-
unless mapper.persisted? value
|
150
|
-
mapper_registry[value.class].insert value
|
151
|
-
end
|
152
|
-
reference = Reference.new(value.class.to_s, mapper.id_for(value))
|
153
|
-
end
|
154
|
-
{
|
155
|
-
'__metadata__' => {
|
156
|
-
'class' => reference.klass.to_s,
|
157
|
-
'id' => reference.id
|
158
|
-
}
|
159
|
-
}
|
160
|
-
end
|
161
|
-
|
162
|
-
def marshal value
|
163
|
-
{
|
164
|
-
'__marshaled__' => true,
|
165
|
-
'value' => Marshal.dump(value)
|
166
|
-
}
|
167
|
-
end
|
168
|
-
|
169
|
-
def unmarshal value
|
170
|
-
Marshal.load(value)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|