gorillib-model 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +12 -0
  3. data/README.md +21 -0
  4. data/Rakefile +15 -0
  5. data/gorillib-model.gemspec +27 -0
  6. data/lib/gorillib/builder.rb +239 -0
  7. data/lib/gorillib/core_ext/datetime.rb +23 -0
  8. data/lib/gorillib/core_ext/exception.rb +153 -0
  9. data/lib/gorillib/core_ext/module.rb +10 -0
  10. data/lib/gorillib/core_ext/object.rb +14 -0
  11. data/lib/gorillib/model/base.rb +273 -0
  12. data/lib/gorillib/model/collection/model_collection.rb +157 -0
  13. data/lib/gorillib/model/collection.rb +200 -0
  14. data/lib/gorillib/model/defaults.rb +115 -0
  15. data/lib/gorillib/model/errors.rb +24 -0
  16. data/lib/gorillib/model/factories.rb +555 -0
  17. data/lib/gorillib/model/field.rb +168 -0
  18. data/lib/gorillib/model/lint.rb +24 -0
  19. data/lib/gorillib/model/named_schema.rb +53 -0
  20. data/lib/gorillib/model/positional_fields.rb +35 -0
  21. data/lib/gorillib/model/schema_magic.rb +163 -0
  22. data/lib/gorillib/model/serialization/csv.rb +60 -0
  23. data/lib/gorillib/model/serialization/json.rb +44 -0
  24. data/lib/gorillib/model/serialization/lines.rb +30 -0
  25. data/lib/gorillib/model/serialization/to_wire.rb +54 -0
  26. data/lib/gorillib/model/serialization/tsv.rb +53 -0
  27. data/lib/gorillib/model/serialization.rb +41 -0
  28. data/lib/gorillib/model/type/extended.rb +83 -0
  29. data/lib/gorillib/model/type/ip_address.rb +153 -0
  30. data/lib/gorillib/model/type/url.rb +11 -0
  31. data/lib/gorillib/model/validate.rb +22 -0
  32. data/lib/gorillib/model/version.rb +5 -0
  33. data/lib/gorillib/model.rb +34 -0
  34. data/spec/builder_spec.rb +193 -0
  35. data/spec/core_ext/datetime_spec.rb +41 -0
  36. data/spec/core_ext/exception.rb +98 -0
  37. data/spec/core_ext/object.rb +45 -0
  38. data/spec/model/collection_spec.rb +290 -0
  39. data/spec/model/defaults_spec.rb +104 -0
  40. data/spec/model/factories_spec.rb +323 -0
  41. data/spec/model/lint_spec.rb +28 -0
  42. data/spec/model/serialization/csv_spec.rb +30 -0
  43. data/spec/model/serialization/tsv_spec.rb +28 -0
  44. data/spec/model/serialization_spec.rb +41 -0
  45. data/spec/model/type/extended_spec.rb +166 -0
  46. data/spec/model/type/ip_address_spec.rb +141 -0
  47. data/spec/model_spec.rb +261 -0
  48. data/spec/spec_helper.rb +15 -0
  49. data/spec/support/capture_output.rb +28 -0
  50. data/spec/support/nuke_constants.rb +9 -0
  51. data/spec/support/shared_context_for_builders.rb +59 -0
  52. data/spec/support/shared_context_for_models.rb +55 -0
  53. data/spec/support/shared_examples_for_factories.rb +71 -0
  54. data/spec/support/shared_examples_for_model_fields.rb +62 -0
  55. data/spec/support/shared_examples_for_models.rb +87 -0
  56. metadata +193 -0
@@ -0,0 +1,323 @@
1
+ require 'spec_helper'
2
+
3
+ describe '', :model_spec => true, :factory_spec => true do
4
+
5
+ describe Gorillib::Factory do
6
+ describe 'Factory()' do
7
+ it 'turns a proc into an ApplyProcFactory' do
8
+ ff = Gorillib::Factory( ->(obj){ "bob says #{obj}" } )
9
+ ff.receive(3).should == "bob says 3"
10
+ end
11
+ it 'returns anything that responds to #receive directly' do
12
+ ff = Object.new ; ff.define_singleton_method(:receive){}
13
+ Gorillib::Factory(ff).should equal(ff)
14
+ end
15
+ it 'returns a factory directly' do
16
+ ff = Gorillib::Factory::SymbolFactory.new
17
+ Gorillib::Factory(ff).should equal(ff)
18
+ end
19
+ it 'does not look up factory **classes**' do
20
+ ->{ Gorillib::Factory(Gorillib::Factory::SymbolFactory) }.should raise_error(ArgumentError, /Don\'t know which factory makes/)
21
+ end
22
+ it 'looks up factories by typename' do
23
+ Gorillib::Factory(:symbol ).should be_a(Gorillib::Factory::SymbolFactory)
24
+ Gorillib::Factory(:identical).should == (::Whatever)
25
+ end
26
+ it 'looks up factories by class' do
27
+ Gorillib::Factory(Symbol).should be_a(Gorillib::Factory::SymbolFactory)
28
+ Gorillib::Factory(String).should be_a(Gorillib::Factory::StringFactory)
29
+ end
30
+ it 'calls Gorillib::Factory.lookup' do
31
+ x = double
32
+ Gorillib::Factory.should_receive(:find).with(x)
33
+ Gorillib::Factory(x)
34
+ end
35
+ end
36
+ end
37
+
38
+ # __________________________________________________________________________
39
+ #
40
+ #
41
+ #
42
+ describe Gorillib::Factory::StringFactory do
43
+ it_behaves_like :it_considers_native, 'foo', ''
44
+ it_behaves_like :it_converts, :foo => 'foo', 3 => '3', false => "false", [] => "[]"
45
+ it_behaves_like :it_considers_blankish, nil
46
+ it_behaves_like :it_is_registered_as, :string, String
47
+ its(:typename){ should == :string }
48
+ end
49
+
50
+ describe Gorillib::Factory::SymbolFactory do
51
+ it_behaves_like :it_considers_native, :foo, :"symbol :with weird chars"
52
+ it_behaves_like :it_converts, 'foo' => :foo
53
+ it_behaves_like :it_considers_blankish, nil, ""
54
+ it_behaves_like :it_is_a_mismatch_for, 3, false, []
55
+ it_behaves_like :it_is_registered_as, :symbol, Symbol
56
+ its(:typename){ should == :symbol }
57
+ end
58
+
59
+ describe Gorillib::Factory::RegexpFactory do
60
+ it_behaves_like :it_considers_native, /foo/, //
61
+ it_behaves_like :it_converts, 'foo' => /foo/, ".*" => /.*/
62
+ it_behaves_like :it_considers_blankish, nil, ""
63
+ it_behaves_like :it_is_a_mismatch_for, :foo, 3, false, []
64
+ it_behaves_like :it_is_registered_as, :regexp, Regexp
65
+ its(:typename){ should == :regexp }
66
+ end
67
+
68
+ describe Gorillib::Factory::IntegerFactory do
69
+ it_behaves_like :it_considers_native, 1, -1, 123_456_789_123_456_789_123_456_789_123_456_789
70
+ #
71
+ it_behaves_like :it_converts, '1' => 1, '0' => 0, '1234567' => 1234567
72
+ it_behaves_like :it_converts, '123456789123456789123456789123456789' => 123_456_789_123_456_789_123_456_789_123_456_789
73
+ it_behaves_like :it_converts, '1_234_567' => 1234567
74
+ it_behaves_like :it_converts, 1.0 => 1, 1.99 => 1, -0.9 => 0
75
+ it_behaves_like :it_converts, Complex(1,0) => 1, Complex(1.0,0) => 1, Rational(5,2) => 2
76
+ #
77
+ it_behaves_like :it_considers_blankish, nil, ''
78
+ it_behaves_like :it_is_a_mismatch_for, Complex(1,0.0), Complex(0,3), :foo, false, []
79
+ it_behaves_like :it_is_a_mismatch_for, '8_', 'one', '3blindmice', '_8_'
80
+ it_behaves_like :it_is_a_mismatch_for, Float::INFINITY, Float::NAN
81
+ # Does not accept floating-point-ish
82
+ it_behaves_like :it_is_a_mismatch_for, '1.0', '0.0', '1234567.0'
83
+ it_behaves_like :it_is_a_mismatch_for, '1e5', '1_234_567e-3', '1_234_567.0', '+11.123E+12'
84
+ # Handles hex
85
+ it_behaves_like :it_converts, '011' => 9, '0x10' => 16
86
+ # Intolerant of cruft, unlike GraciousIntegerFactory
87
+ it_behaves_like :it_is_a_mismatch_for, '0L', '1_234_567L', '1_234_567e-3f', '1,234,567'
88
+ #
89
+ it_behaves_like :it_is_registered_as, :int, :integer, Integer
90
+ its(:typename){ should == :integer }
91
+ end
92
+
93
+ describe Gorillib::Factory::GraciousIntegerFactory do
94
+ it_behaves_like :it_considers_native, 1, -1, 123_456_789_123_456_789_123_456_789_123_456_789
95
+ #
96
+ it_behaves_like :it_converts, '1' => 1, '0' => 0, '1234567' => 1234567
97
+ it_behaves_like :it_converts, '123456789123456789123456789123456789' => 123_456_789_123_456_789_123_456_789_123_456_789
98
+ it_behaves_like :it_converts, '1_234_567' => 1234567
99
+ it_behaves_like :it_converts, 1.0 => 1, 1.99 => 1, -0.9 => 0
100
+ it_behaves_like :it_converts, Complex(1,0) => 1, Complex(1.0,0) => 1, Rational(5,2) => 2
101
+ #
102
+ it_behaves_like :it_considers_blankish, nil, ''
103
+ it_behaves_like :it_is_a_mismatch_for, Complex(1,0.0), Complex(0,3), :foo, false, []
104
+ it_behaves_like :it_is_a_mismatch_for, '8_', 'one', '3blindmice', '_8_'
105
+ it_behaves_like :it_is_a_mismatch_for, Float::INFINITY, Float::NAN
106
+ # Handles floating-point well
107
+ it_behaves_like :it_converts, '1.0' => 1, '0.0' => 0, '1234567.0' => 1234567
108
+ it_behaves_like :it_converts, '1e5' => 100000, '1_234_567e-3' => 1234, '1_234.5e3' => 1_234_500, '+11.123E+12' => 11_123_000_000_000
109
+ # Silently confuses hex and octal
110
+ it_behaves_like :it_converts, '011' => 9, '0x10' => 16, '0x1.999999999999ap4' => 25
111
+ # Tolerates some cruft, unlike IntegerFactory
112
+ it_behaves_like :it_converts, '0L' => 0, '1_234_567L' => 1234567, '1234.5e3f' => 1_234_500, '1234567e-3f' => 1_234
113
+ it_behaves_like :it_converts, '1,234,567' => 1234567, ',,,,1,23,45.67e,-1,' => 1234
114
+ #
115
+ it_behaves_like :it_is_registered_as, :gracious_int
116
+ its(:typename){ should == :integer }
117
+ end
118
+
119
+ describe Gorillib::Factory::FloatFactory do
120
+ it_behaves_like :it_considers_native, 1.0, 1.234567e6, 123_456_789_123_456_789_123_456_789_123_456_789.0
121
+ it_behaves_like :it_considers_native, Float::INFINITY, Float::NAN
122
+ it_behaves_like :it_converts, '1' => 1.0, '0' => 0.0, '1234567' => 1234567.0
123
+ it_behaves_like :it_converts, '1.0' => 1.0, '0.0' => 0.0, '1234567.0' => 1234567.0
124
+ it_behaves_like :it_converts, '123456789123456789123456789123456789' => 123_456_789_123_456_789_123_456_789_123_456_789.0
125
+ it_behaves_like :it_converts, '1_234_567' => 1234567.0
126
+ it_behaves_like :it_converts, 1 => 1.0
127
+ it_behaves_like :it_converts, Complex(1,0) => 1.0, Complex(1.0,0) => 1.0, Rational(5,2) => 2.5
128
+ it_behaves_like :it_converts, '1e5' => 1e5, '1_234_567e-3' => 1234.567, '1_234_567.0' => 1234567.0, '+11.123E+700' => 11.123e700
129
+ #
130
+ it_behaves_like :it_considers_blankish, nil, ''
131
+ it_behaves_like :it_is_a_mismatch_for, Complex(1,0.0), Complex(0,3), :foo, false, []
132
+ #
133
+ # Different from #to_f
134
+ it_behaves_like :it_converts, '011' => 11.0, '0x10' => 16.0, '0x1.999999999999ap4' => 25.6
135
+ it_behaves_like :it_is_a_mismatch_for, '0L', '1_234_567L', '1_234_567e-3f'
136
+ it_behaves_like :it_is_a_mismatch_for, '_8_', 'one', '3blindmice', '8_'
137
+ #
138
+ it_behaves_like :it_is_registered_as, :float, Float
139
+ its(:typename){ should == :float }
140
+ end
141
+
142
+ describe Gorillib::Factory::GraciousFloatFactory do
143
+ it_behaves_like :it_considers_native, 1.0, 1.234567e6, 123_456_789_123_456_789_123_456_789_123_456_789.0
144
+ it_behaves_like :it_converts, '1' => 1.0, '0' => 0.0, '1234567' => 1234567.0
145
+ it_behaves_like :it_converts, '1.0' => 1.0, '0.0' => 0.0, '1234567.0' => 1234567.0
146
+ it_behaves_like :it_converts, '123456789123456789123456789123456789' => 123_456_789_123_456_789_123_456_789_123_456_789.0
147
+ it_behaves_like :it_converts, '1_234_567' => 1234567.0
148
+ it_behaves_like :it_converts, 1 => 1.0
149
+ it_behaves_like :it_converts, Complex(1,0) => 1.0, Complex(1.0,0) => 1.0, Rational(5,2) => 2.5
150
+ it_behaves_like :it_converts, '1e5' => 1e5, '1_234_567e-3' => 1234.567, '1_234_567.0' => 1234567.0, '+11.123E+700' => 11.123e700
151
+ #
152
+ it_behaves_like :it_considers_blankish, nil, ''
153
+ it_behaves_like :it_is_a_mismatch_for, Complex(1,0.0), Complex(0,3), :foo, false, []
154
+ #
155
+ # Different from stricter FloatFactory or laxer #to_f
156
+ it_behaves_like :it_converts, '011' => 11.0, '0x10' => 16.0, '0x1.999999999999ap4' => 25.6
157
+ it_behaves_like :it_converts, '0L' => 0.0, '1_234_567L' => 1234567.0, '1_234_567e-3f' => 1234.567
158
+ it_behaves_like :it_is_a_mismatch_for, '_8_', 'one', '3blindmice', '8_'
159
+ it_behaves_like :it_converts, '1,234,567e-3' => 1234.567, ',,,,1,23,45.67e,-1,' => 1234.567, '+11.123E+700' => 11.123e700
160
+ #
161
+ it_behaves_like :it_is_registered_as, :gracious_float
162
+ its(:typename){ should == :float }
163
+ end
164
+
165
+ describe Gorillib::Factory::ComplexFactory do
166
+ cplx0 = Complex(0) ; cplx1 = Complex(1) ; cplx1234500 = Complex(1_234_500,0) ; cplx1234500f = Complex(1_234_500.0,0) ;
167
+ it_behaves_like :it_considers_native, Complex(1,3), Complex(1,0)
168
+ it_behaves_like :it_converts, '1234.5e3' => cplx1234500f, '1234500' => cplx1234500, '0' => cplx0
169
+ it_behaves_like :it_converts, 1234.5e3 => cplx1234500f, 1 => cplx1, -1 => Complex(-1), Rational(3,2) => Complex(Rational(3,2),0)
170
+ it_behaves_like :it_converts, [1,0] => Complex(1), [1,2] => Complex(1,2)
171
+ it_behaves_like :it_converts, ['1234.5e3','98.6'] => Complex(1234.5e3, 98.6)
172
+ it_behaves_like :it_considers_blankish, nil, ''
173
+ it_behaves_like :it_is_a_mismatch_for, 'one', '3blindmice', '0x10', '1234.5e3f', '1234L', :foo, false, []
174
+ it_behaves_like :it_is_registered_as, :complex, Complex
175
+ its(:typename){ should == :complex }
176
+ end
177
+
178
+ describe Gorillib::Factory::RationalFactory do
179
+ rat_0 = Rational(0) ; rat1 = Rational(1) ; rat3_2 = Rational(3, 2) ;
180
+ it_behaves_like :it_considers_native, Rational(1, 3), Rational(1, 7)
181
+ it_behaves_like :it_converts, '1.5' => rat3_2, '1' => rat1, '0' => rat_0, '1_234_567' => Rational(1234567), '1_234_567.0' => Rational(1234567)
182
+ it_behaves_like :it_converts, 1.5 => rat3_2, 1 => rat1, -1 => Rational(-1), Complex(1.5) => rat3_2
183
+ it_behaves_like :it_considers_blankish, nil, ''
184
+ it_behaves_like :it_is_a_mismatch_for, 'one', '3blindmice', '0x10', '1234.5e3f', '1234L', :foo, false, [], Complex(1.5,3)
185
+ it_behaves_like :it_is_registered_as, :rational, Rational
186
+ its(:typename){ should == :rational }
187
+ end
188
+
189
+ describe Gorillib::Factory::TimeFactory do
190
+ fuck_wit_dre_day = Time.new(1993, 2, 18, 8, 8, 0, '-08:00') # and Everybody's Celebratin'
191
+ ice_cubes_good_day = Time.utc(1992, 1, 20, 0, 0, 0)
192
+ it_behaves_like :it_considers_native, Time.now.utc, ice_cubes_good_day
193
+ it_behaves_like :it_converts, fuck_wit_dre_day => fuck_wit_dre_day.getutc
194
+ it_behaves_like :it_converts, '19930218160800' => fuck_wit_dre_day.getutc, '19920120000000Z' => ice_cubes_good_day
195
+ it_behaves_like :it_converts, Date.new(1992, 1, 20) => ice_cubes_good_day
196
+ before('behaves like it_converts "an unparseable time" to nil'){ subject.stub(:warn) }
197
+ it_behaves_like :it_converts, "an unparseable time" => nil, :non_native_ok => true
198
+ it_behaves_like :it_considers_blankish, nil, ''
199
+ it_behaves_like :it_is_a_mismatch_for, :foo, false, []
200
+ it_behaves_like :it_is_registered_as, :time, Time
201
+ it('always returns a UTC timezoned time') do
202
+ subject.convert(fuck_wit_dre_day).utc_offset.should == 0
203
+ fuck_wit_dre_day.utc_offset.should == (-8 * 3600)
204
+ end
205
+ its(:typename){ should == :time }
206
+ end
207
+
208
+ describe Gorillib::Factory::BooleanFactory do
209
+ it_behaves_like :it_considers_native, true, false
210
+ it_behaves_like :it_considers_blankish, nil
211
+ it_behaves_like :it_converts, 'false' => false, :false => false
212
+ it_behaves_like :it_converts, 'true' => true, :true => true, '0' => true, 0 => true, [] => true, :foo => true, [] => true, Complex(1.5,3) => true, Object.new => true
213
+ it_behaves_like :it_is_registered_as, :boolean
214
+ its(:typename){ should == :boolean }
215
+ end
216
+
217
+ describe ::Whatever do
218
+ it_behaves_like :it_considers_native, true, false, nil, 3, '', 'a string', :a_symbol, [], {}, ->(){ 'a proc' }, Module.new, Complex(1,3), Object.new
219
+ it 'it is itself the factory for :identical and :whatever' do
220
+ keys = [Whatever, :identical, :whatever]
221
+ keys.each do |key|
222
+ Gorillib::Factory(key).should equal(described_class)
223
+ end
224
+ its_factory = ::Whatever
225
+ Gorillib::Factory.send(:factories).to_hash.select{|key,val| val.equal?(its_factory) }.keys.should == keys
226
+ end
227
+ end
228
+ describe Gorillib::Factory::IdenticalFactory do
229
+ it{ described_class.should equal(Whatever) }
230
+ end
231
+
232
+ describe Gorillib::Factory::ModuleFactory do
233
+ it_behaves_like :it_considers_blankish, nil
234
+ it_behaves_like :it_considers_native, Module, Module.new, Class, Class.new, Object, String, BasicObject
235
+ it_behaves_like :it_is_a_mismatch_for, true, false, 3, '', 'a string', :a_symbol, [], {}, ->(){ 'a proc' }, Complex(1,3), Object.new
236
+ it_behaves_like :it_is_registered_as, :module, Module
237
+ its(:typename){ should == :module }
238
+ end
239
+
240
+ describe Gorillib::Factory::ClassFactory do
241
+ it_behaves_like :it_considers_blankish, nil
242
+ it_behaves_like :it_considers_native, Module, Class, Class.new, Object, String, BasicObject
243
+ it_behaves_like :it_is_a_mismatch_for, true, false, 3, '', 'a string', :a_symbol, [], {}, ->(){ 'a proc' }, Module.new, Complex(1,3), Object.new
244
+ it_behaves_like :it_is_registered_as, :class, Class
245
+ its(:typename){ should == :class }
246
+ end
247
+
248
+ describe Gorillib::Factory::NilFactory do
249
+ it_behaves_like :it_considers_native, nil
250
+ it_behaves_like :it_is_a_mismatch_for, true, false, 3, '', 'a string', :a_symbol, [], {}, ->(){ 'a proc' }, Module.new, Complex(1,3), Object.new
251
+ it_behaves_like :it_is_registered_as, :nil, NilClass
252
+ its(:typename){ should == :nil_class }
253
+ end
254
+
255
+ describe Gorillib::Factory::TrueFactory do
256
+ it_behaves_like :it_considers_native, true
257
+ it_behaves_like :it_is_a_mismatch_for, false, 3, '', 'a string', :a_symbol, [], {}, ->(){ 'a proc' }, Module.new, Complex(1,3), Object.new
258
+ it_behaves_like :it_is_registered_as, :true, TrueClass
259
+ end
260
+
261
+ describe Gorillib::Factory::FalseFactory do
262
+ it_behaves_like :it_considers_native, false
263
+ it_behaves_like :it_is_a_mismatch_for, true, 3, '', 'a string', :a_symbol, [], {}, ->(){ 'a proc' }, Module.new, Complex(1,3), Object.new
264
+ it_behaves_like :it_is_registered_as, :false, FalseClass
265
+ end
266
+
267
+ describe Gorillib::Factory::RangeFactory do
268
+ it_behaves_like :it_considers_blankish, nil, []
269
+ it_behaves_like :it_considers_native, (1..2), ('a'..'z')
270
+ it_behaves_like :it_is_a_mismatch_for, true, 3, '', 'a string', :a_symbol, [1,2], {}, ->(){ 'a proc' }, Module.new, Complex(1,3), Object.new
271
+ it_behaves_like :it_is_registered_as, :range, Range
272
+ its(:typename){ should == :range }
273
+ end
274
+
275
+ # __________________________________________________________________________
276
+
277
+ describe Gorillib::Factory::HashFactory do
278
+ let(:collection_123){ { 'a' => 1, :b => 2, 'c' => 3 } }
279
+ let(:empty_collection){ {} }
280
+
281
+ it_behaves_like :it_considers_blankish, nil
282
+ it_behaves_like :it_converts, { {} => {}, { "a" => 2 } => { 'a' => 2 }, { :a => 2 } => { :a => 2 }, :non_native_ok => true }
283
+ it_behaves_like :it_is_a_mismatch_for, [1,2,3]
284
+ it_behaves_like :an_enumerable_factory
285
+
286
+ it 'follows examples' do
287
+ described_class.new.receive(collection_123).should == { 'a' => 1, :b => 2, 'c' => 3}
288
+ described_class.new(:keys => :symbol).receive({'a' => 'x', :b => 'y', 'c' => :z}).should == {:a => 'x', :b => 'y', :c => :z}
289
+ described_class.new(:items => :symbol).receive({'a' => 'x', :b => 'y', 'c' => :z}).should == {'a' => :x, :b => :y, 'c' => :z}
290
+ autov_factory = described_class.new(:empty_product => Hash.new{|h,k| h[k] = {} })
291
+ result = autov_factory.receive({:a => :b}) ; result.should == { :a => :b }
292
+ result[:flanger][:modacity] = 11 ; result.should == { :a => :b, :flanger => { :modacity => 11 }}
293
+ result2 = autov_factory.receive({:x => :y}) ; result2.should == { :x => :y } ; result.should == { :a => :b, :flanger => { :modacity => 11 }}
294
+ end
295
+
296
+ it "accepts a factory for the keys" do
297
+ mock_factory = double('factory')
298
+ mock_factory.should_receive(:receive).with(3).and_return("converted!")
299
+ factory = described_class.new(:keys => mock_factory)
300
+ factory.receive( { 3 => 4 } ).should == { 'converted!' => 4 }
301
+ end
302
+ it_behaves_like :it_is_registered_as, :hash, Hash
303
+ its(:typename){ should == :hash }
304
+ end
305
+
306
+ describe Gorillib::Factory::ArrayFactory do
307
+ let(:collection_123){ [1,2,3] }
308
+ let(:empty_collection){ [] }
309
+
310
+ it 'follows examples' do
311
+ described_class.new.receive([1,2,3]).should == [1,2,3]
312
+ described_class.new(:items => :symbol).receive(['a', 'b', :c]).should == [:a, :b, :c]
313
+ described_class.new(:empty_product => [1,2,3]).receive([:a, :b, :c]).should == [1, 2, 3, :a, :b, :c]
314
+ end
315
+
316
+ it_behaves_like :it_considers_blankish, nil
317
+ it_behaves_like :it_converts, { [] => [], {} => [], [1,2,3] => [1,2,3], {:a => :b} => [[:a, :b]], [:a] => [:a], [[]] => [[]], :non_native_ok => true }
318
+ it_behaves_like :an_enumerable_factory
319
+ it_behaves_like :it_is_registered_as, :array, Array
320
+ its(:typename){ should == :array }
321
+ end
322
+
323
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ require 'gorillib/model/lint'
4
+
5
+ describe Gorillib::Model::Lint, :model_spec => true do
6
+ subject do
7
+ klass = Class.new{ include Gorillib::Model ; include Gorillib::Model::Lint ; field :bob, Integer }
8
+ klass.new
9
+ end
10
+
11
+ context '#read_attribute' do
12
+ it "raises an error if the field does not exist" do
13
+ ->{ subject.read_attribute(:fnord) }.should raise_error(Gorillib::Model::UnknownFieldError, /unknown field: fnord/)
14
+ end
15
+ end
16
+
17
+ context '#write_attribute' do
18
+ it "raises an error if the field does not exist" do
19
+ ->{ subject.write_attribute(:fnord, 8) }.should raise_error(Gorillib::Model::UnknownFieldError, /unknown field: fnord/)
20
+ end
21
+ end
22
+
23
+ context '#attribute_set?' do
24
+ it "raises an error if the field does not exist" do
25
+ ->{ subject.attribute_set?(:fnord) }.should raise_error(Gorillib::Model::UnknownFieldError, /unknown field: fnord/)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ require 'gorillib/model/serialization'
4
+
5
+ describe Gorillib::Model::LoadFromCsv, :model_spec => true, :builder_spec => true do
6
+
7
+ context ".load_csv" do
8
+
9
+ let(:expected_engine) do
10
+ {:name=>:Wankel, :carburetor=>:no, :volume=>1, :cylinders=>982, :owner=>"who_am_i"}
11
+ end
12
+
13
+ before :each do
14
+ engine_class.class_eval { include Gorillib::Model::LoadFromCsv }
15
+ csv_file = double('csv_file')
16
+ csv_file.stub(:shift) {}
17
+ csv_file.stub(:each).and_yield(expected_engine.values)
18
+ CSV.should_receive(:open).and_yield(csv_file)
19
+ end
20
+
21
+ it "loads from file" do
22
+ engine_class.load_csv('test').to_wire().first.keep_if{|k,| k != :_type}.should
23
+ eql(expected_engine)
24
+ end
25
+
26
+ it "loads from file with block" do
27
+ expect { |b| engine_class.load_csv('test', &b) }.to yield_with_args(engine_class)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ require 'gorillib/model/serialization'
4
+
5
+ describe Gorillib::Model::LoadFromTsv, :model_spec => true, :builder_spec => true do
6
+
7
+ context ".load_tsv" do
8
+
9
+ let(:expected_engine) do
10
+ {:name=>:Wankel, :carburetor=>:no, :volume=>1, :cylinders=>982, :owner=>"who_am_i"}
11
+ end
12
+
13
+ before :each do
14
+ engine_class.class_eval { include Gorillib::Model::LoadFromTsv }
15
+ engine_class.should_receive(:_each_raw_line).with(:test, {}).
16
+ and_yield(expected_engine.values.join("\t"))
17
+ end
18
+
19
+ it "loads from file" do
20
+ engine_class.load_tsv(:test).to_wire().first.keep_if{|k,| k != :_type}.should
21
+ eql(expected_engine)
22
+ end
23
+
24
+ it "loads from file with block" do
25
+ expect { |b| engine_class.load_tsv(:test, &b) }.to yield_with_args(engine_class)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ require 'gorillib/model/serialization'
4
+
5
+ describe Gorillib::Model, :model_spec => true, :builder_spec => true do
6
+ subject do
7
+ garage.cars << wildcat
8
+ garage.cars << ford_39
9
+ garage
10
+ end
11
+ let :wired_garage_hash do
12
+ { :cars => [
13
+ {:name=>:wildcat, :make_model=>"Buick Wildcat", :year=>1968, :doors=>2, :engine=>{:volume=>455, :cylinders=>8, :_type => "gorillib.test.engine"}, :_type => "gorillib.test.car"},
14
+ {:name=>:ford_39, :make_model=>"Ford Tudor Sedan", :year=>1939, :doors=>2, :_type => "gorillib.test.car"}, ], :_type => "gorillib.test.garage" }
15
+ end
16
+
17
+ describe 'to_json' do
18
+ it 'recursively serializes' do
19
+ MultiJson.load(wildcat.to_json).should == {"name"=>"wildcat","make_model"=>"Buick Wildcat","year"=>1968,"doors"=>2,"engine"=>{"volume"=>455,"cylinders"=>8, "_type"=>"gorillib.test.engine"},"_type"=>"gorillib.test.car"}
20
+ end
21
+ it 'recursively serializes' do
22
+ subject.to_json.should == MultiJson.dump(wired_garage_hash)
23
+ end
24
+ end
25
+
26
+ describe 'to_wire' do
27
+ it 'calls to_wire recursively, passing options along' do
28
+ opts = {:dummy=>'options'}
29
+ ford_39.should_receive(:to_wire).with(opts)
30
+ wildcat.engine.should_receive(:to_wire).with(opts)
31
+ subject.to_wire(opts)
32
+ end
33
+
34
+ it 'returns a nested hash' do
35
+ subject.to_wire.should == wired_garage_hash
36
+ end
37
+ it 'aliases method as_json' do
38
+ subject.as_json.should == wired_garage_hash
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ require 'gorillib/model/type/extended'
4
+
5
+ describe ::Long do
6
+ it "is_a?(Integer)" do ::Long.should < ::Integer ; end
7
+ end
8
+
9
+ describe ::Double do
10
+ it "is_a?(Float)" do ::Double.should < ::Float ; end
11
+ end
12
+
13
+ describe ::Binary do
14
+ it "is_a?(String)" do ::Binary.should < ::String ; end
15
+ end
16
+
17
+ describe 'factory', :factory_spec => true do
18
+ describe Gorillib::Factory::DateFactory do
19
+ fuck_wit_dre_day = Date.new(1993, 2, 18) # and Everybody's Celebratin'
20
+ ice_cubes_good_day = Date.new(1992, 1, 20)
21
+ it_behaves_like :it_considers_native, Date.today, fuck_wit_dre_day, ice_cubes_good_day
22
+ it_behaves_like :it_converts, '19930218' => fuck_wit_dre_day, '19920120' => ice_cubes_good_day
23
+ it_behaves_like :it_converts, Time.utc(1992, 1, 20, 8, 8, 8) => ice_cubes_good_day
24
+ before('behaves like it_converts "an unparseable date" to nil'){ subject.stub(:warn) }
25
+ it_behaves_like :it_converts, "an unparseable date" => nil, :non_native_ok => true
26
+ it_behaves_like :it_considers_blankish, nil, ""
27
+ it_behaves_like :it_is_a_mismatch_for, :foo, false, []
28
+ it_behaves_like :it_is_registered_as, :date, Date
29
+ its(:typename){ should == :date }
30
+ end
31
+
32
+ describe Gorillib::Factory::SetFactory do
33
+ let(:collection_123){ Set.new([1,2,3]) }
34
+ let(:empty_collection){ Set.new }
35
+
36
+ it 'follows examples' do
37
+ described_class.new.receive([1,2,3]).should == collection_123
38
+ described_class.new(:items => :symbol).receive(['a', 'b', :c]).should == [:a, :b, :c].to_set
39
+ described_class.new(:empty_product => [1,2,3].to_set).receive([:a, :b, :c]).should == [1, 2, 3, :a, :b, :c].to_set
40
+
41
+ has_an_empty_array = described_class.new.receive( [[]] )
42
+ has_an_empty_array.should == Set.new( [[]] )
43
+ has_an_empty_array.first.should == []
44
+ has_an_empty_array.size.should == 1
45
+ end
46
+
47
+ it_behaves_like :it_considers_blankish, nil
48
+ it_behaves_like :it_converts, { [] => Set.new, {} => Set.new, [1,2,3] => [1,2,3].to_set, {:a => :b} => Set.new({:a => :b}), [:a] => [:a].to_set, :non_native_ok => true }
49
+ it_behaves_like :an_enumerable_factory
50
+ it_behaves_like :it_is_registered_as, :set, Set
51
+ its(:typename){ should == :set }
52
+ end
53
+
54
+ describe Gorillib::Factory::Boolean10Factory do
55
+ it_behaves_like :it_considers_native, true, false
56
+ it_behaves_like :it_considers_blankish, nil
57
+ it_behaves_like :it_converts, "false" => false, :false => false, "0" => false, 0 => false
58
+ it_behaves_like :it_converts, "true" => true, :true => true, "1" => true, [] => true, :foo => true, [] => true, Complex(1.5,3) => true, Object.new => true
59
+ it_behaves_like :it_is_registered_as, :boolean_10
60
+ its(:typename){ should == :boolean_10 }
61
+ end
62
+ end
63
+
64
+ # describe ::Boolean, :model_spec => true do
65
+ # let(:true_bool ){ ::Boolean.new(true) }
66
+ # let(:false_bool){ ::Boolean.new(false) }
67
+ #
68
+ # def it_responds_same_as(test_obj, comparable, meth, *meth_args, &block)
69
+ # test_obj.send(meth, *meth_args, &block).should == comparable.send(meth, *meth_args, &block)
70
+ # end
71
+ #
72
+ # def it_responds_with_same_contents(test_obj, comparable, meth, *meth_args, &block)
73
+ # test_obj.send(meth, *meth_args, &block).sort.should == comparable.send(meth, *meth_args, &block).sort
74
+ # end
75
+ #
76
+ # it("has #class ::Boolean" ){ (true_bool.class).should == ::Boolean ; (false_bool.class).should == ::Boolean }
77
+ #
78
+ # it "#is_a?(Boolean)" do true_bool.should be_a(::Boolean) ; false_bool.should be_a(::Boolean) ; end
79
+ # it "#is_a?(True/False)" do true_bool.should be_a(::TrueClass) ; false_bool.should be_a(::FalseClass) ; end
80
+ # it "#kind_of?(Boolean)" do true_bool.should be_a_kind_of(::Boolean) ; false_bool.should be_a_kind_of(::Boolean) ; end
81
+ # it "#instance_of?(True/False)" do true_bool.should be_instance_of(::TrueClass) ; false_bool.should be_instance_of(::FalseClass) ; end
82
+ #
83
+ # describe 'mimics true/false' do
84
+ # [ :!, :to_s, :blank?, :frozen?, :nil?, :present?,
85
+ # ].each do |meth|
86
+ # it "##{meth}" do
87
+ # it_responds_same_as(true_bool, true, meth)
88
+ # it_responds_same_as(false_bool, false, meth)
89
+ # end
90
+ # end
91
+ #
92
+ # [ :private_methods, :protected_methods, :singleton_methods,
93
+ # ].each do |meth|
94
+ # it "##{meth}" do
95
+ # it_responds_with_same_contents(true_bool, true, meth)
96
+ # it_responds_with_same_contents(false_bool, false, meth)
97
+ # end
98
+ # end
99
+ # it "#methods" do ( true.methods - true_bool.methods ).should be_empty ; end
100
+ # it "#methods" do ( false.methods - false_bool.methods ).should be_empty ; end
101
+ # it "#public_methods" do ( true.public_methods - true_bool.public_methods ).should be_empty ; end
102
+ # it "#public_methods" do ( false.public_methods - false_bool.public_methods ).should be_empty ; end
103
+ #
104
+ # it ".methods" do (TrueClass.methods | [:true, :false, :new]).sort.should == Boolean.methods.sort ; end
105
+ #
106
+ # { :!= => [true, false, nil],
107
+ # :!~ => [true, false, nil],
108
+ # :& => [true, false, nil],
109
+ # :<=> => [true, false, nil],
110
+ # :== => [true, false, nil],
111
+ # :=== => [true, false, nil],
112
+ # :=~ => [true, false, nil],
113
+ # :^ => [true, false, nil],
114
+ # :| => [true, false, nil],
115
+ # :eql? => [true, false, nil],
116
+ # :equal? => [true, false, nil],
117
+ # :instance_of? => [::TrueClass, ::FalseClass, ::Object],
118
+ # :is_a? => [::TrueClass, ::FalseClass, ::Object],
119
+ # :kind_of? => [::TrueClass, ::FalseClass, ::Object],
120
+ # }.each do |meth, meth_args|
121
+ # meth_args.each do |meth_arg|
122
+ # it "##{meth}(#{meth_arg})" do
123
+ # it_responds_same_as(true_bool, true, meth, meth_arg)
124
+ # it_responds_same_as(false_bool, false, meth, meth_arg)
125
+ # end
126
+ # end
127
+ # end
128
+ #
129
+ # end
130
+ #
131
+ # [ :==, :===, :eql?, :equal?, :<=> ].each do |meth|
132
+ # it "Boolean.true #{meth} itself and true" do
133
+ # true_bool.send(meth, true_bool ).should be_true
134
+ # true_bool.send(meth, Boolean.true ).should be_true
135
+ # true_bool.send(meth, true ).should be_true
136
+ # true_bool.send(meth, false_bool ).should be_false
137
+ # true_bool.send(meth, Boolean.false ).should be_false
138
+ # true_bool.send(meth, false ).should be_false
139
+ # true_bool.send(meth, 0 ).should be_false
140
+ # end
141
+ # it "Boolean.false #{meth} itself and false" do
142
+ # false_bool.send(meth, false_bool ).should be_true
143
+ # false_bool.send(meth, Boolean.false ).should be_true
144
+ # false_bool.send(meth, false ).should be_true
145
+ # false_bool.send(meth, true_bool ).should be_false
146
+ # false_bool.send(meth, Boolean.true ).should be_false
147
+ # false_bool.send(meth, true ).should be_false
148
+ # false_bool.send(meth, 0 ).should be_false
149
+ # end
150
+ # it "!=" do
151
+ # (true_bool != true ).should be_false ; (true_bool != false ).should be_true
152
+ # (true_bool != true_bool ).should be_false ; (true_bool != false_bool ).should be_true
153
+ # (true_bool != Boolean.true ).should be_false ; (true_bool != Boolean.false).should be_true
154
+ # (true_bool != 0 ).should be_true ; (true_bool != "true" ).should be_true
155
+ # (false_bool != false ).should be_false ; (false_bool != true ).should be_true
156
+ # (false_bool != false_bool ).should be_false ; (false_bool != true_bool ).should be_true
157
+ # (false_bool != Boolean.false).should be_false ; (false_bool != Boolean.true ).should be_true
158
+ # (false_bool != 0 ).should be_true ; (false_bool != "true" ).should be_true
159
+ # end
160
+ # it "!~" do
161
+ # (true_bool !~ true ).should be_true
162
+ # (true_bool !~ true_bool ).should be_true
163
+ # (true_bool !~ Boolean.true).should be_true
164
+ # end
165
+ # end
166
+ # end