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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile +3 -0
  4. data/README.md +18 -8
  5. data/lib/perpetuity.rb +4 -4
  6. data/lib/perpetuity/attribute.rb +9 -0
  7. data/lib/perpetuity/attribute_set.rb +4 -6
  8. data/lib/perpetuity/data_injectable.rb +1 -1
  9. data/lib/perpetuity/duplicator.rb +27 -0
  10. data/lib/perpetuity/mapper.rb +9 -14
  11. data/lib/perpetuity/version.rb +1 -1
  12. data/perpetuity.gemspec +0 -1
  13. data/spec/integration/associations_spec.rb +2 -6
  14. data/spec/integration/indexing_spec.rb +1 -1
  15. data/spec/integration/persistence_spec.rb +3 -2
  16. data/spec/integration/retrieval_spec.rb +5 -13
  17. data/spec/perpetuity/attribute_set_spec.rb +1 -1
  18. data/spec/perpetuity/attribute_spec.rb +6 -1
  19. data/spec/perpetuity/duplicator_spec.rb +35 -0
  20. data/spec/perpetuity/mapper_spec.rb +21 -2
  21. data/spec/perpetuity_spec.rb +2 -2
  22. data/spec/spec_helper.rb +8 -2
  23. data/spec/support/test_classes.rb +22 -26
  24. data/spec/support/test_classes/topic.rb +5 -0
  25. data/spec/support/test_classes/user.rb +1 -1
  26. metadata +7 -55
  27. data/lib/perpetuity/mongodb.rb +0 -230
  28. data/lib/perpetuity/mongodb/index.rb +0 -52
  29. data/lib/perpetuity/mongodb/nil_query.rb +0 -11
  30. data/lib/perpetuity/mongodb/query.rb +0 -33
  31. data/lib/perpetuity/mongodb/query_attribute.rb +0 -66
  32. data/lib/perpetuity/mongodb/query_expression.rb +0 -94
  33. data/lib/perpetuity/mongodb/query_intersection.rb +0 -16
  34. data/lib/perpetuity/mongodb/query_union.rb +0 -16
  35. data/lib/perpetuity/mongodb/serializer.rb +0 -174
  36. data/lib/perpetuity/validations.rb +0 -1
  37. data/lib/perpetuity/validations/length.rb +0 -36
  38. data/lib/perpetuity/validations/presence.rb +0 -14
  39. data/lib/perpetuity/validations/validation_set.rb +0 -28
  40. data/spec/integration/mongodb_spec.rb +0 -218
  41. data/spec/integration/validations_spec.rb +0 -17
  42. data/spec/perpetuity/mongodb/index_spec.rb +0 -44
  43. data/spec/perpetuity/mongodb/query_attribute_spec.rb +0 -58
  44. data/spec/perpetuity/mongodb/query_expression_spec.rb +0 -67
  45. data/spec/perpetuity/mongodb/query_intersection_spec.rb +0 -16
  46. data/spec/perpetuity/mongodb/query_spec.rb +0 -79
  47. data/spec/perpetuity/mongodb/query_union_spec.rb +0 -16
  48. data/spec/perpetuity/mongodb/serializer_spec.rb +0 -212
  49. data/spec/perpetuity/validations/length_spec.rb +0 -53
  50. data/spec/perpetuity/validations/presence_spec.rb +0 -30
  51. 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,11 +0,0 @@
1
- module Perpetuity
2
- class NilQuery
3
- def self.new
4
- @instance ||= allocate
5
- end
6
-
7
- def to_db
8
- {}
9
- end
10
- end
11
- 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,16 +0,0 @@
1
- module Perpetuity
2
- class MongoDB
3
- class QueryIntersection
4
- attr_reader :lhs, :rhs
5
-
6
- def initialize lhs, rhs
7
- @lhs = lhs
8
- @rhs = rhs
9
- end
10
-
11
- def to_db
12
- { '$and' => [lhs.to_db, rhs.to_db] }
13
- end
14
- end
15
- end
16
- end
@@ -1,16 +0,0 @@
1
- module Perpetuity
2
- class MongoDB
3
- class QueryUnion
4
- attr_reader :lhs, :rhs
5
-
6
- def initialize lhs, rhs
7
- @lhs = lhs
8
- @rhs = rhs
9
- end
10
-
11
- def to_db
12
- { '$or' => [lhs.to_db, rhs.to_db] }
13
- end
14
- end
15
- end
16
- 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