gom 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -5,20 +5,24 @@ shared_examples_for "a read-only adapter connected to a stateless storage" do
5
5
  GOM::Storage.setup
6
6
  end
7
7
 
8
+ after :all do
9
+ GOM::Storage.teardown
10
+ end
11
+
8
12
  describe "fetching an object" do
9
13
 
10
14
  it "should return the correct object" do
11
15
  object = GOM::Storage.fetch "test_storage:object_1"
12
- object.should be_instance_of(Object)
13
- object.instance_variable_get(:@number).should == 5
16
+ object.should be_instance_of(GOM::Spec::Object)
17
+ object.number.should == 5
14
18
  GOM::Object.id(object).should == "test_storage:object_1"
15
19
  end
16
20
 
17
21
  it "should return proxy objects that fetches the related objects" do
18
22
  object = GOM::Storage.fetch "test_storage:object_1"
19
- related_object = object.instance_variable_get :@related_object
23
+ related_object = object.related_object
20
24
  related_object.should be_instance_of(GOM::Object::Proxy)
21
- related_object.object.instance_variable_get(:@test).should == "test value"
25
+ related_object.object.number.should == 7
22
26
  end
23
27
 
24
28
  end
@@ -58,10 +62,7 @@ shared_examples_for "a read-only adapter connected to a stateless storage" do
58
62
  collection = GOM::Storage.collection :test_storage, :test_object_class_view
59
63
  collection.size > 0
60
64
  collection.each do |object_proxy|
61
- (
62
- object_proxy.object.instance_variable_get(:@number) == 5 ||
63
- object_proxy.object.instance_variable_get(:@test) == "test value"
64
- ).should be_true
65
+ [ 5, 7 ].should include(object_proxy.object.number)
65
66
  end
66
67
  end
67
68
 
@@ -0,0 +1,8 @@
1
+
2
+ # A dummy test class
3
+ class GOM::Spec::Object
4
+
5
+ attr_accessor :number
6
+ attr_accessor :related_object
7
+
8
+ end
data/lib/gom/storage.rb CHANGED
@@ -1,39 +1,43 @@
1
1
 
2
- module GOM
2
+ module GOM::Storage
3
3
 
4
- module Storage
4
+ autoload :Adapter, File.join(File.dirname(__FILE__), "storage", "adapter")
5
+ autoload :Configuration, File.join(File.dirname(__FILE__), "storage", "configuration")
6
+ autoload :Fetcher, File.join(File.dirname(__FILE__), "storage", "fetcher")
7
+ autoload :Remover, File.join(File.dirname(__FILE__), "storage", "remover")
8
+ autoload :Saver, File.join(File.dirname(__FILE__), "storage", "saver")
5
9
 
6
- autoload :Adapter, File.join(File.dirname(__FILE__), "storage", "adapter")
7
- autoload :Configuration, File.join(File.dirname(__FILE__), "storage", "configuration")
8
- autoload :Fetcher, File.join(File.dirname(__FILE__), "storage", "fetcher")
9
- autoload :Remover, File.join(File.dirname(__FILE__), "storage", "remover")
10
- autoload :Saver, File.join(File.dirname(__FILE__), "storage", "saver")
10
+ # This error can be thrown by the setup method if the given adapter name isn't registered
11
+ class AdapterNotFoundError < StandardError; end
11
12
 
12
- # This error can be thrown by an adapter if it's doesn't support write operations
13
- class ReadOnlyError < StandardError; end
13
+ # This error can be thrown by an adapter if it's doesn't support write operations
14
+ class ReadOnlyError < StandardError; end
14
15
 
15
- def self.setup
16
- Configuration.setup_all
17
- end
16
+ def self.setup
17
+ GOM::Object::Mapping.clear!
18
+ Configuration.setup_all
19
+ end
18
20
 
19
- def self.fetch(id_string)
20
- id = id_string.is_a?(String) ? GOM::Object::Id.new(id_string) : nil
21
- Fetcher.new(id).object
22
- end
21
+ def self.teardown
22
+ Configuration.teardown_all
23
+ end
23
24
 
24
- def self.store(object, storage_name = nil)
25
- Saver.new(object, storage_name).perform
26
- end
25
+ def self.fetch(id_string)
26
+ id = id_string.is_a?(String) ? GOM::Object::Id.new(id_string) : nil
27
+ Fetcher.new(id).object
28
+ end
27
29
 
28
- def self.remove(object_or_id)
29
- object_or_id = GOM::Object::Id.new object_or_id if object_or_id.is_a?(String)
30
- Remover.new(object_or_id).perform
31
- end
30
+ def self.store(object, storage_name = nil)
31
+ Saver.new(object, storage_name).perform
32
+ end
32
33
 
33
- def self.collection(storage_name, *arguments)
34
- Configuration[storage_name].adapter.collection *arguments
35
- end
34
+ def self.remove(object_or_id)
35
+ object_or_id = GOM::Object::Id.new object_or_id if object_or_id.is_a?(String)
36
+ Remover.new(object_or_id).perform
37
+ end
36
38
 
39
+ def self.collection(storage_name, *arguments)
40
+ Configuration[storage_name].adapter.collection *arguments
37
41
  end
38
42
 
39
43
  end
@@ -1,58 +1,41 @@
1
1
 
2
- module GOM
2
+ # Base class for a storage adapter
3
+ class GOM::Storage::Adapter
3
4
 
4
- module Storage
5
+ # If the adapter is used without a setup, this error is may raised.
6
+ class NoSetupError < StandardError; end
5
7
 
6
- # Base class for a storage adapter
7
- class Adapter
8
+ # If a view could not be found, this error is raised.
9
+ class ViewNotFoundError < StandardError; end
8
10
 
9
- # If a view could not be found, this error is raised.
10
- class ViewNotFoundError < StandardError; end
11
+ attr_reader :configuration
11
12
 
12
- attr_reader :configuration
13
-
14
- def initialize(configuration)
15
- @configuration = configuration
16
- end
17
-
18
- def setup(*arguments)
19
- not_implemented "setup"
20
- end
21
-
22
- def fetch(*arguments)
23
- not_implemented "fetch"
24
- end
25
-
26
- def store(*arguments)
27
- not_implemented "store"
28
- end
29
-
30
- def remove(*arguments)
31
- not_implemented "remove"
32
- end
13
+ def initialize(configuration)
14
+ @configuration = configuration
15
+ end
33
16
 
34
- def collection(*arguments)
35
- not_implemented "collection"
36
- end
17
+ [ :setup, :teardown, :fetch, :store, :remove, :collection ].each do |key|
37
18
 
38
- private
19
+ define_method key do |*arguments|
20
+ not_implemented key
21
+ end
39
22
 
40
- def not_implemented(method_name)
41
- raise NotImplementedError, "The adapter has no #{method_name} method implemented"
42
- end
23
+ end
43
24
 
44
- def self.register(id, adapter_class)
45
- @adapter_classes ||= { }
46
- @adapter_classes[id.to_sym] = adapter_class
47
- end
25
+ private
48
26
 
49
- def self.[](id)
50
- @adapter_classes ||= { }
51
- @adapter_classes[id.to_sym]
52
- end
27
+ def not_implemented(method_name)
28
+ raise NotImplementedError, "The adapter has no #{method_name} method implemented"
29
+ end
53
30
 
54
- end
31
+ def self.register(id, adapter_class)
32
+ @adapter_classes ||= { }
33
+ @adapter_classes[id.to_sym] = adapter_class
34
+ end
55
35
 
36
+ def self.[](id)
37
+ @adapter_classes ||= { }
38
+ @adapter_classes[id.to_sym]
56
39
  end
57
40
 
58
41
  end
@@ -1,94 +1,101 @@
1
- require File.join(File.dirname(__FILE__), "adapter")
2
1
  require 'yaml'
3
2
 
4
- module GOM
3
+ # Stores all information to configure a storage.
4
+ class GOM::Storage::Configuration
5
5
 
6
- module Storage
6
+ autoload :View, File.join(File.dirname(__FILE__), "configuration", "view")
7
7
 
8
- # Stores all information to configure a storage.
9
- class Configuration
8
+ attr_reader :name
9
+ attr_reader :hash
10
10
 
11
- autoload :View, File.join(File.dirname(__FILE__), "configuration", "view")
12
-
13
- attr_reader :name
11
+ def initialize(name, hash)
12
+ @name, @hash = name, { }
13
+ hash.each{ |key, value| @hash[key.to_sym] = value }
14
+ end
14
15
 
15
- def initialize(name, hash)
16
- @name, @hash = name, { }
17
- hash.each{ |key, value| @hash[key.to_sym] = value }
18
- end
16
+ def setup
17
+ adapter.setup
18
+ end
19
19
 
20
- def setup
21
- adapter.setup
22
- end
20
+ def teardown
21
+ adapter.teardown
22
+ clear_adapter
23
+ end
23
24
 
24
- def adapter
25
- @adapter ||= adapter_class.new self
26
- end
25
+ def adapter
26
+ @adapter ||= adapter_class.new self
27
+ end
27
28
 
28
- def adapter_class
29
- @adapter_class ||= Adapter[@hash[:adapter]]
30
- end
29
+ def adapter_class
30
+ @adapter_class ||= GOM::Storage::Adapter[@hash[:adapter]] || raise(GOM::Storage::AdapterNotFoundError)
31
+ end
31
32
 
32
- def [](key)
33
- @hash[key.to_sym]
34
- end
33
+ def [](key)
34
+ @hash[key.to_sym]
35
+ end
35
36
 
36
- def values_at(*arguments)
37
- arguments.map{ |argument| self[argument] }
38
- end
37
+ def values_at(*arguments)
38
+ arguments.map{ |argument| self[argument] }
39
+ end
39
40
 
40
- def views
41
- @views ||= begin
42
- result = { }
43
- (self["views"] || { }).each do |name, hash|
44
- result[name.to_sym] = self.class.view hash
45
- end
46
- result
47
- end
41
+ def views
42
+ @views ||= begin
43
+ result = { }
44
+ (self["views"] || { }).each do |name, hash|
45
+ result[name.to_sym] = self.class.view hash
48
46
  end
47
+ result
48
+ end
49
+ end
49
50
 
50
- private
51
-
52
- def self.view(hash)
53
- type = hash["type"]
54
- method_name = :"#{type}_view"
55
- raise NotImplementedError, "the view type '#{type}' doesn't exists" unless self.respond_to?(method_name)
56
- self.send method_name, hash
57
- end
51
+ private
58
52
 
59
- def self.class_view(hash)
60
- View::Class.new hash["class"]
61
- end
53
+ def clear_adapter
54
+ @adapter, @adapter_class = nil, nil
55
+ end
62
56
 
63
- def self.map_reduce_view(hash)
64
- View::MapReduce.new *hash.values_at("map", "reduce")
65
- end
57
+ def self.view(hash)
58
+ type = hash["type"]
59
+ method_name = :"#{type}_view"
60
+ raise NotImplementedError, "the view type '#{type}' doesn't exists" unless self.respond_to?(method_name)
61
+ self.send method_name, hash
62
+ end
66
63
 
67
- def self.read(file_name)
68
- @configurations = { }
69
- YAML::load_file(file_name).each do |name, values|
70
- @configurations[name.to_sym] = self.new name, values
71
- end
72
- end
64
+ def self.class_view(hash)
65
+ View::Class.new hash["class"]
66
+ end
73
67
 
74
- def self.setup_all
75
- @configurations.values.each do |configuration|
76
- configuration.setup
77
- end
78
- end
68
+ def self.map_reduce_view(hash)
69
+ View::MapReduce.new *hash.values_at("map", "reduce")
70
+ end
79
71
 
80
- def self.[](name)
81
- @configurations ||= { }
82
- @configurations[name.to_sym]
83
- end
72
+ def self.read(file_name)
73
+ @configurations = { }
74
+ YAML::load_file(file_name).each do |name, values|
75
+ @configurations[name.to_sym] = self.new name, values
76
+ end
77
+ end
84
78
 
85
- def self.default
86
- @configurations ||= { }
87
- @configurations.values.first || raise(StandardError, "No storage configuration loaded!")
88
- end
79
+ def self.setup_all
80
+ @configurations.values.each do |configuration|
81
+ configuration.setup
82
+ end
83
+ end
89
84
 
85
+ def self.teardown_all
86
+ @configurations.values.each do |configuration|
87
+ configuration.teardown
90
88
  end
89
+ end
90
+
91
+ def self.[](name)
92
+ @configurations ||= { }
93
+ @configurations[name.to_sym]
94
+ end
91
95
 
96
+ def self.default
97
+ @configurations ||= { }
98
+ @configurations.values.first || raise(StandardError, "No storage configuration loaded!")
92
99
  end
93
100
 
94
101
  end
@@ -1,20 +1,7 @@
1
1
 
2
- module GOM
2
+ module GOM::Storage::Configuration::View
3
3
 
4
- module Storage
5
-
6
- # Stores all information to configure a storage.
7
- class Configuration
8
-
9
- module View
10
-
11
- autoload :Class, File.join(File.dirname(__FILE__), "view", "class")
12
- autoload :MapReduce, File.join(File.dirname(__FILE__), "view", "map_reduce")
13
-
14
- end
15
-
16
- end
17
-
18
- end
4
+ autoload :Class, File.join(File.dirname(__FILE__), "view", "class")
5
+ autoload :MapReduce, File.join(File.dirname(__FILE__), "view", "map_reduce")
19
6
 
20
7
  end
@@ -1,28 +1,11 @@
1
1
 
2
- module GOM
2
+ # Contains all the parameters for a class view.
3
+ class GOM::Storage::Configuration::View::Class
3
4
 
4
- module Storage
5
-
6
- # Stores all information to configure a storage.
7
- class Configuration
8
-
9
- module View
10
-
11
- # Contains all the parameters for a class view.
12
- class Class
13
-
14
- attr_accessor :class_name
15
-
16
- def initialize(class_name)
17
- @class_name = class_name
18
- end
19
-
20
- end
21
-
22
- end
23
-
24
- end
5
+ attr_accessor :class_name
25
6
 
7
+ def initialize(class_name)
8
+ @class_name = class_name
26
9
  end
27
10
 
28
11
  end
@@ -1,29 +1,12 @@
1
1
 
2
- module GOM
2
+ # Contains all parameters for a map reduce view.
3
+ class GOM::Storage::Configuration::View::MapReduce
3
4
 
4
- module Storage
5
-
6
- # Stores all information to configure a storage.
7
- class Configuration
8
-
9
- module View
10
-
11
- # Contains all parameters for a map reduce view.
12
- class MapReduce
13
-
14
- attr_accessor :map
15
- attr_accessor :reduce
16
-
17
- def initialize(map, reduce)
18
- @map, @reduce = map, reduce
19
- end
20
-
21
- end
22
-
23
- end
24
-
25
- end
5
+ attr_accessor :map
6
+ attr_accessor :reduce
26
7
 
8
+ def initialize(map, reduce)
9
+ @map, @reduce = map, reduce
27
10
  end
28
11
 
29
- end
12
+ end