gom 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -10,15 +10,14 @@ is plugged-in via an adapter interface. Currently, the following adapters are pr
10
10
 
11
11
  == Configuration
12
12
 
13
- At the beginning of your program the configuration should be read with the following command.
13
+ At the beginning of your program the storage configuration should be done with the <tt>GOM::Storage.configure</tt>
14
+ command.
14
15
 
15
- GOM::Storage::Configuration.read filename
16
-
17
- The configuration file should be written in the YML format and look like...
18
-
19
- storage_name:
20
- adapter: filesystem
21
- directory: /var/project-name/data
16
+ GOM::Storage.configure {
17
+ name :storage_name
18
+ adapter :filesystem
19
+ directory "/var/project-name/data"
20
+ }
22
21
 
23
22
  Look at the adapter pages to see the adapter-specific configuration values.
24
23
 
@@ -124,13 +123,16 @@ of results at runtime. There are several kinds of views.
124
123
  There views simply provides a collection of all object of a specified class. They are defined at the storage
125
124
  configuration.
126
125
 
127
- storage_name:
128
- adapter: filesystem
129
- directory: /var/project-name/data
130
- views:
131
- users:
132
- type: class
133
- class: User
126
+ GOM::Storage.configure {
127
+ name :storage_name
128
+ adapter :filesystem
129
+ directory "/var/project-name/data"
130
+ view {
131
+ name :users
132
+ type :class
133
+ model_class User
134
+ }
135
+ }
134
136
 
135
137
  The example defines a class view for all objects of the class <tt>User</tt>. The result can be fetched via...
136
138
 
@@ -143,21 +145,26 @@ array.
143
145
 
144
146
  These views are also defined in the storage configuration.
145
147
 
146
- storage_name:
147
- adapter: couchdb
148
- views:
149
- active_user_count:
150
- type: map_reduce
151
- map:
152
- function(document) {
153
- if (document['model_class'] == 'User' && document['active']) {
154
- emit(document['_id'], 1);
155
- }
156
- }
157
- reduce:
158
- function(keys, values, rereduce) {
159
- return sum(values);
148
+ GOM::Storage.configure {
149
+ name :storage_name
150
+ adapter :couchdb
151
+ view {
152
+ name :active_user_count
153
+ type :map_reduce
154
+ map_function """
155
+ function(document) {
156
+ if (document['model_class'] == 'User' && document['active']) {
157
+ emit(document['_id'], 1);
160
158
  }
159
+ }
160
+ """
161
+ reduce_function """
162
+ function(keys, values, rereduce) {
163
+ return sum(values);
164
+ }
165
+ """
166
+ }
167
+ }
161
168
 
162
169
  The example defined a map/reduce view that results in a single row with the count of all active users. This row can be
163
170
  fetched by...
@@ -168,17 +175,21 @@ fetched by...
168
175
  If no <tt>reduce</tt> method is given, <tt>GOM</tt> will try to map the fetched data back to ruby-objects. The
169
176
  definition would be...
170
177
 
171
- storage_name:
172
- adapter: couchdb
173
- views:
174
- active_users:
175
- type: map_reduce
176
- map:
177
- function(document) {
178
- if (document['model_class'] == 'User') {
179
- emit(document['_id'], null);
180
- }
178
+ GOM::Storage.configure {
179
+ name :storage_name
180
+ adapter :couchdb
181
+ view {
182
+ name :active_users
183
+ type :map_reduce
184
+ map_function """
185
+ function(document) {
186
+ if (document['model_class'] == 'User') {
187
+ emit(document['_id'], null);
181
188
  }
189
+ }
190
+ """
191
+ }
192
+ }
182
193
 
183
194
  ...and the fetch is done by...
184
195
 
data/lib/gom/storage.rb CHANGED
@@ -14,6 +14,10 @@ module GOM::Storage
14
14
  # This error can be thrown by an adapter if it's doesn't support write operations
15
15
  class ReadOnlyError < StandardError; end
16
16
 
17
+ def self.configure(&block)
18
+ Configuration.configure &block
19
+ end
20
+
17
21
  def self.setup
18
22
  GOM::Object::Mapping.clear!
19
23
  Configuration.setup_all
@@ -1,15 +1,29 @@
1
1
  require 'yaml'
2
+ require 'configure'
2
3
 
3
4
  # Stores all information to configure a storage.
4
5
  class GOM::Storage::Configuration
5
6
 
6
7
  autoload :View, File.join(File.dirname(__FILE__), "configuration", "view")
7
8
 
8
- attr_reader :name
9
+ SCHEMA = Configure::Schema.build{
10
+ only :storage
11
+ nested {
12
+ storage {
13
+ not_nil :name, :adapter
14
+ nested {
15
+ view {
16
+ not_nil :name, :type
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }.freeze
22
+
9
23
  attr_reader :hash
10
24
 
11
- def initialize(name, hash)
12
- @name, @hash = name, { }
25
+ def initialize(hash)
26
+ @hash = { }
13
27
  hash.each{ |key, value| @hash[key.to_sym] = value }
14
28
  end
15
29
 
@@ -22,6 +36,10 @@ class GOM::Storage::Configuration
22
36
  clear_adapter
23
37
  end
24
38
 
39
+ def name
40
+ @hash[:name].to_s
41
+ end
42
+
25
43
  def adapter
26
44
  @adapter ||= adapter_class.new self
27
45
  end
@@ -41,7 +59,8 @@ class GOM::Storage::Configuration
41
59
  def views
42
60
  @views ||= begin
43
61
  result = { }
44
- (self["views"] || { }).each do |name, hash|
62
+ [ @hash[:view] ].flatten.compact.each do |hash|
63
+ name = hash[:name]
45
64
  result[name.to_sym] = self.class.view hash
46
65
  end
47
66
  result
@@ -54,26 +73,28 @@ class GOM::Storage::Configuration
54
73
  @adapter, @adapter_class = nil, nil
55
74
  end
56
75
 
76
+ def self.configure(&block)
77
+ @configurations = { }
78
+ configurations = Configure.process SCHEMA, &block
79
+ [ configurations[:storage] ].flatten.compact.each do |hash|
80
+ name = hash[:name]
81
+ @configurations[name.to_sym] = self.new hash
82
+ end
83
+ end
84
+
57
85
  def self.view(hash)
58
- type = hash["type"]
86
+ type = hash[:type]
59
87
  method_name = :"#{type}_view"
60
88
  raise NotImplementedError, "the view type '#{type}' doesn't exists" unless self.respond_to?(method_name)
61
89
  self.send method_name, hash
62
90
  end
63
91
 
64
92
  def self.class_view(hash)
65
- View::Class.new hash["class"]
93
+ View::Class.new hash[:model_class]
66
94
  end
67
95
 
68
96
  def self.map_reduce_view(hash)
69
- View::MapReduce.new *hash.values_at("map", "reduce")
70
- end
71
-
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
97
+ View::MapReduce.new *hash.values_at(:map_function, :reduce_function)
77
98
  end
78
99
 
79
100
  def self.setup_all
@@ -1,7 +1,5 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
2
 
3
- GOM::Storage::Configuration.read File.join(File.dirname(__FILE__), "..", "storage.configuration")
4
-
5
3
  describe "adapter" do
6
4
 
7
5
  before :each do
@@ -19,4 +17,4 @@ describe "adapter" do
19
17
 
20
18
  end
21
19
 
22
- end
20
+ end
@@ -1,7 +1,5 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
2
 
3
- GOM::Storage::Configuration.read File.join(File.dirname(__FILE__), "..", "storage.configuration")
4
-
5
3
  describe "fake adapter" do
6
4
 
7
5
  it_should_behave_like "an adapter that needs setup"
@@ -1,7 +1,5 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
2
 
3
- GOM::Storage::Configuration.read File.join(File.dirname(__FILE__), "..", "storage.configuration")
4
-
5
3
  describe "object" do
6
4
 
7
5
  before :each do
@@ -5,13 +5,29 @@ describe GOM::Storage::Configuration do
5
5
  before :each do
6
6
  @adapter = mock GOM::Storage::Adapter, :setup => nil
7
7
  @adapter_class = mock Class, :new => @adapter
8
- GOM::Storage::Adapter.stub(:[]).and_return(@adapter_class)
9
-
10
- described_class.read File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "storage.configuration"))
8
+ GOM::Storage::Adapter.stub :[] => @adapter_class
9
+
10
+ described_class.configure {
11
+ storage {
12
+ name :test_storage
13
+ adapter :test
14
+ view {
15
+ name :test_object_class_view
16
+ type :class
17
+ model_class Object
18
+ }
19
+ view {
20
+ name :test_map_view
21
+ type :map_reduce
22
+ map_function "function(document) { }"
23
+ reduce_function "function(key, values) { }"
24
+ }
25
+ }
26
+ }
11
27
  @configuration = described_class[:test_storage]
12
28
  end
13
29
 
14
- describe "setup" do
30
+ describe "#setup" do
15
31
 
16
32
  it "should call setup on the adapter instance" do
17
33
  @adapter.should_receive(:setup)
@@ -20,7 +36,7 @@ describe GOM::Storage::Configuration do
20
36
 
21
37
  end
22
38
 
23
- describe "teardown" do
39
+ describe "#teardown" do
24
40
 
25
41
  it "should call teardown on the adapter instance" do
26
42
  @adapter.should_receive(:teardown)
@@ -29,7 +45,12 @@ describe GOM::Storage::Configuration do
29
45
 
30
46
  end
31
47
 
32
- describe "adapter_class" do
48
+ describe "#adapter_class" do
49
+
50
+ it "should fetch the right adapter class" do
51
+ GOM::Storage::Adapter.should_receive(:[]).with(:test).and_return(@adapter_class)
52
+ @configuration.adapter_class
53
+ end
33
54
 
34
55
  it "should return the adapter class" do
35
56
  adapter_class = @configuration.adapter_class
@@ -45,28 +66,43 @@ describe GOM::Storage::Configuration do
45
66
 
46
67
  end
47
68
 
48
- describe "[]" do
69
+ describe "#[]" do
49
70
 
50
71
  it "should return the configuration value" do
51
- @configuration[:test].should == "test value"
72
+ @configuration[:name].should == :test_storage
52
73
  end
53
74
 
54
75
  end
55
76
 
56
- describe "values_at" do
77
+ describe "#values_at" do
57
78
 
58
79
  it "should return multiple configuration values" do
59
- @configuration.values_at(:adapter, :test).should == [ "fake_adapter", "test value" ]
80
+ @configuration.values_at(:adapter, :name).should == [ :test, :test_storage ]
81
+ end
82
+
83
+ end
84
+
85
+ describe "#self.configure" do
86
+
87
+ before :each do
88
+ @block = Proc.new { }
89
+ @configuration = { :storage => { :name => :test } }
90
+ Configure.stub :process => @configuration
91
+ end
92
+
93
+ it "should pass the given block to Configure.process along with the configuration schema" do
94
+ Configure.should_receive(:process).with(described_class::SCHEMA, &@block).and_return(@configuration)
95
+ described_class.configure &@block
60
96
  end
61
97
 
62
98
  end
63
99
 
64
- describe "views" do
100
+ describe "#self.views" do
65
101
 
66
102
  it "should return a hash including class views" do
67
103
  view = @configuration.views[:test_object_class_view]
68
104
  view.should be_instance_of(described_class::View::Class)
69
- view.class_name.should == "Object"
105
+ view.class_name.should == Object
70
106
  end
71
107
 
72
108
  it "should return a hash including map reduce views" do
@@ -77,7 +113,7 @@ describe GOM::Storage::Configuration do
77
113
  end
78
114
 
79
115
  it "should raise a #{NotImplementedError} if the view type is invalid" do
80
- @configuration["views"]["test_invalid_view"] = { "type" => "invalid" }
116
+ @configuration["view"] << { :name => "test", :type => "invalid" }
81
117
  lambda do
82
118
  @configuration.views[:test_invalid_view]
83
119
  end.should raise_error(NotImplementedError)
@@ -90,24 +126,7 @@ describe GOM::Storage::Configuration do
90
126
 
91
127
  end
92
128
 
93
- describe "read" do
94
-
95
- it "should read the configuration file" do
96
- @configuration.should be_instance_of(described_class)
97
- end
98
-
99
- it "should initialize the right adapter class" do
100
- @configuration.adapter_class.should == @adapter_class
101
- end
102
-
103
- it "should create an adapter instance if requested" do
104
- @adapter_class.should_receive(:new).with(@configuration).and_return(@adapter)
105
- @configuration.adapter.should == @adapter
106
- end
107
-
108
- end
109
-
110
- describe "setup_all" do
129
+ describe "#self.setup_all" do
111
130
 
112
131
  before :each do
113
132
  @configuration.stub(:setup)
@@ -120,7 +139,7 @@ describe GOM::Storage::Configuration do
120
139
 
121
140
  end
122
141
 
123
- describe "teardown_all" do
142
+ describe "#self.teardown_all" do
124
143
 
125
144
  before :each do
126
145
  @configuration.stub(:teardown)
@@ -133,7 +152,7 @@ describe GOM::Storage::Configuration do
133
152
 
134
153
  end
135
154
 
136
- describe "default" do
155
+ describe "#self.default" do
137
156
 
138
157
  it "should select the first configuration" do
139
158
  described_class.default.should == GOM::Storage::Configuration[:test_storage]
@@ -7,11 +7,25 @@ describe GOM::Storage do
7
7
  @object = Object.new
8
8
  end
9
9
 
10
- describe "setup" do
10
+ describe "#self.configure" do
11
11
 
12
12
  before :each do
13
- GOM::Object::Mapping.stub(:clear!)
14
- described_class::Configuration.stub(:setup_all)
13
+ @block = Proc.new { }
14
+ described_class::Configuration.stub :configure => nil
15
+ end
16
+
17
+ it "should call :configure on the configuration class" do
18
+ described_class::Configuration.should_receive(:configure).with(&@block)
19
+ described_class.configure &@block
20
+ end
21
+
22
+ end
23
+
24
+ describe "#self.setup" do
25
+
26
+ before :each do
27
+ GOM::Object::Mapping.stub :clear! => nil
28
+ described_class::Configuration.stub :setup_all => nil
15
29
  end
16
30
 
17
31
  it "should clear the mapping" do
@@ -26,10 +40,10 @@ describe GOM::Storage do
26
40
 
27
41
  end
28
42
 
29
- describe "teardown" do
43
+ describe "#self.teardown" do
30
44
 
31
45
  before :each do
32
- described_class::Configuration.stub(:teardown_all)
46
+ described_class::Configuration.stub :teardown_all => nil
33
47
  end
34
48
 
35
49
  it "should teardown all storage configurations" do
@@ -39,11 +53,11 @@ describe GOM::Storage do
39
53
 
40
54
  end
41
55
 
42
- describe "fetch" do
56
+ describe "#self.fetch" do
43
57
 
44
58
  before :each do
45
59
  @id = mock GOM::Object::Id
46
- GOM::Object::Id.stub(:new).and_return(@id)
60
+ GOM::Object::Id.stub :new => @id
47
61
 
48
62
  @fetcher = mock GOM::Storage::Fetcher, :object => @object
49
63
  described_class::Fetcher.stub(:new).and_return(@fetcher)
@@ -65,19 +79,19 @@ describe GOM::Storage do
65
79
 
66
80
  it "should return nil if nil is given" do
67
81
  described_class::Fetcher.should_receive(:new).with(nil).and_return(@fetcher)
68
- @fetcher.stub(:object).and_return(nil)
82
+ @fetcher.stub :object => nil
69
83
 
70
84
  described_class.fetch(nil).should be_nil
71
85
  end
72
86
 
73
87
  end
74
88
 
75
- describe "store" do
89
+ describe "#self.store" do
76
90
 
77
91
  before :each do
78
92
  @storage_name = "another_test_storage"
79
93
  @saver = mock described_class::Saver, :perform => nil
80
- described_class::Saver.stub(:new).and_return(@saver)
94
+ described_class::Saver.stub :new => @saver
81
95
  end
82
96
 
83
97
  it "should initialize the saver correctly" do
@@ -92,14 +106,14 @@ describe GOM::Storage do
92
106
 
93
107
  end
94
108
 
95
- describe "remove" do
109
+ describe "#self.remove" do
96
110
 
97
111
  before :each do
98
112
  @id = mock GOM::Object::Id
99
- GOM::Object::Id.stub(:new).and_return(@id)
113
+ GOM::Object::Id.stub :new => @id
100
114
 
101
115
  @remover = mock described_class::Remover, :perform => nil
102
- described_class::Remover.stub(:new).and_return(@remover)
116
+ described_class::Remover.stub :new => @remover
103
117
  end
104
118
 
105
119
  it "should initialize the remover correctly" do
@@ -120,11 +134,11 @@ describe GOM::Storage do
120
134
 
121
135
  end
122
136
 
123
- describe "count" do
137
+ describe "#self.count" do
124
138
 
125
139
  before :each do
126
140
  @counter = mock described_class::Counter, :perform => 1
127
- described_class::Counter.stub(:new).and_return(@counter)
141
+ described_class::Counter.stub :new => @counter
128
142
  end
129
143
 
130
144
  it "should initialize the counter" do
@@ -139,7 +153,7 @@ describe GOM::Storage do
139
153
 
140
154
  end
141
155
 
142
- describe "collection" do
156
+ describe "#self.collection" do
143
157
 
144
158
  before :each do
145
159
  @collection = mock GOM::Object::Collection
data/spec/spec_helper.rb CHANGED
@@ -5,3 +5,21 @@ require 'rspec'
5
5
  require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "gom"))
6
6
  require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "gom", "spec"))
7
7
  require File.join(File.dirname(__FILE__), "fake_adapter")
8
+
9
+ GOM::Storage.configure {
10
+ storage {
11
+ name :test_storage
12
+ adapter :fake_adapter
13
+ view {
14
+ name :test_object_class_view
15
+ type :class
16
+ model_class Object
17
+ }
18
+ view {
19
+ name :test_map_view
20
+ type :map_reduce
21
+ map_function "function(document) { }"
22
+ reduce_function "function(key, values) { }"
23
+ }
24
+ }
25
+ }
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gom
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 3
8
- - 1
9
- version: 0.3.1
4
+ prerelease:
5
+ version: 0.4.0
10
6
  platform: ruby
11
7
  authors:
12
8
  - "Philipp Br\xC3\xBCll"
@@ -14,36 +10,42 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2011-03-07 00:00:00 +01:00
13
+ date: 2011-05-10 00:00:00 +02:00
18
14
  default_executable:
19
15
  dependencies:
20
16
  - !ruby/object:Gem::Dependency
21
- name: rspec
17
+ name: configure
22
18
  prerelease: false
23
19
  requirement: &id001 !ruby/object:Gem::Requirement
24
20
  none: false
25
21
  requirements:
26
22
  - - ">="
27
23
  - !ruby/object:Gem::Version
28
- segments:
29
- - 2
24
+ version: 0.3.0
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
30
35
  version: "2"
31
36
  type: :development
32
- version_requirements: *id001
37
+ version_requirements: *id002
33
38
  - !ruby/object:Gem::Dependency
34
39
  name: reek
35
40
  prerelease: false
36
- requirement: &id002 !ruby/object:Gem::Requirement
41
+ requirement: &id003 !ruby/object:Gem::Requirement
37
42
  none: false
38
43
  requirements:
39
44
  - - ">="
40
45
  - !ruby/object:Gem::Version
41
- segments:
42
- - 1
43
- - 2
44
46
  version: "1.2"
45
47
  type: :development
46
- version_requirements: *id002
48
+ version_requirements: *id003
47
49
  description: Core package of the General Object Mapper.
48
50
  email: b.phifty@gmail.com
49
51
  executables: []
@@ -119,21 +121,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
119
121
  requirements:
120
122
  - - ">="
121
123
  - !ruby/object:Gem::Version
122
- segments:
123
- - 0
124
124
  version: "0"
125
125
  required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  none: false
127
127
  requirements:
128
128
  - - ">="
129
129
  - !ruby/object:Gem::Version
130
- segments:
131
- - 0
132
130
  version: "0"
133
131
  requirements: []
134
132
 
135
133
  rubyforge_project: gom
136
- rubygems_version: 1.3.7
134
+ rubygems_version: 1.6.1
137
135
  signing_key:
138
136
  specification_version: 3
139
137
  summary: General Object Mapper - maps any ruby object to different kinds of storage engines and vice versa.