gorillib-model 0.0.1

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.
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