secretary 0.0.1 → 0.1.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.
@@ -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