foraneus 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 6a1af4481bfbdeb0cc0aa78900c6b7f4512d7a21
4
- data.tar.gz: 58cd1c7f084558def0575754919263b6763ba17a
5
- SHA512:
6
- metadata.gz: 093a3fdc5eecea2934cd2ef01c88191bcf62fe317f61ed73519d8a77b4afcadd2ff96b5af17d4e5337e43da96bdd325861b6f94ca53d0a6642db6ffaf0aa5a03
7
- data.tar.gz: cbf2a485c1df7a4da036256ea27f6a8097f7433cb8b4bcd3e5c922e1ef985b2003ed6a5e442f3755af1f89a66da393efd6c80f314787f54c6d9767223304fd1f
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d581bebcc546182ffb84546ff4fb8ad667ee126f
4
+ data.tar.gz: 241b1dfc78a1837a6ec6404904ab1a4b1f6d3125
5
+ SHA512:
6
+ metadata.gz: 457b8493632fb86f01ea610b164f05df68c0f85f156ab26d3c7fe98ee62a2262c9a2281dd037f636ffb31fac42b49f68ad66386dcd264db5023134d9ef0fbe15
7
+ data.tar.gz: 4c668906d942e090e563b7ec8a8241c4cfa1cb42096bad58146c168aca89672cdd82b1a92c99896fd8bcf7af7c354d5a9e525fb7a32122f9900103fc4060d52d
@@ -10,13 +10,14 @@ require 'foraneus/converters/integer'
10
10
  require 'foraneus/converters/noop'
11
11
  require 'foraneus/converters/string'
12
12
  require 'foraneus/errors'
13
+ require 'foraneus/utils'
13
14
 
14
15
  # Foraneus base class used to declare a data set, aka 'form'.
15
16
  class Foraneus
16
17
 
17
18
  # @api private
18
19
  def initialize
19
- @_ = {}
20
+ @_ = {} # Hash that holds external representation data
20
21
  end
21
22
 
22
23
  # Declares a boolean field.
@@ -99,6 +100,11 @@ class Foraneus
99
100
  @fields ||= {}
100
101
  end
101
102
 
103
+ # Return the names of data and error accessors
104
+ #
105
+ # Returned hash contains the keys :data and :errors, where values are the proper accesor names
106
+ #
107
+ # @return [Hash]
102
108
  def self.accessors
103
109
  @accessors ||= {
104
110
  :data => :data,
@@ -106,11 +112,14 @@ class Foraneus
106
112
  }
107
113
  end
108
114
 
115
+ # Create a new instance while setting up data and error accessors
116
+ #
117
+ # @return [Foraneus]
109
118
  def self.create_instance
110
119
  instance = self.new
111
120
 
112
- __singleton_attr_reader(instance, :data, {})
113
- __singleton_attr_reader(instance, :errors, {})
121
+ Utils.singleton_attr_accessor(instance, :data, {})
122
+ Utils.singleton_attr_accessor(instance, :errors, {})
114
123
 
115
124
  instance
116
125
  end
@@ -122,24 +131,12 @@ class Foraneus
122
131
  # @return [Foraneus] An instance of a form.
123
132
  def self.parse(data = {})
124
133
  instance = self.create_instance
134
+ data = data.dup
125
135
 
126
- parsed_keys = []
136
+ instance.instance_variable_set(:@_, data.dup)
127
137
 
128
138
  fields.each do |field, converter|
129
- given_key = field
130
- v = data.fetch(given_key) do
131
- given_key = field.to_sym
132
- data.fetch(given_key, nil)
133
- end
134
-
135
- parsed_keys << given_key
136
- __parse_raw_datum(given_key, v, instance, converter)
137
- end
138
-
139
- data.each do |k, v|
140
- unless parsed_keys.include?(k)
141
- instance[k] = v
142
- end
139
+ __parse_field(data, field, converter, instance)
143
140
  end
144
141
 
145
142
  instance
@@ -152,16 +149,12 @@ class Foraneus
152
149
  # @return [Foraneus] An instance of a form.
153
150
  def self.raw(data = {})
154
151
  instance = self.create_instance
152
+ data = data.dup
155
153
 
156
- fields.each do |field, converter|
157
- given_key = field
158
-
159
- v = data.fetch(given_key) do
160
- given_key = field.to_sym
161
- data.fetch(given_key, nil)
162
- end
154
+ instance.send("#{self.accessors[:data]}=", data)
163
155
 
164
- __raw_datum(given_key, v, instance, converter)
156
+ fields.each do |field, converter|
157
+ __raw_field(data, field, converter, instance)
165
158
  end
166
159
 
167
160
  instance
@@ -174,8 +167,8 @@ class Foraneus
174
167
  if m.nil?
175
168
  @_
176
169
  else
177
- @_.fetch(m) do
178
- @_[m.to_s]
170
+ @_.fetch(m.to_s) do
171
+ @_[m.to_sym]
179
172
  end
180
173
  end
181
174
  end
@@ -198,100 +191,33 @@ class Foraneus
198
191
  @errors.empty?
199
192
  end
200
193
 
201
- # @api private
202
- #
203
- # Parses a value and assigns it to the corresponding field.
204
- #
205
- # It also registers errors if the conversion fails.
206
- #
207
- # @param [String, Symbol] k
208
- # @param [String] v
209
- # @param [Foraneus] foraneus
210
- # @param [Converter] converter
211
- def self.__parse_raw_datum(k, v, foraneus, converter)
212
- field = k.to_s
213
-
214
- foraneus[k] = v
215
-
216
- v = __parse(k, v, converter)
194
+ def self.__parse_field(data, field, converter, instance)
195
+ s, is_present = Utils.fetch(data, field)
217
196
 
218
- foraneus.send("#{field}=", v)
219
- foraneus.send(self.accessors[:data])[k] = v
197
+ v, error = Utils.parse_datum(field, s, converter)
220
198
 
221
- rescue
222
- error = Foraneus::Error.new($!.class.name, $!.message)
223
- foraneus.send(self.accessors[:errors])[k] = error
224
- end
225
- private_class_method :__parse_raw_datum
226
-
227
- # @api private
228
- #
229
- # Parses a raw value.
230
- #
231
- # @param [String, Symbol] field
232
- # @param [String] v Raw value.
233
- # @param converter
234
- #
235
- # @raise [KeyError] if converter requires a value but no one is given.
236
- #
237
- # @return [Object]
238
- def self.__parse(field, v, converter)
239
- if v == '' && converter.opts.fetch(:blanks_as_nil, true)
240
- v = nil
199
+ unless error
200
+ instance.send("#{field}=", v)
201
+ instance.send(self.accessors[:data])[field.to_sym] = v if is_present || converter.opts.include?(:default)
241
202
  end
242
203
 
243
- if v.nil? && converter.opts[:required]
244
- raise KeyError, "required parameter not found: #{field.inspect}"
245
- elsif v.nil?
246
- converter.opts[:default]
247
- else
248
- converter.parse(v)
249
- end
204
+ instance.send(self.accessors[:errors])[field.to_sym] = error if error
250
205
  end
251
- private_class_method :__parse
206
+ private_class_method :__parse_field
252
207
 
253
- # @api private
254
- #
255
- # Obtains a raw representation of a value and assigns it to the corresponding field.
256
- #
257
- # It also registers errors if the conversion fails.
258
- #
259
- # @param [String, Symbol] k
260
- # @param [String] v
261
- # @param [Foraneus] foraneus
262
- # @param [Converter] converter
263
- def self.__raw_datum(k, v, foraneus, converter)
264
- foraneus.send("#{k}=", v)
208
+ def self.__raw_field(data, field, converter, instance)
209
+ v, is_present = Utils.fetch(data, field)
210
+
211
+ instance.send("#{field}=", v)
265
212
 
266
213
  if v.nil?
267
214
  v = converter.opts[:default]
268
215
  end
269
216
 
270
- s = unless v.nil?
271
- converter.raw(v)
272
- end
273
-
274
- foraneus[k] = s
275
- foraneus.send(self.accessors[:data])[k] = v
276
- end
277
- private_class_method :__raw_datum
278
-
279
- # @api private
280
- #
281
- # Creates a singleton attribute reader on an instance.
282
- #
283
- # @param [Foraneus] instance
284
- # @param [Symbol] attribute
285
- # @param initial_value
286
- def self.__singleton_attr_reader(instance, attribute, initial_value = nil)
287
- spec = instance.class
217
+ s = Utils.raw_datum(v, converter)
288
218
 
289
- instance.singleton_class.send(:attr_reader, spec.accessors[attribute])
290
-
291
- instance.instance_exec do
292
- instance.instance_variable_set(:"@#{spec.accessors[attribute]}", initial_value)
293
- end
219
+ instance[field.to_sym] = s if is_present || converter.opts.include?(:default)
294
220
  end
295
- private_class_method :__singleton_attr_reader
221
+ private_class_method :__raw_field
296
222
 
297
223
  end
@@ -0,0 +1,86 @@
1
+ class Foraneus
2
+ module Utils
3
+
4
+ # Return the value of a key in the given hash and flag indicating whether the keys exists or not
5
+ #
6
+ # If the given key is not present then tries fetching key#to_sym
7
+ #
8
+ # @param [Hash] data
9
+ # @param [String] field
10
+ #
11
+ # @return [Object, Boolean]
12
+ def self.fetch(hash, key)
13
+ v = nil
14
+ is_present = true
15
+
16
+ v = hash.fetch(key) do
17
+ hash.fetch(key.to_sym) do
18
+ is_present = false
19
+ nil
20
+ end
21
+ end
22
+
23
+ [v, is_present]
24
+ end
25
+
26
+ # Parses a raw value.
27
+ #
28
+ # @param [String, Symbol] field
29
+ # @param [String] s Raw value.
30
+ # @param converter
31
+ #
32
+ # @raise [KeyError] if converter requires a value but no one is given.
33
+ #
34
+ # @return [Object, nil] when parsing succeeds
35
+ # @return [nil, Foraneus::Error] when parsing fails
36
+ def self.parse_datum(field, s, converter)
37
+ if s == '' && converter.opts.fetch(:blanks_as_nil, true)
38
+ s = nil
39
+ end
40
+
41
+ if s.nil? && converter.opts[:required]
42
+ raise KeyError, "required parameter not found: #{field.inspect}"
43
+ end
44
+
45
+ result = if s.nil?
46
+ converter.opts[:default]
47
+
48
+ else
49
+ converter.parse(s)
50
+ end
51
+
52
+ [result, nil]
53
+
54
+ rescue
55
+ error = Foraneus::Error.new($!.class.name, $!.message)
56
+
57
+ [nil, error]
58
+ end
59
+
60
+ # Obtains a raw representation of a value and assigns it to the corresponding field.
61
+ #
62
+ # @param [Object] v
63
+ # @param [Converter] converter
64
+ #
65
+ # @return [String]
66
+ def self.raw_datum(v, converter)
67
+ converter.raw(v) unless v.nil?
68
+ end
69
+
70
+ # Creates a singleton attribute accessor on an instance.
71
+ #
72
+ # @param [Foraneus] instance
73
+ # @param [Symbol] attribute
74
+ # @param initial_value
75
+ def self.singleton_attr_accessor(instance, attribute, initial_value = nil)
76
+ spec = instance.class
77
+
78
+ instance.singleton_class.send(:attr_accessor, spec.accessors[attribute])
79
+
80
+ instance.instance_exec do
81
+ instance.instance_variable_set(:"@#{spec.accessors[attribute]}", initial_value)
82
+ end
83
+ end
84
+
85
+ end
86
+ end
@@ -82,9 +82,10 @@ describe Foraneus do
82
82
 
83
83
  assert_equal 5, subject.delay
84
84
  assert_equal 5, subject.data[:delay]
85
+ assert_equal({ :delay => 5 }, subject.data)
85
86
 
86
87
  assert_equal '5', subject[:delay]
87
- assert_nil subject['delay']
88
+ assert_equal '5', subject['delay']
88
89
  assert_equal({ :delay => '5' }, subject[])
89
90
 
90
91
  assert subject.valid?
@@ -98,7 +99,8 @@ describe Foraneus do
98
99
  it 'parses given data' do
99
100
  assert_equal '5', subject['delay']
100
101
  assert_equal '5', subject[:delay]
101
- assert_equal 5, subject.data['delay']
102
+
103
+ assert_equal({ :delay => 5 }, subject.data)
102
104
 
103
105
  assert_equal({ 'delay' => '5' }, subject[])
104
106
  end
@@ -267,11 +269,7 @@ describe Foraneus do
267
269
 
268
270
  assert_equal 1, subject.delay
269
271
 
270
- assert_equal 1, subject.data[:delay]
271
-
272
- assert_nil subject[:delay]
273
-
274
- assert_nil subject[][:delay]
272
+ assert_equal({ :delay => 1}, subject.data)
275
273
 
276
274
  refute subject.errors.include?(:delay)
277
275
  end
@@ -289,6 +287,21 @@ describe Foraneus do
289
287
  assert_nil subject[:delay]
290
288
  end
291
289
  end
290
+
291
+ describe 'when missing optional field' do
292
+ let(:converter) { Foraneus::Converters::Integer.new(:required => false) }
293
+
294
+ subject { form_spec.parse }
295
+
296
+ it 'parses' do
297
+ assert subject.valid?
298
+
299
+ assert_nil subject.delay
300
+ refute_includes subject.data, :delay
301
+
302
+ refute_includes subject[], :delay
303
+ end
304
+ end
292
305
  end
293
306
  end
294
307
  end
@@ -303,7 +316,7 @@ describe Foraneus do
303
316
 
304
317
  assert_equal '5', subject[:delay]
305
318
 
306
- assert_equal '5', subject[][:delay]
319
+ assert_equal({ :delay => '5' }, subject[])
307
320
 
308
321
  assert subject.valid?
309
322
 
@@ -320,7 +333,7 @@ describe Foraneus do
320
333
 
321
334
  assert_equal '5', subject[:delay]
322
335
 
323
- assert_equal '5', subject[]['delay']
336
+ assert_equal({ :delay => '5' }, subject[])
324
337
 
325
338
  assert subject.valid?
326
339
 
@@ -349,11 +362,22 @@ describe Foraneus do
349
362
 
350
363
  it 'parses' do
351
364
  assert_nil subject.delay
365
+ refute_includes subject.data, :delay
352
366
 
353
367
  assert_equal '1', subject[:delay]
354
368
  assert_equal '1', subject[][:delay]
355
369
  end
356
370
  end
357
- end
358
371
 
372
+ describe 'with absent values' do
373
+ subject { form_spec.raw }
374
+
375
+ it 'parses' do
376
+ assert_nil subject.delay
377
+
378
+ assert_equal({}, subject.data)
379
+ assert_equal({}, subject[])
380
+ end
381
+ end
382
+ end
359
383
  end
metadata CHANGED
@@ -1,52 +1,63 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: foraneus
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.14
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.15
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Gianfranco Zas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2014-12-04 00:00:00 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
11
+ date: 2015-04-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
15
14
  name: minitest
16
- prerelease: false
17
- requirement: &id001 !ruby/object:Gem::Requirement
18
- requirements:
19
- - &id002
20
- - ">="
21
- - !ruby/object:Gem::Version
22
- version: "0"
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
23
20
  type: :development
24
- version_requirements: *id001
25
- - !ruby/object:Gem::Dependency
26
- name: yard
27
21
  prerelease: false
28
- requirement: &id003 !ruby/object:Gem::Requirement
29
- requirements:
30
- - *id002
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: yard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
31
34
  type: :development
32
- version_requirements: *id003
33
- - !ruby/object:Gem::Dependency
34
- name: kramdown
35
35
  prerelease: false
36
- requirement: &id004 !ruby/object:Gem::Requirement
37
- requirements:
38
- - *id002
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: kramdown
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
39
48
  type: :development
40
- version_requirements: *id004
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Provides two way transformation mechanisms to external data.
42
56
  email: snmgian@gmail.com
43
57
  executables: []
44
-
45
58
  extensions: []
46
-
47
59
  extra_rdoc_files: []
48
-
49
- files:
60
+ files:
50
61
  - COPYING
51
62
  - COPYING.LESSER
52
63
  - README.md
@@ -60,6 +71,7 @@ files:
60
71
  - lib/foraneus/converters/noop.rb
61
72
  - lib/foraneus/converters/string.rb
62
73
  - lib/foraneus/errors.rb
74
+ - lib/foraneus/utils.rb
63
75
  - spec/lib/foraneus/converters/boolean_converter_spec.rb
64
76
  - spec/lib/foraneus/converters/date_converter_spec.rb
65
77
  - spec/lib/foraneus/converters/decimal_converter_spec.rb
@@ -70,42 +82,38 @@ files:
70
82
  - spec/lib/foraneus_spec.rb
71
83
  - spec/runner.rb
72
84
  - spec/spec_helper.rb
73
- - spec/spec_helper_its.rb
74
85
  homepage: https://github.com/snmgian/foraneus
75
- licenses:
86
+ licenses:
76
87
  - LGPL
77
88
  metadata: {}
78
-
79
89
  post_install_message:
80
90
  rdoc_options: []
81
-
82
- require_paths:
91
+ require_paths:
83
92
  - lib
84
- required_ruby_version: !ruby/object:Gem::Requirement
85
- requirements:
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
86
95
  - - ">="
87
- - !ruby/object:Gem::Version
96
+ - !ruby/object:Gem::Version
88
97
  version: 1.8.7
89
- required_rubygems_version: !ruby/object:Gem::Requirement
90
- requirements:
91
- - *id002
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
92
103
  requirements: []
93
-
94
104
  rubyforge_project:
95
105
  rubygems_version: 2.4.5
96
106
  signing_key:
97
107
  specification_version: 4
98
108
  summary: Transforms external data.
99
- test_files:
100
- - spec/lib/foraneus_spec.rb
109
+ test_files:
110
+ - spec/lib/foraneus/converters/float_converter_spec.rb
101
111
  - spec/lib/foraneus/converters/noop_converter_spec.rb
102
- - spec/lib/foraneus/converters/decimal_converter_spec.rb
103
112
  - spec/lib/foraneus/converters/date_converter_spec.rb
113
+ - spec/lib/foraneus/converters/decimal_converter_spec.rb
104
114
  - spec/lib/foraneus/converters/integer_converter_spec.rb
105
- - spec/lib/foraneus/converters/string_converter_spec.rb
106
- - spec/lib/foraneus/converters/float_converter_spec.rb
107
115
  - spec/lib/foraneus/converters/boolean_converter_spec.rb
108
- - spec/spec_helper.rb
109
- - spec/spec_helper_its.rb
116
+ - spec/lib/foraneus/converters/string_converter_spec.rb
117
+ - spec/lib/foraneus_spec.rb
110
118
  - spec/runner.rb
111
- has_rdoc:
119
+ - spec/spec_helper.rb
@@ -1,42 +0,0 @@
1
-
2
- require 'minitest/autorun'
3
- require 'minitest/spec'
4
- require 'minitest/unit'
5
-
6
- require 'foraneus'
7
-
8
- module MiniTest
9
- class Spec
10
- #module
11
-
12
- def self.its(getter, &block)
13
- block ||= proc { skip "(no tests defined)" }
14
-
15
- @specs ||= 0
16
- @specs += 1
17
-
18
- name = "test_%04d_%s" % [ @specs, getter ]
19
-
20
- define_method(name) {
21
- #&block
22
- case getter
23
- when Symbol, String
24
- expression = subject.public_send(getter)
25
- when Array
26
- expression = subject[*getter]
27
- end
28
-
29
- expression.instance_exec &block
30
- }
31
-
32
- self.children.each do |mod|
33
- mod.send :undef_method, name if mod.public_method_defined? name
34
- end
35
-
36
- name
37
- end
38
-
39
- #end
40
- end
41
- end
42
-