perpetuity 0.4.7 → 0.4.8
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.
- data/CHANGELOG.md +9 -0
- data/lib/perpetuity/dereferencer.rb +47 -0
- data/lib/perpetuity/identity_map.rb +10 -18
- data/lib/perpetuity/mapper.rb +11 -12
- data/lib/perpetuity/mongodb/serializer.rb +151 -0
- data/lib/perpetuity/mongodb.rb +33 -27
- data/lib/perpetuity/persisted_object.rb +1 -1
- data/lib/perpetuity/retrieval.rb +9 -8
- data/lib/perpetuity/version.rb +1 -1
- data/lib/perpetuity.rb +7 -1
- data/spec/integration/associations_spec.rb +33 -1
- data/spec/integration/mongodb_spec.rb +7 -0
- data/spec/integration/pagination_spec.rb +1 -1
- data/spec/integration/retrieval_spec.rb +41 -23
- data/spec/integration/update_spec.rb +18 -0
- data/spec/perpetuity/dereferencer_spec.rb +23 -0
- data/spec/perpetuity/identity_map_spec.rb +22 -0
- data/spec/perpetuity/mapper_spec.rb +0 -19
- data/spec/perpetuity/mongodb/serializer_spec.rb +117 -0
- data/spec/perpetuity/retrieval_spec.rb +4 -10
- data/spec/spec_helper.rb +1 -4
- data/spec/support/test_classes/generic_object.rb +3 -0
- data/spec/support/test_classes/user.rb +4 -0
- data/spec/support/test_classes.rb +6 -1
- metadata +20 -13
- data/lib/perpetuity/serializer.rb +0 -147
- data/spec/perpetuity/serializer_spec.rb +0 -86
@@ -1,147 +0,0 @@
|
|
1
|
-
require 'perpetuity/data_injectable'
|
2
|
-
|
3
|
-
module Perpetuity
|
4
|
-
class Serializer
|
5
|
-
include DataInjectable
|
6
|
-
|
7
|
-
attr_reader :mapper, :mapper_registry
|
8
|
-
|
9
|
-
def initialize(mapper)
|
10
|
-
@mapper = mapper
|
11
|
-
@class = mapper.mapped_class
|
12
|
-
@mapper_registry = mapper.mapper_registry
|
13
|
-
end
|
14
|
-
|
15
|
-
def attribute_for object, attribute_name
|
16
|
-
object.instance_variable_get("@#{attribute_name}")
|
17
|
-
end
|
18
|
-
|
19
|
-
def serialize object
|
20
|
-
attrs = mapper.class.attribute_set.map do |attrib|
|
21
|
-
value = attribute_for object, attrib.name
|
22
|
-
|
23
|
-
serialized_value = if value.is_a? Reference
|
24
|
-
serialize_reference value
|
25
|
-
elsif value.is_a? Array
|
26
|
-
serialize_array(value, attrib.embedded?)
|
27
|
-
elsif mapper.data_source.can_serialize? value
|
28
|
-
value
|
29
|
-
elsif mapper_registry.has_mapper?(value.class)
|
30
|
-
serialize_with_foreign_mapper(value, attrib.embedded?)
|
31
|
-
else
|
32
|
-
Marshal.dump(value)
|
33
|
-
end
|
34
|
-
|
35
|
-
[attrib.name.to_s, serialized_value]
|
36
|
-
end
|
37
|
-
|
38
|
-
Hash[attrs]
|
39
|
-
end
|
40
|
-
|
41
|
-
def unserialize data
|
42
|
-
if data.is_a? Array
|
43
|
-
unserialize_object_array data
|
44
|
-
else
|
45
|
-
object = unserialize_object(data)
|
46
|
-
give_id_to object
|
47
|
-
object
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def unserialize_object data, klass=@class
|
52
|
-
if data.is_a? Hash
|
53
|
-
object = klass.allocate
|
54
|
-
data.each do |attr, value|
|
55
|
-
inject_attribute object, attr, unserialize_attribute(value)
|
56
|
-
end
|
57
|
-
object
|
58
|
-
else
|
59
|
-
unserialize_attribute data
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def unserialize_object_array objects
|
64
|
-
objects.map do |data|
|
65
|
-
object = unserialize_object data
|
66
|
-
give_id_to object
|
67
|
-
object
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def unserialize_attribute data
|
72
|
-
if data.is_a?(String) && data.start_with?("\u0004") # if it's marshaled
|
73
|
-
Marshal.load(data)
|
74
|
-
elsif data.is_a? Array
|
75
|
-
data.map { |i| unserialize_attribute i }
|
76
|
-
elsif data.is_a? Hash
|
77
|
-
metadata = data.delete('__metadata__')
|
78
|
-
if metadata
|
79
|
-
klass = metadata['class'].split('::').inject(Kernel) do |scope, const_name|
|
80
|
-
scope.const_get(const_name)
|
81
|
-
end
|
82
|
-
id = metadata['id']
|
83
|
-
|
84
|
-
if id
|
85
|
-
object = Reference.new(klass, id)
|
86
|
-
else
|
87
|
-
object = unserialize_object(data, klass)
|
88
|
-
end
|
89
|
-
else
|
90
|
-
data
|
91
|
-
end
|
92
|
-
else
|
93
|
-
data
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def serialize_with_foreign_mapper value, embedded = false
|
98
|
-
if embedded
|
99
|
-
value_mapper = mapper_registry[value.class]
|
100
|
-
value_serializer = Serializer.new(value_mapper)
|
101
|
-
attr = value_serializer.serialize(value)
|
102
|
-
attr.merge '__metadata__' => { 'class' => value.class }
|
103
|
-
else
|
104
|
-
serialize_reference(value)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def serialize_array enum, embedded
|
109
|
-
enum.map do |value|
|
110
|
-
if value.is_a? Array
|
111
|
-
serialize_array(value)
|
112
|
-
elsif mapper.data_source.can_serialize? value
|
113
|
-
value
|
114
|
-
elsif mapper_registry.has_mapper?(value.class)
|
115
|
-
if embedded
|
116
|
-
{
|
117
|
-
'__metadata__' => {
|
118
|
-
'class' => value.class.to_s
|
119
|
-
}
|
120
|
-
}.merge mapper_registry[value.class].serialize(value)
|
121
|
-
else
|
122
|
-
serialize_reference value
|
123
|
-
end
|
124
|
-
else
|
125
|
-
Marshal.dump(value)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def serialize_reference value
|
131
|
-
if value.is_a? Reference
|
132
|
-
reference = value
|
133
|
-
else
|
134
|
-
unless value.is_a? PersistedObject
|
135
|
-
mapper_registry[value.class].insert value
|
136
|
-
end
|
137
|
-
reference = Reference.new(value.class.to_s, value.id)
|
138
|
-
end
|
139
|
-
{
|
140
|
-
'__metadata__' => {
|
141
|
-
'class' => reference.klass.to_s,
|
142
|
-
'id' => reference.id
|
143
|
-
}
|
144
|
-
}
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
require 'perpetuity/serializer'
|
2
|
-
require 'perpetuity/mapper'
|
3
|
-
require 'perpetuity/mapper_registry'
|
4
|
-
require 'support/test_classes/book'
|
5
|
-
require 'support/test_classes/user'
|
6
|
-
|
7
|
-
module Perpetuity
|
8
|
-
describe Serializer do
|
9
|
-
let(:dave) { User.new('Dave') }
|
10
|
-
let(:andy) { User.new('Andy') }
|
11
|
-
let(:authors) { [dave, andy] }
|
12
|
-
let(:book) { Book.new('The Pragmatic Programmer', authors) }
|
13
|
-
let(:mapper_registry) { MapperRegistry.new }
|
14
|
-
let!(:book_mapper_class) do
|
15
|
-
registry = mapper_registry
|
16
|
-
Class.new(Perpetuity::Mapper) do
|
17
|
-
map Book, registry
|
18
|
-
attribute :title
|
19
|
-
attribute :authors
|
20
|
-
end
|
21
|
-
end
|
22
|
-
let!(:user_mapper_class) do
|
23
|
-
registry = mapper_registry
|
24
|
-
Class.new(Perpetuity::Mapper) do
|
25
|
-
map User, registry
|
26
|
-
attribute :name
|
27
|
-
end
|
28
|
-
end
|
29
|
-
let(:data_source) { double('Data Source') }
|
30
|
-
let(:serializer) { Serializer.new(mapper_registry[Book]) }
|
31
|
-
|
32
|
-
before do
|
33
|
-
dave.extend PersistedObject
|
34
|
-
andy.extend PersistedObject
|
35
|
-
user_mapper_class.stub(data_source: data_source)
|
36
|
-
book_mapper_class.stub(data_source: data_source)
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'serializes an array of non-embedded attributes as references' do
|
40
|
-
data_source.should_receive(:can_serialize?).with(book.title).and_return true
|
41
|
-
data_source.should_receive(:can_serialize?).with(dave).and_return false
|
42
|
-
data_source.should_receive(:can_serialize?).with(andy).and_return false
|
43
|
-
serializer.serialize(book).should be == {
|
44
|
-
'title' => book.title,
|
45
|
-
'authors' => [
|
46
|
-
{
|
47
|
-
'__metadata__' => {
|
48
|
-
'class' => 'User',
|
49
|
-
'id' => dave.id
|
50
|
-
}
|
51
|
-
},
|
52
|
-
{
|
53
|
-
'__metadata__' => {
|
54
|
-
'class' => 'User',
|
55
|
-
'id' => andy.id
|
56
|
-
}
|
57
|
-
}
|
58
|
-
]
|
59
|
-
}
|
60
|
-
end
|
61
|
-
|
62
|
-
context 'with objects that have hashes as attributes' do
|
63
|
-
let(:name_data) { {first_name: 'Jamie', last_name: 'Gaskins'} }
|
64
|
-
let(:serialized_data) do
|
65
|
-
{
|
66
|
-
'name' => name_data
|
67
|
-
}
|
68
|
-
end
|
69
|
-
let(:user) { User.new(name_data) }
|
70
|
-
let(:user_mapper) { mapper_registry[User] }
|
71
|
-
let(:user_serializer) { Serializer.new(user_mapper) }
|
72
|
-
|
73
|
-
before do
|
74
|
-
data_source.stub(:can_serialize?).with(name_data) { true }
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'serializes' do
|
78
|
-
user_serializer.serialize(user).should be == serialized_data
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'unserializes' do
|
82
|
-
user_serializer.unserialize(serialized_data).name.should be == user.name
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|