foraneus 0.0.7 → 0.0.8

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.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZWMwYTU4OWRiZmI3YWMyYzVjYTc3OTc1YzJiOTUzZDM4YmU5YzZjNw==
5
- data.tar.gz: !binary |-
6
- Mjc1YzUwODZhMTRiZmFhNTcxZjljYTQ3YzY1Nzk3NDA3Y2YyOTkyZQ==
2
+ SHA1:
3
+ metadata.gz: 9cc94a9dc63702c1d2b3c8cbfb61fb4df4c0184c
4
+ data.tar.gz: a17c6451c968d63a195d242c95633aa9a10430d2
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MjY2MmFlYmQ2MzhlMzBhOWM0MTE0ZWQ1N2ZmZDI4MmVhMzkxMzA5Nzg0NmY4
10
- MzM1YjJmNzNiNzQ0YWU4MTY4ZDcxNTkzNjMzZTdjMjY5ZTdiNDY4ODJlYjdh
11
- YWRhOWZmNTY0NTBmMDhiMTIyNjk4ZTU4M2ZmODI2NjMwM2ZhZDM=
12
- data.tar.gz: !binary |-
13
- ZmRmZGI3NjFiODYzOGU1NDNjMGUwMTQ1NTkxODUzNGYwZmYzNzQxZWY0ZTY2
14
- NjA4NjZmMjQxYTY5ZGJkNzQwOWYyMGYxN2UxNmVhYzgzYzQ5MzI4ZTZlNTA3
15
- YTZhNTUyYWUwZjAwODE4YzBiZThkM2M3NWI1NWNkODg4YjAxMzk=
6
+ metadata.gz: 72d2b1d0693b01fe09d794b3cfc25f3316ff732e2df92fcfe5316645a5f6063c8c1e8fadae7b2827050297295d4c2c82415d16ce60c33b0a7fac56656ae179e8
7
+ data.tar.gz: 707019d7e8a43204dea773430eada124306bda384fcff69664b393ac4db9372379cfa11fc1cc61874bcc4e0436c1321d2539d29ab445670a0a75b43c594c102b
data/README.md CHANGED
@@ -91,11 +91,13 @@ Converters have two interrelated responsibilities:
91
91
  - Parse data, like the string `"3,000"`, into an object, `like 3_000`.
92
92
  - Serialize data, like integer `3_000`, into string `"3,000"`
93
93
 
94
- A converter is simply an object that responds to `#parse(s)` and `#raw(v)` methods.
94
+ A converter is simply an object that responds to `#parse(s)`, `#raw(v)`, and `#opts` methods.
95
95
 
96
96
  When `#parse(s)` raises a StandardError exception, or any of its descendants, the exception is
97
97
  rescued and a Foraneus::Error instance is added to `Foraneus#errors` map.
98
98
 
99
+ `#opts` should return the opts hash used to instantiate the converter.
100
+
99
101
  Built-in converters:
100
102
 
101
103
  - Boolean
@@ -8,6 +8,12 @@ class Foraneus
8
8
  # When converting to a raw value, a true value => 'true', a false value => 'false'.
9
9
  class Boolean
10
10
 
11
+ attr_reader :opts
12
+
13
+ def initialize(opts = {})
14
+ @opts = opts
15
+ end
16
+
11
17
  # @return [Boolean]
12
18
  def parse(s)
13
19
  if s == 'true'
@@ -7,9 +7,12 @@ class Foraneus
7
7
 
8
8
  DEFAULT_FORMAT = '%Y-%m-%d'
9
9
 
10
+ attr_reader :opts
11
+
10
12
  # @param [Hash] opts
11
13
  # @option opts [String] format Date format.
12
14
  def initialize(opts = {})
15
+ @opts = opts
13
16
  @format = opts[:format] || DEFAULT_FORMAT
14
17
  end
15
18
 
@@ -1,34 +1,14 @@
1
1
  require 'bigdecimal'
2
+ require 'foraneus/converters/float'
2
3
 
3
4
  class Foraneus
4
5
  module Converters
5
6
 
6
- class Decimal
7
- DEFAULT_SEPARATOR = '.'
8
-
9
- DELIMITED_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
10
-
11
- # @param [Hash] opts
12
- # @option opts [String] delimiter Thousands delimiter.
13
- # @option opts [String] separator Decimal separator.
14
- # @option opts [Integer] precision Minimum precision.
15
- def initialize(opts = {})
16
- @delimiter = opts[:delimiter]
17
- @precision = opts[:precision]
18
- @separator = opts[:separator] || DEFAULT_SEPARATOR
19
- end
7
+ class Decimal < Foraneus::Converters::Float
20
8
 
21
9
  # @return [BigDecimal]
22
10
  def parse(s)
23
- parts = s.split(@separator)
24
-
25
- integer_part = (parts[0] || '0')
26
-
27
- if @delimiter
28
- integer_part.gsub!(@delimiter, '')
29
- end
30
-
31
- fractional_part = parts[1] || '0'
11
+ integer_part, fractional_part = split(s)
32
12
 
33
13
  BigDecimal.new("#{integer_part}.#{fractional_part}")
34
14
  end
@@ -36,15 +16,7 @@ class Foraneus
36
16
  def raw(v)
37
17
  left, right = v.to_s('F').split('.')
38
18
 
39
- if @precision && right.length < @precision
40
- right = add_trailing_zeros(right, @precision - right.length)
41
- end
42
-
43
- if @delimiter
44
- left.gsub!(DELIMITED_REGEX) { "#{$1}#{@delimiter}" }
45
- end
46
-
47
- "#{left}#{@separator}#{right}"
19
+ join(left, right)
48
20
  end
49
21
 
50
22
  private
@@ -7,11 +7,15 @@ class Foraneus
7
7
 
8
8
  DELIMITED_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
9
9
 
10
+ attr_reader :opts
11
+
10
12
  # @param [Hash] opts
11
13
  # @option opts [String] delimiter Thousands delimiter.
12
14
  # @option opts [String] separator Decimal separator.
13
15
  # @option opts [Integer] precision Minimum precision.
14
16
  def initialize(opts = {})
17
+ @opts = opts
18
+
15
19
  @delimiter = opts[:delimiter]
16
20
  @precision = opts[:precision]
17
21
  @separator = opts[:separator] || DEFAULT_SEPARATOR
@@ -19,19 +23,7 @@ class Foraneus
19
23
 
20
24
  # @return [Float]
21
25
  def parse(s)
22
- if s == ''
23
- raise ArgumentError, 'invalid value for Float(): ""'
24
- end
25
-
26
- parts = s.split(@separator)
27
-
28
- integer_part = parts[0] || '0'
29
-
30
- if @delimiter
31
- integer_part.gsub!(@delimiter, '')
32
- end
33
-
34
- fractional_part = parts[1] || '0'
26
+ integer_part, fractional_part = split(s)
35
27
 
36
28
  Kernel.Float("#{integer_part}.#{fractional_part}")
37
29
  end
@@ -39,6 +31,19 @@ class Foraneus
39
31
  def raw(v)
40
32
  left, right = v.to_s.split('.')
41
33
 
34
+ join(left, right)
35
+ end
36
+
37
+ protected
38
+ # Joins both integer and fractional parts.
39
+ #
40
+ # It adds trailing zeros according to the current precision.
41
+ #
42
+ # @param [Integer] left Integer part
43
+ # @param [Integer] right Fractional part
44
+ #
45
+ # @return [String]
46
+ def join(left, right)
42
47
  if @precision && right.length < @precision
43
48
  right = add_trailing_zeros(right, @precision - right.length)
44
49
  end
@@ -50,6 +55,25 @@ class Foraneus
50
55
  "#{left}#{@separator}#{right}"
51
56
  end
52
57
 
58
+ # Splits a float representation into its integer and fractional parts.
59
+ #
60
+ # @param [String] s
61
+ #
62
+ # @return [Array [integer_part, fractional_part] ]
63
+ def split(s)
64
+ parts = s.split(@separator)
65
+
66
+ integer_part = parts[0] || '0'
67
+
68
+ if @delimiter
69
+ integer_part.gsub!(@delimiter, '')
70
+ end
71
+
72
+ fractional_part = parts[1] || '0'
73
+
74
+ [integer_part, fractional_part]
75
+ end
76
+
53
77
  private
54
78
  def add_trailing_zeros(s, n)
55
79
  zeros = '0' * n
@@ -4,9 +4,12 @@ class Foraneus
4
4
  class Integer
5
5
  DELIMITED_REGEX = /(\d)(?=(\d\d\d)+(?!\d))/
6
6
 
7
+ attr_reader :opts
8
+
7
9
  # @param [Hash] opts
8
10
  # @option opts [String] delimiter Thousands delimiter.
9
11
  def initialize(opts = {})
12
+ @opts = opts
10
13
  @delimiter = opts[:delimiter]
11
14
  end
12
15
 
@@ -6,6 +6,12 @@ class Foraneus
6
6
  # It does not perform any conversion at all. Useful when its needed to have a field but
7
7
  # conversion is handled at another level.
8
8
  class Noop
9
+ attr_reader :opts
10
+
11
+ def initialize(opts = {})
12
+ @opts = opts
13
+ end
14
+
9
15
  # @return [Object]
10
16
  def parse(o)
11
17
  o
@@ -3,6 +3,12 @@ class Foraneus
3
3
 
4
4
  class String
5
5
 
6
+ attr_reader :opts
7
+
8
+ def initialize(opts = {})
9
+ @opts = opts
10
+ end
11
+
6
12
  # @return [String]
7
13
  def parse(s)
8
14
  s.to_s
data/lib/foraneus.rb CHANGED
@@ -186,11 +186,15 @@ class Foraneus
186
186
  field = k.to_s
187
187
  converter = fields[field]
188
188
 
189
- return unless converter
190
-
191
189
  foraneus[k] = v
192
190
 
193
- unless v.nil?
191
+ return unless converter
192
+
193
+ if (v.nil? || v == '') && converter.opts[:required]
194
+ raise KeyError, "required parameter not found: #{field.inspect}"
195
+ elsif v.nil? || v == ''
196
+ v = nil
197
+ else
194
198
  v = converter.parse(v)
195
199
  end
196
200
 
@@ -66,22 +66,6 @@ describe Foraneus::Converters::Float do
66
66
  }.to raise_error
67
67
  end
68
68
  end
69
-
70
- context 'with empty values' do
71
- it 'raises an error' do
72
- expect {
73
- subject.parse('')
74
- }.to raise_error
75
- end
76
- end
77
-
78
- context 'with nil values' do
79
- it 'raises an error' do
80
- expect {
81
- subject.parse(nil)
82
- }.to raise_error
83
- end
84
- end
85
69
  end
86
70
 
87
71
  describe '#raw' do
@@ -16,9 +16,11 @@ describe Foraneus do
16
16
 
17
17
  its(:delay) { should eq(5) }
18
18
 
19
+ its(:data) { should include(:delay => 5) }
20
+
19
21
  its([:delay]) { should eq('5') }
20
22
 
21
- its(:data) { should include(:delay => 5) }
23
+ its(['delay']) { should be_nil }
22
24
 
23
25
  its([]) { should include(:delay => '5') }
24
26
 
@@ -37,18 +39,6 @@ describe Foraneus do
37
39
 
38
40
  its([]) { should include('delay' => '5') }
39
41
  end
40
-
41
- context 'with nil values' do
42
- subject(:form) { form_spec.parse('delay' => nil) }
43
-
44
- its(['delay']) { should eq(nil) }
45
-
46
- its([:delay]) { should eq(nil) }
47
-
48
- its(:data) { should include('delay' => nil) }
49
-
50
- its([]) { should include('delay' => nil) }
51
- end
52
42
  end
53
43
 
54
44
  context 'with non parseable data' do
@@ -80,6 +70,68 @@ describe Foraneus do
80
70
  its(:message) { should eq(converter_exception.message) }
81
71
  end
82
72
  end
73
+
74
+ context 'with unexpected data' do
75
+ subject(:form) { form_spec.parse(:position => 'north') }
76
+
77
+ it 'does not have a getter for the received param' do
78
+ expect {
79
+ form.position
80
+ }.to raise_error(NoMethodError)
81
+ end
82
+
83
+ its(:data) { should_not include(:position) }
84
+
85
+ its([:position]) { should eq('north') }
86
+
87
+ its([]) { should include(:position => 'north') }
88
+
89
+ it { should be_valid }
90
+ end
91
+
92
+ shared_examples 'an absent parameters handler' do |missing_value|
93
+ subject(:form) { form_spec.parse(:delay => missing_value) }
94
+
95
+ it { should be_valid }
96
+
97
+ its(:delay) { should be_nil }
98
+
99
+ its(:data) { should include(:delay => nil) }
100
+
101
+ its([:delay]) { should eq(missing_value) }
102
+
103
+ its([]) { should include(:delay => missing_value) }
104
+
105
+ context 'when required field' do
106
+ let(:converter) { Foraneus::Converters::Integer.new(:required => true) }
107
+
108
+ it { should_not be_valid }
109
+
110
+ its(:delay) { should be_nil }
111
+
112
+ its(:data) { should_not include(:delay) }
113
+
114
+ its([:delay]) { should eq(missing_value) }
115
+
116
+ its([]) { should include(:delay => missing_value) }
117
+
118
+ its([:errors]) { should include(:delay) }
119
+
120
+ describe 'an error' do
121
+ subject(:error) { form[:errors].values.first }
122
+
123
+ its(:key) { should eq('KeyError') }
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'with nil values' do
129
+ it_behaves_like 'an absent parameters handler', nil
130
+ end
131
+
132
+ context 'with empty values' do
133
+ it_behaves_like 'an absent parameters handler', ''
134
+ end
83
135
  end
84
136
 
85
137
  describe '.raw' do
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foraneus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gianfranco Zas
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-15 00:00:00.000000000 Z
11
+ date: 2014-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
15
- requirement: !ruby/object:Gem::Requirement
15
+ version_requirements: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: 2.14.0
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
20
+ requirement: !ruby/object:Gem::Requirement
23
21
  requirements:
24
22
  - - ~>
25
23
  - !ruby/object:Gem::Version
26
24
  version: 2.14.0
25
+ prerelease: false
26
+ type: :development
27
27
  - !ruby/object:Gem::Dependency
28
- name: redcarpet
29
- requirement: !ruby/object:Gem::Requirement
28
+ name: yard-kramdown
29
+ version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
34
+ requirement: !ruby/object:Gem::Requirement
37
35
  requirements:
38
- - - ! '>='
36
+ - - '>='
39
37
  - !ruby/object:Gem::Version
40
38
  version: '0'
39
+ prerelease: false
40
+ type: :development
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: yard
43
- requirement: !ruby/object:Gem::Requirement
43
+ version_requirements: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
51
49
  requirements:
52
- - - ! '>='
50
+ - - '>='
53
51
  - !ruby/object:Gem::Version
54
52
  version: '0'
53
+ prerelease: false
54
+ type: :development
55
55
  description: Provides two way transformation mechanisms to external data.
56
56
  email: snmgian@gmail.com
57
57
  executables: []
@@ -70,6 +70,7 @@ files:
70
70
  - COPYING
71
71
  - COPYING.LESSER
72
72
  - README.md
73
+ - spec/spec_helper.rb
73
74
  - spec/lib/foraneus_spec.rb
74
75
  - spec/lib/foraneus/converters/noop_converter_spec.rb
75
76
  - spec/lib/foraneus/converters/decimal_converter_spec.rb
@@ -78,32 +79,32 @@ files:
78
79
  - spec/lib/foraneus/converters/string_converter_spec.rb
79
80
  - spec/lib/foraneus/converters/float_converter_spec.rb
80
81
  - spec/lib/foraneus/converters/boolean_converter_spec.rb
81
- - spec/spec_helper.rb
82
82
  homepage: https://github.com/snmgian/foraneus
83
83
  licenses:
84
84
  - LGPL
85
85
  metadata: {}
86
- post_install_message:
86
+ post_install_message:
87
87
  rdoc_options: []
88
88
  require_paths:
89
89
  - lib
90
90
  required_ruby_version: !ruby/object:Gem::Requirement
91
91
  requirements:
92
- - - ! '>='
92
+ - - '>='
93
93
  - !ruby/object:Gem::Version
94
94
  version: '0'
95
95
  required_rubygems_version: !ruby/object:Gem::Requirement
96
96
  requirements:
97
- - - ! '>='
97
+ - - '>='
98
98
  - !ruby/object:Gem::Version
99
99
  version: '0'
100
100
  requirements: []
101
- rubyforge_project:
102
- rubygems_version: 2.1.5
103
- signing_key:
101
+ rubyforge_project:
102
+ rubygems_version: 2.1.9
103
+ signing_key:
104
104
  specification_version: 4
105
105
  summary: Transforms external data.
106
106
  test_files:
107
+ - spec/spec_helper.rb
107
108
  - spec/lib/foraneus_spec.rb
108
109
  - spec/lib/foraneus/converters/noop_converter_spec.rb
109
110
  - spec/lib/foraneus/converters/decimal_converter_spec.rb
@@ -112,5 +113,4 @@ test_files:
112
113
  - spec/lib/foraneus/converters/string_converter_spec.rb
113
114
  - spec/lib/foraneus/converters/float_converter_spec.rb
114
115
  - spec/lib/foraneus/converters/boolean_converter_spec.rb
115
- - spec/spec_helper.rb
116
- has_rdoc:
116
+ has_rdoc: