perpetuity 0.7.3 → 1.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- 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
|