foraneus 0.0.12 → 0.0.13

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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5dd151153010e57f4108ce2e054238b10b2d0b46
4
- data.tar.gz: b582478fbb77f95ef5f924b1e7ae2b5bb492c15b
3
+ metadata.gz: f3f668a304ebd112cf2651006dc871679cac85db
4
+ data.tar.gz: 607492a6bd176a001eca2f2f0971e2f6f6dca73f
5
5
  SHA512:
6
- metadata.gz: 6a0c78292a5a51eb6d59dbb6000bed04e4669b95e0b3a78b09e84a9d4c302db1a426930a141166291cab1d2b34279a5837625932655f29270e25b7c82abef74f
7
- data.tar.gz: c9385cc3522459024a4d68f148dbb08200411099b3d809e85f54d4c51d4ab99bc8a2965466f278b960d093d15e9d0fe929bd687dffd75e5c4e0f24d7a2a1135d
6
+ metadata.gz: 1954c53b5f18b2099d55a2e4c0d92dc09cb6cfca491e0db191b220a997cb8abedd580392edcb70c8ab3d80363d97b938fee4d6e99531d2fe13436b0074eb1f8c
7
+ data.tar.gz: 8689562a31c5c06aade9b290f663539f0e8f042bddb1a71638b92a70f24944f853ee48fa3458b7310cfac8dc304b0d09db019023bded19bb9d6fd694b8d415f3
data/README.md CHANGED
@@ -62,16 +62,16 @@ Declare source classes by inheriting from `Foraneus` base class.
62
62
  end
63
63
  ```
64
64
 
65
- Fields are declared in two ways:
65
+ Fields are declared by two ways:
66
66
 
67
67
  - calling `.field`
68
68
  - calling a shortcut method, like `.float`
69
69
 
70
70
 
71
- There are handy methods for any of the built-in converters: boolean, date, decimal, float, integer,
71
+ There are shortcut methods for any of the built-in converters: boolean, date, decimal, float, integer,
72
72
  noop, and string.
73
73
 
74
- When no converter is passed to `.field`, Foraneus::Converters::Noop is assigned to the declared
74
+ When no converter is passed to `.field`, `Foraneus::Converters::Noop` is assigned to the declared
75
75
  field.
76
76
 
77
77
  ## Instantiation
@@ -91,10 +91,10 @@ 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)`, `#raw(v)`, and `#opts` methods.
94
+ A converter is 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
- rescued and a Foraneus::Error instance is added to `Foraneus#errors` map.
97
+ rescued and a `Foraneus::Error` instance is added to `Foraneus#errors` map.
98
98
 
99
99
  `#opts` should return the opts hash used to instantiate the converter.
100
100
 
@@ -119,7 +119,7 @@ Valid instance:
119
119
 
120
120
  ``` ruby
121
121
  form.valid? # => true
122
- form[:errors] # => {}
122
+ form.errors # => {}
123
123
  ```
124
124
 
125
125
  Invalid one:
@@ -129,15 +129,15 @@ Invalid one:
129
129
 
130
130
  form.valid? # => false
131
131
 
132
- form[:errors][:delay].key # => 'ArgumentError'
133
- form[:errors][:delay].message # => 'invalid value for Integer(): "INVALID"'
132
+ form.errors[:delay].key # => 'ArgumentError'
133
+ form.errors[:delay].message # => 'invalid value for Integer(): "INVALID"'
134
134
  ```
135
135
 
136
136
  `#errors` is a map in which keys correspond to field names, and values are instances of
137
137
  `Foraneus::Error`.
138
138
 
139
139
  The name of the exception raised by `#parse` is the error's `key` attribute, and the exception's
140
- message is added to the error's `message` attribute.
140
+ message is set to the error's `message` attribute.
141
141
 
142
142
  Data coming from the inside is assumed to be valid, so `.raw` won't return an instance having
143
143
  errors neither being invalid.
@@ -152,15 +152,15 @@ Fields can be declared as required.
152
152
  end
153
153
  ```
154
154
 
155
- If an external value is not fed into a required field, an error with key 'KeyError' will be assigned.
155
+ If an external value is not fed into a required field, an error with key `KeyError` will be assigned.
156
156
 
157
157
  ``` ruby
158
158
  form = MyForm.parse
159
159
 
160
160
  form.valid? # => false
161
161
 
162
- form[:errors][:delay].key # => 'KeyError'
163
- form[:errors][:delay].message # => 'required parameter not found: "delay"'
162
+ form.errors[:delay].key # => 'KeyError'
163
+ form.errors[:delay].message # => 'required parameter not found: "delay"'
164
164
  ```
165
165
 
166
166
  ## Blank values
@@ -197,7 +197,8 @@ Parse data from the ouside:
197
197
  form = MyForm.parse
198
198
 
199
199
  form.name # => 'Alice'
200
- form[:name] # => nil, data from the outside don't include any value
200
+ form[:name] # => nil, because data from the outside
201
+ # don't include any value
201
202
  ```
202
203
 
203
204
  Convert values back from the inside:
@@ -206,7 +207,32 @@ Convert values back from the inside:
206
207
  form = MyForm.raw
207
208
 
208
209
  form[:name] # => 'Alice'
209
- form.name # => nil, data from the inside don't include any value
210
+ form.name # => nil, because data from the inside
211
+ # don't include any value
212
+ ```
213
+
214
+ ## Prevent name clashes
215
+
216
+ It is possible to rename methods `#errors` and `#data` so it will not conflict with defined fields.
217
+
218
+ ``` ruby
219
+ MyForm = Class.new(Foraneus) {
220
+ field :errors
221
+ field :data
222
+
223
+ accessors[:errors] = :non_clashing_errors
224
+ accessors[:data] = :non_clashing_data
225
+ }
226
+ ```
227
+
228
+ ``` ruby
229
+ form = MyForm.parse(:errors => 'some errors', :data => 'some data')
230
+
231
+ form.errors # => 'some errors'
232
+ form.data # => 'some data'
233
+
234
+ form.non_clashing_errors # []
235
+ form.non_clashing_data # { :errors => 'some errors', :data => 'some data' }
210
236
  ```
211
237
 
212
238
  ## Installation
@@ -219,10 +245,16 @@ Convert values back from the inside:
219
245
 
220
246
  ## Running tests
221
247
 
222
- Tests are written in RSpec. To run them all just execute the following from your command line:
248
+ Tests are written in MiniTest. To run them all just execute the following from your command line:
249
+
250
+ ``` shell
251
+ ruby spec/runner.rb
252
+ ```
253
+
254
+ To run a specific test case:
223
255
 
224
256
  ``` shell
225
- rspec
257
+ ruby -Ispec -Ilib spec/lib/foraneus_spec.rb
226
258
  ```
227
259
 
228
260
  ## Code documentation
@@ -11,15 +11,9 @@ require_relative 'foraneus/errors'
11
11
  class Foraneus
12
12
 
13
13
 
14
- # @return [Hash] Parsed data.
15
- attr_accessor :data
16
-
17
14
  # @api private
18
15
  def initialize
19
- @data = {}
20
- @raw_data = {}
21
-
22
- @errors = {}
16
+ @_ = {}
23
17
  end
24
18
 
25
19
  # Declares a boolean field.
@@ -102,13 +96,38 @@ class Foraneus
102
96
  @fields ||= {}
103
97
  end
104
98
 
99
+ def self.accessors
100
+ @accessors ||= {
101
+ :data => :data,
102
+ :errors => :errors
103
+ }
104
+ end
105
+
106
+ def self.create_instance
107
+ instance = self.new
108
+ spec = self
109
+
110
+ instance.singleton_class.send(:attr_reader, self.accessors[:data])
111
+
112
+ instance.instance_exec do
113
+ instance.instance_variable_set(:"@#{spec.accessors[:data]}", {})
114
+ end
115
+
116
+ instance.singleton_class.send(:attr_reader, self.accessors[:errors])
117
+ instance.instance_exec do
118
+ instance.instance_variable_set(:"@#{spec.accessors[:errors]}", {})
119
+ end
120
+
121
+ instance
122
+ end
123
+
105
124
  # Parses data coming from an external source.
106
125
  #
107
126
  # @param [Hash<Symbol, String>] data External data.
108
127
  #
109
128
  # @return [Foraneus] An instance of a form.
110
129
  def self.parse(data = {})
111
- instance = self.new
130
+ instance = self.create_instance
112
131
 
113
132
  parsed_keys = []
114
133
 
@@ -138,7 +157,7 @@ class Foraneus
138
157
  #
139
158
  # @return [Foraneus] An instance of a form.
140
159
  def self.raw(data = {})
141
- instance = self.new
160
+ instance = self.create_instance
142
161
 
143
162
  fields.each do |field, converter|
144
163
  given_key = field
@@ -161,7 +180,7 @@ class Foraneus
161
180
  end
162
181
 
163
182
  instance[given_key] = s
164
- instance.data[given_key] = v
183
+ instance.send(self.accessors[:data])[given_key] = v
165
184
  end
166
185
 
167
186
  instance
@@ -171,13 +190,11 @@ class Foraneus
171
190
  # @return [Array<Error>] errors when m == :errors.
172
191
  # @return [String] raw data value for the field m.
173
192
  def [](m = nil)
174
- if m == :errors
175
- @errors
176
- elsif m.nil?
177
- @raw_data
193
+ if m.nil?
194
+ @_
178
195
  else
179
- @raw_data.fetch(m) do
180
- @raw_data[m.to_s]
196
+ @_.fetch(m) do
197
+ @_[m.to_s]
181
198
  end
182
199
  end
183
200
  end
@@ -189,7 +206,10 @@ class Foraneus
189
206
  # @param [Symbol] k Field name.
190
207
  # @param [String] v Raw value.
191
208
  def []=(k, v)
192
- @raw_data[k] = v
209
+ #raw_data = @_
210
+
211
+ #raw_data[k] = v
212
+ @_[k] = v
193
213
  end
194
214
 
195
215
  # Returns true if no conversion errors occurred. false otherwise.
@@ -225,11 +245,11 @@ class Foraneus
225
245
  end
226
246
 
227
247
  foraneus.send("#{field}=", v)
228
- foraneus.data[k] = v
248
+ foraneus.send(self.accessors[:data])[k] = v
229
249
 
230
250
  rescue
231
251
  error = Foraneus::Error.new($!.class.name, $!.message)
232
- foraneus.instance_variable_get(:@errors)[k] = error
252
+ foraneus.send(self.accessors[:errors])[k] = error
233
253
  end
234
254
  private_class_method :__parse_raw_datum
235
255
 
@@ -16,7 +16,10 @@ class Foraneus
16
16
  @format = opts[:format] || DEFAULT_FORMAT
17
17
  end
18
18
 
19
- # return [Date]
19
+
20
+ # @raise [ArgumentError] with message 'invalid date'
21
+ #
22
+ # @return [Date]
20
23
  def parse(s)
21
24
  ::Date.strptime(s, @format)
22
25
  end
@@ -21,6 +21,8 @@ class Foraneus
21
21
  @separator = opts[:separator] || DEFAULT_SEPARATOR
22
22
  end
23
23
 
24
+ # @raise [ArgumentError] with message 'invalid value for Float(): ...'
25
+ #
24
26
  # @return [Float]
25
27
  def parse(s)
26
28
  integer_part, fractional_part = split(s)
@@ -13,6 +13,8 @@ class Foraneus
13
13
  @delimiter = opts[:delimiter]
14
14
  end
15
15
 
16
+ # @raise [ArgumentError] with message 'invalid value for Integer(): ...'
17
+ #
16
18
  # @return [Integer]
17
19
  def parse(s)
18
20
  s = s.gsub(@delimiter, '') if @delimiter
@@ -2,35 +2,37 @@ require 'spec_helper'
2
2
 
3
3
  describe Foraneus::Converters::Boolean do
4
4
 
5
+ let(:converter) { Foraneus::Converters::Boolean.new }
6
+
5
7
  describe '#parse' do
6
8
  it 'returns true with true' do
7
- parsed = subject.parse('true')
9
+ parsed = converter.parse('true')
8
10
 
9
- parsed.should be_true
11
+ assert_equal true, parsed
10
12
  end
11
13
 
12
14
  it 'returns false with sth else' do
13
- parsed = subject.parse('false')
15
+ parsed = converter.parse('false')
14
16
 
15
- parsed.should be_false
17
+ assert_equal false, parsed
16
18
  end
17
19
  end
18
20
 
19
21
  describe '#raw' do
20
22
  it 'returns "true" with true' do
21
- subject.raw(true).should eq('true')
23
+ assert_equal 'true', converter.raw(true)
22
24
  end
23
25
 
24
26
  it 'returns "false" with false' do
25
- subject.raw(false).should eq('false')
27
+ assert_equal 'false', converter.raw(false)
26
28
  end
27
29
 
28
30
  it 'returns "false" with nil' do
29
- subject.raw(nil).should eq('false')
31
+ assert_equal 'false', converter.raw(nil)
30
32
  end
31
33
 
32
34
  it 'returns "true" with everything else' do
33
- subject.raw(:default).should eq('true')
35
+ assert_equal 'true', converter.raw(:default)
34
36
  end
35
37
  end
36
38
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Foraneus::Converters::Date do
4
4
 
5
- subject(:converter) { Foraneus::Converters::Date.new }
5
+ let(:converter) { Foraneus::Converters::Date.new }
6
6
 
7
7
  describe '#parse' do
8
8
 
@@ -11,13 +11,13 @@ describe Foraneus::Converters::Date do
11
11
 
12
12
  result = converter.parse(s)
13
13
 
14
- result.year.should eq(2012)
15
- result.month.should eq(04)
16
- result.day.should eq(13)
14
+ assert_equal 2012, result.year
15
+ assert_equal 4, result.month
16
+ assert_equal 13, result.day
17
17
  end
18
18
 
19
- context 'when format is given' do
20
- subject(:converter) {
19
+ describe 'when format is given' do
20
+ let(:converter) {
21
21
  Foraneus::Converters::Date.new(:format => '%d/%m/%Y')
22
22
  }
23
23
 
@@ -26,32 +26,28 @@ describe Foraneus::Converters::Date do
26
26
 
27
27
  result = converter.parse(s)
28
28
 
29
- result.year.should eq(2012)
30
- result.month.should eq(04)
31
- result.day.should eq(13)
29
+ assert_equal 2012, result.year
30
+ assert_equal 4, result.month
31
+ assert_equal 13, result.day
32
32
  end
33
33
  end
34
34
  end
35
35
 
36
36
  describe '#raw' do
37
- let(:d) { Date.today }
37
+ let(:d) { Date.new(2012, 4, 13) }
38
38
 
39
39
  it 'returns a date representation' do
40
- s = d.strftime('%Y-%m-%d')
41
-
42
- converter.raw(d).should eq(s)
40
+ assert_equal '2012-04-13', converter.raw(d)
43
41
  end
44
42
 
45
- context 'when format is given' do
43
+ describe 'when format is given' do
46
44
  let(:format) { '%m/%d/%Y' }
47
- subject(:converter) {
45
+ let(:converter) {
48
46
  Foraneus::Converters::Date.new(:format => format)
49
47
  }
50
48
 
51
49
  it 'returns a date representation' do
52
- s = d.strftime(format)
53
-
54
- converter.raw(d).should eq(s)
50
+ assert_equal '04/13/2012', converter.raw(d)
55
51
  end
56
52
  end
57
53
  end
@@ -2,25 +2,25 @@ require 'spec_helper'
2
2
 
3
3
  describe Foraneus::Converters::Decimal do
4
4
 
5
- subject(:converter) { Foraneus::Converters::Decimal.new }
5
+ let(:converter) { Foraneus::Converters::Decimal.new }
6
6
 
7
7
  describe '#parse' do
8
8
  it 'parses a decimal representation' do
9
9
  s = '1234.56'
10
10
  n = BigDecimal.new('1234.56')
11
11
 
12
- converter.parse(s).should eq(n)
12
+ assert_equal n, converter.parse(s)
13
13
  end
14
14
 
15
15
  it 'parses a decimal representation when no integer part' do
16
16
  s = '.56'
17
17
  n = BigDecimal.new('0.56')
18
18
 
19
- converter.parse(s).should eq(n)
19
+ assert_equal n, converter.parse(s)
20
20
  end
21
21
 
22
- context 'when separator and delimiter are given' do
23
- subject(:converter) {
22
+ describe 'when separator and delimiter are given' do
23
+ let(:converter) {
24
24
  Foraneus::Converters::Decimal.new(:delimiter => '.', :separator => ',')
25
25
  }
26
26
 
@@ -28,14 +28,14 @@ describe Foraneus::Converters::Decimal do
28
28
  s = '1.234.567,89'
29
29
  n = BigDecimal.new('1234567.89')
30
30
 
31
- converter.parse(s).should eq(n)
31
+ assert_equal n, converter.parse(s)
32
32
  end
33
33
 
34
34
  it 'parses a decimal representation when no integer part' do
35
35
  s = ',56'
36
36
  n = BigDecimal.new('0.56')
37
37
 
38
- converter.parse(s).should eq(n)
38
+ assert_equal n, converter.parse(s)
39
39
  end
40
40
  end
41
41
  end
@@ -46,39 +46,39 @@ describe Foraneus::Converters::Decimal do
46
46
  it 'returns a decimal representation' do
47
47
  s = '1234567.89'
48
48
 
49
- converter.raw(n).should eq(s)
49
+ assert_equal s, converter.raw(n)
50
50
  end
51
51
 
52
- context 'when separator and delimiter are given' do
53
- subject(:converter) {
52
+ describe 'when separator and delimiter are given' do
53
+ let(:converter) {
54
54
  Foraneus::Converters::Decimal.new(:delimiter => '.', :separator => ',')
55
55
  }
56
56
 
57
57
  it 'returns a decimal representation' do
58
58
  s = '1.234.567,89'
59
59
 
60
- converter.raw(n).should eq(s)
60
+ assert_equal s, converter.raw(n)
61
61
  end
62
62
  end
63
63
 
64
- context 'when precision is given' do
65
- subject(:converter) {
64
+ describe 'when precision is given' do
65
+ let(:converter) {
66
66
  Foraneus::Converters::Decimal.new(:precision => 2)
67
67
  }
68
68
 
69
69
  it 'fills with zeros when value precision is smaller than converter precision' do
70
70
  n = BigDecimal.new('3.1')
71
- converter.raw(n).should eq('3.10')
71
+ assert_equal '3.10', converter.raw(n)
72
72
  end
73
73
 
74
74
  it 'does not affect the representation when precision and converter precision are both equal' do
75
75
  n = BigDecimal.new('3.14')
76
- converter.raw(n).should eq('3.14')
76
+ assert_equal '3.14', converter.raw(n)
77
77
  end
78
78
 
79
79
  it 'does not truncate the representation when precision is larger than converter precision' do
80
80
  n = BigDecimal.new('3.145')
81
- converter.raw(n).should eq('3.145')
81
+ assert_equal '3.145', converter.raw(n)
82
82
  end
83
83
  end
84
84
  end