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.
Files changed (37) hide show
  1. data/README.rdoc +15 -0
  2. data/Rakefile +1 -1
  3. data/lib/gom.rb +1 -0
  4. data/lib/gom/object.rb +15 -19
  5. data/lib/gom/object/builder.rb +35 -33
  6. data/lib/gom/object/cached_builder.rb +23 -31
  7. data/lib/gom/object/collection.rb +49 -57
  8. data/lib/gom/object/draft.rb +17 -25
  9. data/lib/gom/object/id.rb +14 -22
  10. data/lib/gom/object/inspector.rb +46 -54
  11. data/lib/gom/object/mapping.rb +31 -47
  12. data/lib/gom/object/proxy.rb +25 -33
  13. data/lib/gom/spec.rb +11 -0
  14. data/lib/gom/spec/acceptance/adapter_that_needs_setup.rb +58 -0
  15. data/lib/gom/spec/acceptance/adapter_with_stateful_storage.rb +19 -21
  16. data/lib/gom/spec/acceptance/read_only_adapter_with_stateless_storage.rb +9 -8
  17. data/lib/gom/spec/object.rb +8 -0
  18. data/lib/gom/storage.rb +30 -26
  19. data/lib/gom/storage/adapter.rb +26 -43
  20. data/lib/gom/storage/configuration.rb +75 -68
  21. data/lib/gom/storage/configuration/view.rb +3 -16
  22. data/lib/gom/storage/configuration/view/class.rb +5 -22
  23. data/lib/gom/storage/configuration/view/map_reduce.rb +7 -24
  24. data/lib/gom/storage/fetcher.rb +24 -32
  25. data/lib/gom/storage/remover.rb +27 -35
  26. data/lib/gom/storage/saver.rb +35 -43
  27. data/spec/acceptance/adapter_spec.rb +16 -4
  28. data/spec/acceptance/fake_adapter_spec.rb +11 -0
  29. data/spec/acceptance/object_spec.rb +4 -1
  30. data/spec/fake_adapter.rb +12 -3
  31. data/spec/lib/gom/object/builder_spec.rb +5 -5
  32. data/spec/lib/gom/object/inspector_spec.rb +5 -9
  33. data/spec/lib/gom/object/mapping_spec.rb +27 -57
  34. data/spec/lib/gom/storage/adapter_spec.rb +1 -1
  35. data/spec/lib/gom/storage/configuration_spec.rb +33 -3
  36. data/spec/lib/gom/storage_spec.rb +19 -0
  37. 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
@@ -35,7 +35,7 @@ end
35
35
 
36
36
  desc "Run all specs in spec directory"
37
37
  RSpec::Core::RakeTask.new do |task|
38
- task.pattern = "spec/gom/**/*_spec.rb"
38
+ task.pattern = "spec/lib/**/*_spec.rb"
39
39
  end
40
40
 
41
41
  namespace :spec do
data/lib/gom.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  module GOM
3
3
 
4
4
  autoload :Object, File.join(File.dirname(__FILE__), "gom", "object")
5
+ autoload :Spec, File.join(File.dirname(__FILE__), "gom", "spec")
5
6
  autoload :Storage, File.join(File.dirname(__FILE__), "gom", "storage")
6
7
 
7
8
  end
data/lib/gom/object.rb CHANGED
@@ -1,26 +1,22 @@
1
1
 
2
- module GOM
2
+ module GOM::Object
3
3
 
4
- module Object
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
- autoload :Builder, File.join(File.dirname(__FILE__), "object", "builder")
7
- autoload :CachedBuilder, File.join(File.dirname(__FILE__), "object", "cached_builder")
8
- autoload :Collection, File.join(File.dirname(__FILE__), "object", "collection")
9
- autoload :Draft, File.join(File.dirname(__FILE__), "object", "draft")
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
@@ -1,47 +1,49 @@
1
1
 
2
- module GOM
2
+ # Build an object out of the given draft.
3
+ class GOM::Object::Builder
3
4
 
4
- module Object
5
+ attr_accessor :draft
6
+ attr_writer :object
5
7
 
6
- # Build an object out of the given draft.
7
- class Builder
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
- def object
17
- initialize_object unless @object
18
- set_properties
19
- set_relations
20
- @object
21
- end
12
+ def object
13
+ initialize_object unless @object
14
+ set_properties
15
+ set_relations
16
+ @object
17
+ end
22
18
 
23
- private
19
+ private
24
20
 
25
- def initialize_object
26
- klass = Object.const_get @draft.class_name
27
- arity = [ klass.method(:new).arity, 0 ].max
28
- @object = klass.new *([ nil ] * arity)
29
- end
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
- def set_properties
32
- @draft.properties.each do |name, value|
33
- @object.instance_variable_set :"@#{name}", value
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
- def set_relations
38
- @draft.relations.each do |name, value|
39
- @object.instance_variable_set :"@#{name}", value
40
- end
41
- end
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
- module GOM
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
- module Object
6
+ attr_accessor :draft
7
+ attr_accessor :id
5
8
 
6
- # Build an object out of the given draft using Builder. Uses the object-id mapping
7
- # for caching the results.
8
- class CachedBuilder
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
- def check_mapping
27
- @object = GOM::Object::Mapping.object_by_id @id
28
- end
13
+ def object
14
+ check_mapping
15
+ build_object
16
+ set_mapping
17
+ @object
18
+ end
29
19
 
30
- def build_object
31
- @object = GOM::Object::Builder.new(@draft, @object).object
32
- end
20
+ private
33
21
 
34
- def set_mapping
35
- GOM::Object::Mapping.put @object, @id
36
- end
22
+ def check_mapping
23
+ @object = GOM::Object::Mapping.object_by_id @id
24
+ end
37
25
 
38
- end
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
- module GOM
2
+ # A class for a collection of objects.
3
+ class GOM::Object::Collection
3
4
 
4
- module Object
5
-
6
- # A class for a collection of objects.
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
- def load
29
- if fetcher_has_drafts?
30
- load_object_proxies_from_drafts
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
- def fetcher_has_drafts?
41
- @fetcher.respond_to?(:drafts) && @fetcher.drafts
42
- end
13
+ def respond_to?(method_name)
14
+ (@object_proxies || @rows).respond_to?(method_name)
15
+ end
43
16
 
44
- def load_object_proxies_from_drafts
45
- @object_proxies = @fetcher.drafts.map do |draft|
46
- GOM::Object::Proxy.new GOM::Object::CachedBuilder.new(draft).object
47
- end
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
- def fetcher_has_ids?
51
- @fetcher.respond_to?(:ids) && @fetcher.ids
52
- end
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
- def load_object_proxies_from_ids
55
- @object_proxies = @fetcher.ids.map do |id|
56
- GOM::Object::Proxy.new id
57
- end
58
- end
36
+ def fetcher_has_drafts?
37
+ @fetcher.respond_to?(:drafts) && @fetcher.drafts
38
+ end
59
39
 
60
- def fetcher_has_rows?
61
- @fetcher.respond_to?(:rows) && @fetcher.rows
62
- end
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
- def load_rows
65
- @rows = @fetcher.rows
66
- end
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
@@ -1,34 +1,26 @@
1
1
 
2
- module GOM
2
+ # A draft for an object
3
+ class GOM::Object::Draft
3
4
 
4
- module Object
5
+ attr_accessor :id
6
+ attr_accessor :class_name
7
+ attr_writer :properties
8
+ attr_writer :relations
5
9
 
6
- # A draft for an object
7
- class Draft
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
- def ==(other)
27
- id == other.id && class_name == other.class_name && properties == other.properties && relations == other.relations
28
- end
14
+ def properties
15
+ @properties || { }
16
+ end
29
17
 
30
- end
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
- module GOM
2
+ # Value class for object ids.
3
+ class GOM::Object::Id
3
4
 
4
- module Object
5
+ attr_accessor :storage_name
6
+ attr_accessor :object_id
5
7
 
6
- # Value class for object ids.
7
- class Id
8
-
9
- attr_accessor :storage_name
10
- attr_accessor :object_id
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
- end
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