secretary 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,27 +1,21 @@
1
1
  require 'secretary/gopher'
2
2
  require 'yaml'
3
3
 
4
- class Secretary
4
+ class Secretary::Gopher::YAML < Secretary::Gopher
5
+ @file_type = 'YAML'
5
6
 
6
- class Gopher
7
-
8
- class YAML < Secretary::Gopher
9
- @valid_file_type = 'YAML'
10
-
11
- def parse_file(file)
12
- begin
13
- return ::YAML::load(file)
14
- rescue ArgumentError => parsing_error
15
- raise Secretary::Error::Parsing.new(parsing_error, valid_file_type)
16
- end
17
- end
18
-
19
- def emit(data)
20
- data.to_yaml
21
- end
22
-
7
+ protected
8
+
9
+ def parse_file file
10
+ begin
11
+ return ::YAML::load(file)
12
+ rescue ArgumentError => parsing_error
13
+ raise Secretary::Error::Parsing.new(parsing_error, file_type)
23
14
  end
24
-
15
+ end
16
+
17
+ def emit data
18
+ data.to_yaml
25
19
  end
26
20
 
27
21
  end
@@ -23,8 +23,9 @@ end
23
23
  describe Secretary::Error::InvalidData do
24
24
 
25
25
  it 'should have a message with the missing file\'s path' do
26
- Secretary::Error::InvalidData.new([3, 2], Hash).to_s \
27
- .should == 'preference file of invalid data type (should be Hash instead of Array)'
26
+ data = [3, 2]
27
+ Secretary::Error::InvalidData.new(data).to_s \
28
+ .should == "preference file contains invalid data (#{data.inspect})"
28
29
  end
29
30
 
30
31
  end
@@ -0,0 +1,124 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'lib/secretary/gopher/yaml'
3
+
4
+ describe Secretary::Gopher::YAML do
5
+
6
+ it 'should be equal with another if they have equal classes' do
7
+ gopher0 = Secretary::Gopher::YAML.new
8
+ gopher1 = Secretary::Gopher::YAML.new
9
+ gopher0.should == gopher1
10
+ gopher1.should == gopher0
11
+ end
12
+
13
+ it 'should be unequal with another if they are of unequal class, even if ' +
14
+ 'the other is a kind of its class' do
15
+ gopher0 = Secretary::Gopher::YAML.new
16
+ gopher1 = stub :kind_of? => true
17
+ gopher0.should_not == gopher1
18
+ end
19
+
20
+ it 'should know its file-type and it should be YAML' do
21
+ Secretary::Gopher::YAML.new.file_type.should == 'YAML'
22
+ end
23
+
24
+ it 'should always make-raw any data into itself' do
25
+ gopher = Secretary::Gopher::YAML.new
26
+ data = stub 'Data'
27
+ gopher.raw(data).should == data
28
+ end
29
+
30
+ it 'should always cook any data into itself' do
31
+ gopher = Secretary::Gopher::YAML.new
32
+ data = stub 'Data'
33
+ gopher.cook(data).should == data
34
+ end
35
+
36
+ it 'should optionally take special custom options when initialized' do
37
+ options = stub 'Options'
38
+ gopher = Secretary::Gopher::YAML.new options
39
+ gopher.options.should == options
40
+ end
41
+
42
+ describe 'when trying to save an object into a YAML file using a file path' do
43
+
44
+ it 'should save a given Hash' do
45
+ gopher = Secretary::Gopher::YAML.new
46
+ data = {:name => 'Tracy', :url => 'http://tracy.name'}
47
+ file_path = relative_path '/temporary.yaml'
48
+ gopher.save data, file_path
49
+ open file_path do |file|
50
+ YAML::load(file).should == data
51
+ end
52
+ File.delete file_path
53
+ end
54
+
55
+ it 'should save a given Array' do
56
+ gopher = Secretary::Gopher::YAML.new
57
+ data = ['Tracy', 'http://tracy.name']
58
+ file_path = relative_path '/temporary.yaml'
59
+ gopher.save data, file_path
60
+ open file_path do |file|
61
+ YAML::load(file).should == data
62
+ end
63
+ File.delete file_path
64
+ end
65
+
66
+ it 'should save a custom object' do
67
+ class Person
68
+ def initialize
69
+ @name = 'Sal'
70
+ @age = 76
71
+ end
72
+ def ==(other)
73
+ self.class == other.class
74
+ end
75
+ end
76
+ data = Person.new
77
+ gopher = Secretary::Gopher::YAML.new
78
+ file_path = relative_path '/temporary.yaml'
79
+ gopher.save data, file_path
80
+ open file_path do |file|
81
+ YAML::load(file).should == data
82
+ end
83
+ delete_if_exists file_path
84
+ end
85
+
86
+ end
87
+
88
+ describe 'when reading from a path to a file' do
89
+
90
+ it 'should raise a MissingFileError when the path leads to nowhere' do
91
+ gopher = Secretary::Gopher::YAML.new
92
+ lambda { gopher.load 'missing-file.yaml' } \
93
+ .should raise_error(Secretary::Error::MissingFile)
94
+ end
95
+
96
+ it 'should get the path\'s file\'s data when the file is YAML and that ' +
97
+ 'data is a Hash' do
98
+ preferences0 = {'name' => 'Billy Bob', 'email' => 'xxx@yyy.zzz'}
99
+ gopher = Secretary::Gopher::YAML.new
100
+ file_path = relative_path 'hash.yaml'
101
+ preferences1 = gopher.load(file_path)
102
+ preferences1.should == preferences0
103
+ end
104
+
105
+ it 'should get the path\'s file\'s data when the file is YAML and that ' +
106
+ 'data is an Array' do
107
+ data0 = ['Foo', 'Bar', 'Bam']
108
+ gopher = Secretary::Gopher::YAML.new
109
+ file_path = relative_path 'array.yaml'
110
+ data1 = gopher.load file_path
111
+ data1.should == data0
112
+ end
113
+
114
+ it 'should raise an InvalidDataError when the path\'s file\'s is broken ' +
115
+ 'YAML' do
116
+ gopher = Secretary::Gopher::YAML.new
117
+ file_path = relative_path 'broken-yaml.yaml'
118
+ lambda { gopher.load file_path } \
119
+ .should raise_error(Secretary::Error::Parsing)
120
+ end
121
+
122
+ end
123
+
124
+ end
@@ -0,0 +1 @@
1
+ red,blue,yellow
@@ -0,0 +1,321 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'lib/secretary'
3
+
4
+ describe Secretary do
5
+
6
+ describe 'when storing a mapping' do
7
+
8
+ it 'should be enumerable' do
9
+ gopher = stub 'Gopher', :load => {}, :save => nil
10
+ gopher_class = stub 'Gopher Class', :new => gopher
11
+ file_path = stub 'File Path'
12
+ secretary = Secretary.new file_path, :gopher => gopher_class
13
+ secretary.should be_a_kind_of(Enumerable)
14
+ end
15
+
16
+ it 'should know the file path it saves to' do
17
+ gopher = stub 'Gopher', :load => {}, :save => nil
18
+ gopher_class = stub 'Gopher Class', :new => gopher
19
+ file_path = stub 'File Path'
20
+ secretary = Secretary.new file_path, :gopher => gopher_class
21
+ secretary.file_path.should == file_path
22
+ end
23
+
24
+ it 'should know its defaults' do
25
+ gopher = stub 'Gopher', :load => {}, :save => nil
26
+ gopher_class = stub 'Gopher Class', :new => gopher
27
+ secretary = Secretary.new stub_everything, :defaults => {'name' => ''},
28
+ :gopher => gopher_class
29
+ secretary.defaults.should == {'name' => ''}
30
+ end
31
+
32
+ it 'should have an empty hash for its defaults by default' do
33
+ gopher = stub 'Gopher', :load => {}, :save => nil
34
+ gopher_class = stub 'Gopher Class', :new => gopher
35
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
36
+ secretary.defaults.should == {}
37
+ end
38
+
39
+ it 'should create a new gopher from the given gopher class' do
40
+ gopher = stub 'Gopher', :load => {}, :save => nil
41
+ gopher_class = mock 'Gopher Class'
42
+ gopher_class.should_receive(:new).and_return(gopher)
43
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
44
+ end
45
+
46
+ it 'should create a new YAML gopher by default' do
47
+ secretary = Secretary.new 'hash.yaml'
48
+ secretary.gopher.should be_a_kind_of(Secretary::Gopher::YAML)
49
+ end
50
+
51
+ it 'should know its gopher' do
52
+ defaults = stub_everything
53
+ gopher = stub 'Gopher', :load => {}, :save => nil
54
+ gopher_class = stub 'Gopher Class', :new => gopher
55
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
56
+ end
57
+
58
+ it 'should be able to set its values' do
59
+ data = {'name' => 'Billy Bob'}
60
+ gopher = stub 'Gopher', :load => data, :save => nil
61
+ gopher_class = stub 'Gopher Class', :new => gopher
62
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
63
+ secretary['name'] = 'Joe'
64
+ secretary['name'].should == 'Joe'
65
+ end
66
+
67
+ it 'should be able to delete its values' do
68
+ data = {'name' => 'Billy Bob'}
69
+ gopher = stub 'Gopher', :load => data, :save => nil
70
+ gopher_class = stub 'Gopher Class', :new => gopher
71
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
72
+ secretary.delete 'name'
73
+ secretary.should_not include('name')
74
+ end
75
+
76
+ it 'should be able to update its values' do
77
+ data0 = {'name' => ''}
78
+ data1 = {'name' => 'Billy Bob'}
79
+ gopher = stub 'Gopher', :load => data0, :save => nil
80
+ gopher_class = stub 'Gopher Class', :new => gopher
81
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
82
+ secretary.update data1
83
+ secretary.contents.should == data0.merge(data1)
84
+ end
85
+
86
+ describe 'when accessing a key' do
87
+
88
+ it 'should know the key\'s value' do
89
+ data = {'name' => 'Billy Bob'}
90
+ gopher = stub 'Gopher', :load => data, :save => nil
91
+ gopher_class = stub 'Gopher Class', :new => gopher
92
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
93
+ secretary['name'].should == 'Billy Bob'
94
+ end
95
+
96
+ it 'should give the key\'s corresponding default value if the key\'s ' +
97
+ 'does not otherwise exist in its contents' do
98
+ defaults = {'name' => 'Billy Bob'}
99
+ data = {}
100
+ gopher = stub 'Gopher', :load => data, :save => nil
101
+ gopher_class = stub 'Gopher Class', :new => gopher
102
+ secretary = Secretary.new stub_everything, :defaults => defaults,
103
+ :gopher => gopher_class
104
+ secretary['name'].should == 'Billy Bob'
105
+ end
106
+
107
+ it 'should give the key\'s corresponding default value after the key ' +
108
+ 'is deleted' do
109
+ defaults = {'name' => 'Joe'}
110
+ data = {'name' => 'Billy Bob'}
111
+ gopher = stub 'Gopher', :load => data, :save => nil
112
+ gopher_class = stub 'Gopher Class', :new => gopher
113
+ secretary = Secretary.new stub_everything, :defaults => defaults,
114
+ :gopher => gopher_class
115
+ secretary.delete 'name'
116
+ secretary['name'].should == 'Joe'
117
+ end
118
+
119
+ end
120
+
121
+ describe 'using a custom gopher' do
122
+
123
+ it 'should raise an error when its given gopher class cannot make new ' +
124
+ 'gophers' do
125
+ gopher_class = stub 'Gopher Class'
126
+ lambda { Secretary.new stub_everything, :gopher => gopher_class } \
127
+ .should raise_error(ArgumentError)
128
+ end
129
+
130
+ it 'should raise an error when its given gopher class\'s objects ' +
131
+ 'cannot act like Gophers' do
132
+ gopher = stub 'Gopher'
133
+ gopher_class = stub 'Gopher Class', :new => gopher, :save => nil
134
+ lambda { Secretary.new stub_everything, :gopher => gopher_class } \
135
+ .should raise_error(ArgumentError)
136
+ end
137
+
138
+ it 'should give its options given to its gopher, sans :gopher and ' +
139
+ ':defaults values' do
140
+ gopher = stub 'Gopher', :load => {}, :save => nil
141
+ options = stub 'Options'
142
+ gopher_class = mock 'Gopher Class'
143
+ gopher_class.should_receive(:new).with(options).and_return(gopher)
144
+ options.stub!(:delete).with(:gopher).and_return(gopher_class)
145
+ options.stub!(:delete).with(:defaults).and_return(nil)
146
+ secretary = Secretary.new stub_everything, options
147
+ end
148
+
149
+ describe 'updating itself based on what the gopher brings from its ' +
150
+ 'file path' do
151
+
152
+ it 'have contents of its defaults merged with the file\'s data, when ' +
153
+ 'initialized' do
154
+ defaults = {:bash => 'bang', :bar => 'bing'}
155
+ data = {:bar => 'foo', :bam => 'fiz'}
156
+ gopher = stub 'Gopher', :load => data, :save => nil
157
+ gopher_class = stub 'Gopher Class', :new => gopher
158
+ secretary = Secretary.new stub_everything, :defaults => defaults,
159
+ :gopher => gopher_class
160
+ secretary.contents.should == defaults.merge(data)
161
+ end
162
+
163
+ it 'have contents of its defaults only if its file does not yet ' +
164
+ 'exist, when initialized' do
165
+ defaults = {:bash => 'bang', :bar => 'bing'}
166
+ gopher = stub 'Gopher', :save => nil
167
+ gopher.stub!(:load).and_raise(
168
+ Secretary::Error::MissingFile.new(stub_everything)
169
+ )
170
+ gopher_class = stub 'Gopher Class', :new => gopher
171
+ secretary = Secretary.new stub_everything, :defaults => defaults,
172
+ :gopher => gopher_class
173
+ secretary.contents.should == defaults
174
+ end
175
+
176
+ it 'should update its contents with its defaults, based on what the ' +
177
+ 'gopher brings from its file path, when reloaded' do
178
+ defaults = {:bash => 'bang', :bar => 'bing'}
179
+ data = {:bar => 'foo', :bam => 'fiz'}
180
+ gopher = stub 'Gopher', :save => nil
181
+ gopher.stub!(:load).and_return({}, data)
182
+ gopher_class = stub 'Gopher Class', :new => gopher
183
+ secretary = Secretary.new stub_everything, :defaults => defaults,
184
+ :gopher => gopher_class
185
+ secretary.reload!
186
+ secretary.contents.should == defaults.merge(data)
187
+ end
188
+
189
+ end
190
+
191
+ it 'should send its contents to the gopher when saving' do
192
+ contents = {:bar => 'foo', :bam => 'fiz'}
193
+ file_path = stub_everything
194
+ gopher = stub 'Gopher', :load => contents
195
+ gopher.should_receive(:save).with(contents, file_path).once
196
+ gopher_class = stub 'Gopher Class', :new => gopher
197
+ secretary = Secretary.new file_path, :gopher => gopher_class
198
+ secretary.save
199
+ end
200
+
201
+ end
202
+
203
+ describe 'using a default YAML gopher' do
204
+
205
+ describe 'updating itself based on what the gopher brings from its ' +
206
+ 'file path' do
207
+
208
+ it 'have contents of its defaults merged with the file\'s data, when ' +
209
+ 'initialized' do
210
+ defaults = {'name' => '', 'port' => 80}
211
+ data = {'name' => 'Billy Bob', 'email' => 'xxx@yyy.zzz'}
212
+ file_path = relative_path 'hash.yaml'
213
+ secretary = Secretary.new file_path, :defaults => defaults
214
+ secretary.contents.should == defaults.merge(data)
215
+ end
216
+
217
+ it 'have contents of its defaults only if its file does not yet ' +
218
+ 'exist, when initialized' do
219
+ defaults = {'name' => '', 'port' => 80}
220
+ file_path = relative_path 'missing_file.yaml'
221
+ secretary = Secretary.new file_path, :defaults => defaults
222
+ secretary.contents.should == defaults
223
+ end
224
+
225
+ end
226
+
227
+ describe 'when saving data' do
228
+
229
+ it 'should create a new data file if it does not exist' do
230
+ defaults = {'name' => '', 'port' => 80}
231
+ data = {'name' => 'Billy Bob', 'email' => 'xxx@yyy.zzz'}
232
+ file_path = relative_path 'temporary.yaml'
233
+ secretary = Secretary.new file_path, :defaults => defaults
234
+ secretary.save
235
+ File.exists?(file_path).should be_true
236
+ File.delete file_path
237
+ end
238
+
239
+ it 'should save data in the file that can be retrieved' do
240
+ defaults = {'name' => '', 'port' => 80}
241
+ data0 = {'name' => 'Billy Bob', 'email' => 'xxx@yyy.zzz'}
242
+ file_path = relative_path 'temporary.yaml'
243
+ secretary0 = Secretary.new file_path, :defaults => defaults
244
+ secretary1 = Secretary.new file_path, :defaults => defaults
245
+ secretary0.update data0
246
+ data1 = secretary0.contents
247
+ secretary0.save
248
+ secretary1.reload!
249
+ secretary1.contents.should == data1
250
+ end
251
+
252
+ end
253
+
254
+ end
255
+
256
+ describe 'when comparing with another object' do
257
+
258
+ it 'should be equal if their file paths, defaults, and contents are ' +
259
+ 'equal' do
260
+ file_path = stub_everything
261
+ defaults = {:boo => 'bash'}
262
+ contents = {:boo => 'bam', :foo => 'bar'}
263
+ gopher = stub 'Gopher', :load => contents, :save => nil
264
+ gopher_class = stub 'Gopher Class', :new => gopher
265
+ secretary = Secretary.new file_path, :defaults => defaults,
266
+ :gopher => gopher_class
267
+ other = stub 'Other', :file_path => file_path, :defaults => defaults,
268
+ :gopher => gopher, :contents => contents
269
+ secretary.should == other
270
+ end
271
+
272
+ it 'should be unequal if their file paths are unequal' do
273
+ defaults = {:bash => 'bang', :bar => 'bing'}
274
+ gopher = stub 'Gopher', :load => {}, :save => nil
275
+ gopher_class = stub 'Gopher Class', :new => gopher
276
+ secretary0 = Secretary.new stub_everything, :gopher => gopher_class
277
+ secretary1 = Secretary.new stub_everything, :gopher => gopher_class
278
+ secretary0.should_not == secretary1
279
+ end
280
+
281
+ it 'should be unequal if their defaults are unequal' do
282
+ gopher = stub 'Gopher', :load => {}, :save => nil
283
+ gopher_class = stub 'Gopher Class', :new => gopher
284
+ defaults0 = {:bash => 'bang', :bar => 'bing'}
285
+ defaults1 = {:bash => 'foo', :bar => 'bing'}
286
+ secretary0 = Secretary.new stub_everything, :defaults => defaults0,
287
+ :gopher => gopher_class
288
+ secretary1 = Secretary.new stub_everything, :defaults => defaults1,
289
+ :gopher => gopher_class
290
+ secretary0.should_not == secretary1
291
+ end
292
+
293
+ it 'should be unequal if the other does not respond to :file_path' do
294
+ gopher = stub 'Gopher', :load => {}, :save => nil
295
+ gopher_class = stub 'Gopher Class', :new => gopher
296
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
297
+ other = stub 'Other'
298
+ secretary.should_not == other
299
+ end
300
+
301
+ it 'should be unequal if the other does not respond to :gopher' do
302
+ gopher = stub 'Gopher', :load => {}, :save => nil
303
+ gopher_class = stub 'Gopher Class', :new => gopher
304
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
305
+ other = stub 'Other'
306
+ secretary.should_not == other
307
+ end
308
+
309
+ it 'should be unequal if the other does not respond to :file_path' do
310
+ gopher = stub 'Gopher', :load => {}, :save => nil
311
+ gopher_class = stub 'Gopher Class', :new => gopher
312
+ secretary = Secretary.new stub_everything, :gopher => gopher_class
313
+ other = stub 'Other'
314
+ secretary.should_not == other
315
+ end
316
+
317
+ end
318
+
319
+ end
320
+
321
+ end