gom 0.2.0 → 0.3.0
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/README.rdoc +15 -0
- data/Rakefile +1 -1
- data/lib/gom.rb +1 -0
- data/lib/gom/object.rb +15 -19
- data/lib/gom/object/builder.rb +35 -33
- data/lib/gom/object/cached_builder.rb +23 -31
- data/lib/gom/object/collection.rb +49 -57
- data/lib/gom/object/draft.rb +17 -25
- data/lib/gom/object/id.rb +14 -22
- data/lib/gom/object/inspector.rb +46 -54
- data/lib/gom/object/mapping.rb +31 -47
- data/lib/gom/object/proxy.rb +25 -33
- data/lib/gom/spec.rb +11 -0
- data/lib/gom/spec/acceptance/adapter_that_needs_setup.rb +58 -0
- data/lib/gom/spec/acceptance/adapter_with_stateful_storage.rb +19 -21
- data/lib/gom/spec/acceptance/read_only_adapter_with_stateless_storage.rb +9 -8
- data/lib/gom/spec/object.rb +8 -0
- data/lib/gom/storage.rb +30 -26
- data/lib/gom/storage/adapter.rb +26 -43
- data/lib/gom/storage/configuration.rb +75 -68
- data/lib/gom/storage/configuration/view.rb +3 -16
- data/lib/gom/storage/configuration/view/class.rb +5 -22
- data/lib/gom/storage/configuration/view/map_reduce.rb +7 -24
- data/lib/gom/storage/fetcher.rb +24 -32
- data/lib/gom/storage/remover.rb +27 -35
- data/lib/gom/storage/saver.rb +35 -43
- data/spec/acceptance/adapter_spec.rb +16 -4
- data/spec/acceptance/fake_adapter_spec.rb +11 -0
- data/spec/acceptance/object_spec.rb +4 -1
- data/spec/fake_adapter.rb +12 -3
- data/spec/lib/gom/object/builder_spec.rb +5 -5
- data/spec/lib/gom/object/inspector_spec.rb +5 -9
- data/spec/lib/gom/object/mapping_spec.rb +27 -57
- data/spec/lib/gom/storage/adapter_spec.rb +1 -1
- data/spec/lib/gom/storage/configuration_spec.rb +33 -3
- data/spec/lib/gom/storage_spec.rb +19 -0
- metadata +50 -46
data/README.rdoc
CHANGED
@@ -24,6 +24,17 @@ Look at the adapter pages to see the adapter-specific configuration values.
|
|
24
24
|
|
25
25
|
== How to use
|
26
26
|
|
27
|
+
=== Setup the system
|
28
|
+
|
29
|
+
First step after the configuration has been read is to setup the whole storage system. This can be done by
|
30
|
+
|
31
|
+
GOM::Storage.setup
|
32
|
+
|
33
|
+
The call should be done during the initialization of your application and triggers each storage adapter to do his own
|
34
|
+
setup. To shutdown the system and trigger final clean ups simply call
|
35
|
+
|
36
|
+
GOM::Storage.teardown
|
37
|
+
|
27
38
|
=== Storing an object
|
28
39
|
|
29
40
|
To store an object just pass it to <tt>GOM::Storage.store</tt>.
|
@@ -179,3 +190,7 @@ Development has been done test-driven and the code follows at most the Clean Cod
|
|
179
190
|
removed by using the reek[http://github.com/kevinrutherford/reek] code smell detector.
|
180
191
|
|
181
192
|
This project is still experimental and under development. Any bug report and contribution is welcome!
|
193
|
+
|
194
|
+
== Support
|
195
|
+
|
196
|
+
Apart from contribution, support via Flattr[http://flattr.com/thing/108957/Generic-Object-Mapper-for-Ruby] is welcome.
|
data/Rakefile
CHANGED
data/lib/gom.rb
CHANGED
data/lib/gom/object.rb
CHANGED
@@ -1,26 +1,22 @@
|
|
1
1
|
|
2
|
-
module GOM
|
2
|
+
module GOM::Object
|
3
3
|
|
4
|
-
|
4
|
+
autoload :Builder, File.join(File.dirname(__FILE__), "object", "builder")
|
5
|
+
autoload :CachedBuilder, File.join(File.dirname(__FILE__), "object", "cached_builder")
|
6
|
+
autoload :Collection, File.join(File.dirname(__FILE__), "object", "collection")
|
7
|
+
autoload :Draft, File.join(File.dirname(__FILE__), "object", "draft")
|
8
|
+
autoload :Id, File.join(File.dirname(__FILE__), "object", "id")
|
9
|
+
autoload :Inspector, File.join(File.dirname(__FILE__), "object", "inspector")
|
10
|
+
autoload :Mapping, File.join(File.dirname(__FILE__), "object", "mapping")
|
11
|
+
autoload :Proxy, File.join(File.dirname(__FILE__), "object", "proxy")
|
5
12
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
autoload :Id, File.join(File.dirname(__FILE__), "object", "id")
|
11
|
-
autoload :Inspector, File.join(File.dirname(__FILE__), "object", "inspector")
|
12
|
-
autoload :Mapping, File.join(File.dirname(__FILE__), "object", "mapping")
|
13
|
-
autoload :Proxy, File.join(File.dirname(__FILE__), "object", "proxy")
|
14
|
-
|
15
|
-
def self.id(object)
|
16
|
-
id = Mapping.id_by_object object
|
17
|
-
id ? id.to_s : nil
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.reference(object)
|
21
|
-
Proxy.new object
|
22
|
-
end
|
13
|
+
def self.id(object)
|
14
|
+
id = Mapping.id_by_object object
|
15
|
+
id ? id.to_s : nil
|
16
|
+
end
|
23
17
|
|
18
|
+
def self.reference(object)
|
19
|
+
Proxy.new object
|
24
20
|
end
|
25
21
|
|
26
22
|
end
|
data/lib/gom/object/builder.rb
CHANGED
@@ -1,47 +1,49 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
# Build an object out of the given draft.
|
3
|
+
class GOM::Object::Builder
|
3
4
|
|
4
|
-
|
5
|
+
attr_accessor :draft
|
6
|
+
attr_writer :object
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
attr_accessor :draft
|
10
|
-
attr_writer :object
|
11
|
-
|
12
|
-
def initialize(draft, object = nil)
|
13
|
-
@draft, @object = draft, object
|
14
|
-
end
|
8
|
+
def initialize(draft, object = nil)
|
9
|
+
@draft, @object = draft, object
|
10
|
+
end
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
def object
|
13
|
+
initialize_object unless @object
|
14
|
+
set_properties
|
15
|
+
set_relations
|
16
|
+
@object
|
17
|
+
end
|
22
18
|
|
23
|
-
|
19
|
+
private
|
24
20
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
21
|
+
def initialize_object
|
22
|
+
set_class
|
23
|
+
arity = [ @klass.method(:new).arity, 0 ].max
|
24
|
+
@object = @klass.new *([ nil ] * arity)
|
25
|
+
end
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
27
|
+
def set_class
|
28
|
+
names = @draft.class_name.split "::"
|
29
|
+
names.shift if names.empty? || names.first.empty?
|
36
30
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
31
|
+
@klass = ::Object
|
32
|
+
names.each do |name|
|
33
|
+
@klass = @klass.const_defined?(name) ? @klass.const_get(name) : @klass.const_missing(name)
|
34
|
+
end
|
35
|
+
end
|
42
36
|
|
37
|
+
def set_properties
|
38
|
+
@draft.properties.each do |name, value|
|
39
|
+
@object.instance_variable_set :"@#{name}", value
|
43
40
|
end
|
41
|
+
end
|
44
42
|
|
43
|
+
def set_relations
|
44
|
+
@draft.relations.each do |name, value|
|
45
|
+
@object.instance_variable_set :"@#{name}", value
|
46
|
+
end
|
45
47
|
end
|
46
48
|
|
47
49
|
end
|
@@ -1,42 +1,34 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
# Build an object out of the given draft using Builder. Uses the object-id mapping
|
3
|
+
# for caching the results.
|
4
|
+
class GOM::Object::CachedBuilder
|
3
5
|
|
4
|
-
|
6
|
+
attr_accessor :draft
|
7
|
+
attr_accessor :id
|
5
8
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
attr_accessor :draft
|
11
|
-
attr_accessor :id
|
12
|
-
|
13
|
-
def initialize(draft, id = nil)
|
14
|
-
@draft, @id = draft, id
|
15
|
-
end
|
16
|
-
|
17
|
-
def object
|
18
|
-
check_mapping
|
19
|
-
build_object
|
20
|
-
set_mapping
|
21
|
-
@object
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
9
|
+
def initialize(draft, id = nil)
|
10
|
+
@draft, @id = draft, id
|
11
|
+
end
|
25
12
|
|
26
|
-
|
27
|
-
|
28
|
-
|
13
|
+
def object
|
14
|
+
check_mapping
|
15
|
+
build_object
|
16
|
+
set_mapping
|
17
|
+
@object
|
18
|
+
end
|
29
19
|
|
30
|
-
|
31
|
-
@object = GOM::Object::Builder.new(@draft, @object).object
|
32
|
-
end
|
20
|
+
private
|
33
21
|
|
34
|
-
|
35
|
-
|
36
|
-
|
22
|
+
def check_mapping
|
23
|
+
@object = GOM::Object::Mapping.object_by_id @id
|
24
|
+
end
|
37
25
|
|
38
|
-
|
26
|
+
def build_object
|
27
|
+
@object = GOM::Object::Builder.new(@draft, @object).object
|
28
|
+
end
|
39
29
|
|
30
|
+
def set_mapping
|
31
|
+
GOM::Object::Mapping.put @object, @id
|
40
32
|
end
|
41
33
|
|
42
34
|
end
|
@@ -1,72 +1,64 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
# A class for a collection of objects.
|
3
|
+
class GOM::Object::Collection
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
class Collection
|
8
|
-
|
9
|
-
def initialize(fetcher)
|
10
|
-
@fetcher = fetcher
|
11
|
-
end
|
12
|
-
|
13
|
-
def total_count
|
14
|
-
@fetcher.total_count
|
15
|
-
end
|
16
|
-
|
17
|
-
def respond_to?(method_name)
|
18
|
-
(@object_proxies || @rows).respond_to?(method_name)
|
19
|
-
end
|
20
|
-
|
21
|
-
def method_missing(method_name, *arguments, &block)
|
22
|
-
load unless (@object_proxies || @rows)
|
23
|
-
(@object_proxies || @rows).send method_name, *arguments, &block
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
5
|
+
def initialize(fetcher)
|
6
|
+
@fetcher = fetcher
|
7
|
+
end
|
27
8
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
elsif fetcher_has_ids?
|
32
|
-
load_object_proxies_from_ids
|
33
|
-
elsif fetcher_has_rows?
|
34
|
-
load_rows
|
35
|
-
else
|
36
|
-
raise NotImplementedError, "the collection fetcher doesn't provide drafts, ids nor rows."
|
37
|
-
end
|
38
|
-
end
|
9
|
+
def total_count
|
10
|
+
@fetcher.total_count
|
11
|
+
end
|
39
12
|
|
40
|
-
|
41
|
-
|
42
|
-
|
13
|
+
def respond_to?(method_name)
|
14
|
+
(@object_proxies || @rows).respond_to?(method_name)
|
15
|
+
end
|
43
16
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
17
|
+
def method_missing(method_name, *arguments, &block)
|
18
|
+
load unless (@object_proxies || @rows)
|
19
|
+
(@object_proxies || @rows).send method_name, *arguments, &block
|
20
|
+
end
|
49
21
|
|
50
|
-
|
51
|
-
|
52
|
-
|
22
|
+
private
|
23
|
+
|
24
|
+
def load
|
25
|
+
if fetcher_has_drafts?
|
26
|
+
load_object_proxies_from_drafts
|
27
|
+
elsif fetcher_has_ids?
|
28
|
+
load_object_proxies_from_ids
|
29
|
+
elsif fetcher_has_rows?
|
30
|
+
load_rows
|
31
|
+
else
|
32
|
+
raise NotImplementedError, "the collection fetcher doesn't provide drafts, ids nor rows."
|
33
|
+
end
|
34
|
+
end
|
53
35
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
36
|
+
def fetcher_has_drafts?
|
37
|
+
@fetcher.respond_to?(:drafts) && @fetcher.drafts
|
38
|
+
end
|
59
39
|
|
60
|
-
|
61
|
-
|
62
|
-
|
40
|
+
def load_object_proxies_from_drafts
|
41
|
+
@object_proxies = @fetcher.drafts.map do |draft|
|
42
|
+
GOM::Object::Proxy.new GOM::Object::CachedBuilder.new(draft).object
|
43
|
+
end
|
44
|
+
end
|
63
45
|
|
64
|
-
|
65
|
-
|
66
|
-
|
46
|
+
def fetcher_has_ids?
|
47
|
+
@fetcher.respond_to?(:ids) && @fetcher.ids
|
48
|
+
end
|
67
49
|
|
50
|
+
def load_object_proxies_from_ids
|
51
|
+
@object_proxies = @fetcher.ids.map do |id|
|
52
|
+
GOM::Object::Proxy.new id
|
68
53
|
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def fetcher_has_rows?
|
57
|
+
@fetcher.respond_to?(:rows) && @fetcher.rows
|
58
|
+
end
|
69
59
|
|
60
|
+
def load_rows
|
61
|
+
@rows = @fetcher.rows
|
70
62
|
end
|
71
63
|
|
72
64
|
end
|
data/lib/gom/object/draft.rb
CHANGED
@@ -1,34 +1,26 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
# A draft for an object
|
3
|
+
class GOM::Object::Draft
|
3
4
|
|
4
|
-
|
5
|
+
attr_accessor :id
|
6
|
+
attr_accessor :class_name
|
7
|
+
attr_writer :properties
|
8
|
+
attr_writer :relations
|
5
9
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
attr_accessor :id
|
10
|
-
attr_accessor :class_name
|
11
|
-
attr_writer :properties
|
12
|
-
attr_writer :relations
|
13
|
-
|
14
|
-
def initialize(id = nil, class_name = nil, properties = { }, relations = { })
|
15
|
-
@id, @class_name, @properties, @relations = id, class_name, properties, relations
|
16
|
-
end
|
17
|
-
|
18
|
-
def properties
|
19
|
-
@properties || { }
|
20
|
-
end
|
21
|
-
|
22
|
-
def relations
|
23
|
-
@relations || { }
|
24
|
-
end
|
10
|
+
def initialize(id = nil, class_name = nil, properties = { }, relations = { })
|
11
|
+
@id, @class_name, @properties, @relations = id, class_name, properties, relations
|
12
|
+
end
|
25
13
|
|
26
|
-
|
27
|
-
|
28
|
-
|
14
|
+
def properties
|
15
|
+
@properties || { }
|
16
|
+
end
|
29
17
|
|
30
|
-
|
18
|
+
def relations
|
19
|
+
@relations || { }
|
20
|
+
end
|
31
21
|
|
22
|
+
def ==(other)
|
23
|
+
id == other.id && class_name == other.class_name && properties == other.properties && relations == other.relations
|
32
24
|
end
|
33
25
|
|
34
26
|
end
|
data/lib/gom/object/id.rb
CHANGED
@@ -1,30 +1,22 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
# Value class for object ids.
|
3
|
+
class GOM::Object::Id
|
3
4
|
|
4
|
-
|
5
|
+
attr_accessor :storage_name
|
6
|
+
attr_accessor :object_id
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def initialize(id_or_storage_name = nil, object_id = nil)
|
13
|
-
@storage_name, @object_id = id_or_storage_name.is_a?(String) ?
|
14
|
-
(object_id.is_a?(String) ? [ id_or_storage_name, object_id ] : id_or_storage_name.split(":")) :
|
15
|
-
[ nil, nil ]
|
16
|
-
end
|
17
|
-
|
18
|
-
def ==(other)
|
19
|
-
other.is_a?(self.class) && @storage_name == other.storage_name && @object_id == other.object_id
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_s
|
23
|
-
"#{@storage_name}:#{@object_id}"
|
24
|
-
end
|
8
|
+
def initialize(id_or_storage_name = nil, object_id = nil)
|
9
|
+
@storage_name, @object_id = id_or_storage_name.is_a?(String) ?
|
10
|
+
(object_id.is_a?(String) ? [ id_or_storage_name, object_id ] : id_or_storage_name.split(":")) :
|
11
|
+
[ nil, nil ]
|
12
|
+
end
|
25
13
|
|
26
|
-
|
14
|
+
def ==(other)
|
15
|
+
other.is_a?(self.class) && @storage_name == other.storage_name && @object_id == other.object_id
|
16
|
+
end
|
27
17
|
|
18
|
+
def to_s
|
19
|
+
"#{@storage_name}:#{@object_id}"
|
28
20
|
end
|
29
21
|
|
30
22
|
end
|