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