pikelet 1.1.2 → 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -34
- data/lib/pikelet/field_definition.rb +26 -5
- data/lib/pikelet/file_definition.rb +14 -0
- data/lib/pikelet/record_definition.rb +11 -0
- data/lib/pikelet/version.rb +1 -1
- data/spec/pikelet/field_definition_spec.rb +102 -53
- data/spec/pikelet/record_definition_spec.rb +12 -4
- data/spec/pikelet_spec.rb +145 -130
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 580f25b1ccc1b345208d99f759cbca4d42e86933
|
4
|
+
data.tar.gz: 6e333e33e68c71825143a2b393c0376f20f35c5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd176128b19db2521917463563b00e5e6ca4caefd8086be747ae24b6ee36f80273690e33fcbe36879cfc9e9afd327dd4e65415d35554cf420fa234b7f9cd8166
|
7
|
+
data.tar.gz: 6ad11890c1fb69fc6c3641faeba9183b71a13153a350466df873ba37a12abbd27c46866a651198d0d41e28061c47d111a9e1b4035c90619ba526eaf9dd1a3ff9
|
data/README.md
CHANGED
@@ -4,6 +4,16 @@
|
|
4
4
|
[![Build status][build-badge]][build]
|
5
5
|
[![Coverage Status][coverage-badge]][coverage]
|
6
6
|
|
7
|
+
## Beta notes
|
8
|
+
|
9
|
+
The next release of Pikelet will be capable of formatting flat-file databases
|
10
|
+
for output. As part of this I will be dropping CSV support as it is
|
11
|
+
constraining my options and, as far as I know, nobody is using it. For the
|
12
|
+
time being I want to let it evolve as a pure flat-file database parser. In a
|
13
|
+
future release I may restore CSV support, but I make no promises.
|
14
|
+
|
15
|
+
## Introduction
|
16
|
+
|
7
17
|
A [pikelet][pikelet-recipe] is a small, delicious pancake popular in Australia
|
8
18
|
and New Zealand. Also, the stage name of Australian musician
|
9
19
|
[Evelyn Morris][pikelet-musician]. Also, a simple flat-file database parser
|
@@ -17,8 +27,7 @@ record types. Each record type has a different structure, though some types
|
|
17
27
|
share common fields, and all types have a type signature.
|
18
28
|
|
19
29
|
However, Pikelet will also handle more typical flat-file databases comprised
|
20
|
-
of homogeneous records.
|
21
|
-
files as it will with fixed-width records.
|
30
|
+
of homogeneous records.
|
22
31
|
|
23
32
|
## Installation
|
24
33
|
|
@@ -124,38 +133,6 @@ When we parse the data, we end up with this:
|
|
124
133
|
postal_code="45678Y",
|
125
134
|
state="Someplace">
|
126
135
|
|
127
|
-
### Handling CSV files
|
128
|
-
|
129
|
-
What happens if we were given the data in the previous example in CSV form?
|
130
|
-
|
131
|
-
NAME,Nicolaus,Copernicus
|
132
|
-
ADDR,123 South Street,Nowhereville,45678Y,Someplace
|
133
|
-
|
134
|
-
In this case instead of describing fields with a boundary range, we just
|
135
|
-
give it a simple (zero-based) index, like so:
|
136
|
-
|
137
|
-
Pikelet.define do
|
138
|
-
type_signature 0
|
139
|
-
|
140
|
-
record "NAME" do
|
141
|
-
first_name 1
|
142
|
-
last_name 2
|
143
|
-
end
|
144
|
-
|
145
|
-
record "ADDR" do
|
146
|
-
street_address 1
|
147
|
-
city 2
|
148
|
-
postal_code 3
|
149
|
-
state 4
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
This yields the same results as above.
|
154
|
-
|
155
|
-
Note that this ability to handle CSV was not planned - it just sprang
|
156
|
-
fully-formed from the implementation. One of those pleasant little surprises
|
157
|
-
that happens sometimes. If only I had a use for it.
|
158
|
-
|
159
136
|
### Inheritance
|
160
137
|
|
161
138
|
Now we go back to our original example, starting with a simple list of names,
|
@@ -1,17 +1,38 @@
|
|
1
1
|
module Pikelet
|
2
2
|
class FieldDefinition
|
3
|
-
attr_reader :index, :parser
|
3
|
+
attr_reader :index, :parser, :width
|
4
4
|
|
5
|
-
def initialize(index, parse: nil, &
|
5
|
+
def initialize(index, parse: nil, &block)
|
6
|
+
raise ArgumentError, "index must be a range" unless index.is_a? Range
|
6
7
|
@index = index
|
7
|
-
@
|
8
|
+
@width = index.size
|
9
|
+
@parser = parse || block || :strip
|
8
10
|
@parser = @parser.to_proc unless @parser.respond_to? :call
|
9
11
|
end
|
10
12
|
|
11
|
-
def parse(
|
12
|
-
if value =
|
13
|
+
def parse(record)
|
14
|
+
if value = record[index]
|
13
15
|
parser.call(value)
|
14
16
|
end
|
15
17
|
end
|
18
|
+
|
19
|
+
def format(value)
|
20
|
+
pad(truncate(value))
|
21
|
+
end
|
22
|
+
|
23
|
+
def insert(value, record)
|
24
|
+
record[index] = format(value)
|
25
|
+
record
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def truncate(value)
|
31
|
+
value.to_s[0...width]
|
32
|
+
end
|
33
|
+
|
34
|
+
def pad(value)
|
35
|
+
(" " * (width - value.size)) + value
|
36
|
+
end
|
16
37
|
end
|
17
38
|
end
|
@@ -23,8 +23,22 @@ module Pikelet
|
|
23
23
|
parse_records(hashes, method: :parse_hash, &block)
|
24
24
|
end
|
25
25
|
|
26
|
+
def format(records)
|
27
|
+
records.map { |record| format_record(record, width: width) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def width
|
31
|
+
record_definitions.values.map(&:width).max
|
32
|
+
end
|
33
|
+
|
26
34
|
private
|
27
35
|
|
36
|
+
def format_record(record, width:)
|
37
|
+
record_definition = record.respond_to?(:type_signature) && record_definitions[record.type_signature]
|
38
|
+
record_definition ||= base_record_definition
|
39
|
+
record_definition.format(record, width: width)
|
40
|
+
end
|
41
|
+
|
28
42
|
def parse_records(data, method:, &block)
|
29
43
|
records = Enumerator.new do |y|
|
30
44
|
data.each do |data|
|
@@ -22,8 +22,19 @@ module Pikelet
|
|
22
22
|
record_class.new(*hash.values_at(*field_definitions.keys))
|
23
23
|
end
|
24
24
|
|
25
|
+
def format(record, width: nil)
|
26
|
+
width ||= self.width
|
27
|
+
field_definitions.each_with_object(" " * width) do |(field_name, field_definition), result|
|
28
|
+
field_definition.insert(record.send(field_name.to_sym), result)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
25
32
|
def record_class
|
26
33
|
@record_class ||= Struct.new(*field_definitions.keys.map(&:to_sym))
|
27
34
|
end
|
35
|
+
|
36
|
+
def width
|
37
|
+
field_definitions.values.map(&:width).inject(&:+)
|
38
|
+
end
|
28
39
|
end
|
29
40
|
end
|
data/lib/pikelet/version.rb
CHANGED
@@ -3,90 +3,139 @@ require "pikelet"
|
|
3
3
|
require "csv"
|
4
4
|
|
5
5
|
describe Pikelet::FieldDefinition do
|
6
|
-
|
7
|
-
|
6
|
+
describe "#parse" do
|
7
|
+
let(:data) { "The quick brown fox" }
|
8
|
+
let(:definition) { Pikelet::FieldDefinition.new(index) }
|
8
9
|
|
9
|
-
|
10
|
+
subject(:parsed) { definition.parse(data) }
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
context "for a fixed-width field" do
|
13
|
+
let(:index) { 4...9 }
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
it "extracts the field content from the data" do
|
16
|
+
expect(parsed).to eq "quick"
|
17
|
+
end
|
16
18
|
end
|
17
|
-
end
|
18
19
|
|
19
|
-
|
20
|
-
|
20
|
+
context "given whitespace" do
|
21
|
+
let(:index) { 3...16 }
|
21
22
|
|
22
|
-
|
23
|
-
|
23
|
+
it "strips leading and trailing whitespace" do
|
24
|
+
expect(parsed).to eq "quick brown"
|
25
|
+
end
|
24
26
|
end
|
25
|
-
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
let(:index) { 2 }
|
28
|
+
context "given a custom parser" do
|
29
|
+
let(:parser) { ->(value) { value } }
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
before do
|
32
|
+
allow(parser).to receive(:call)
|
33
|
+
parsed
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
context "as a block" do
|
37
|
+
let(:index) { 4...9 }
|
38
|
+
let(:definition) { Pikelet::FieldDefinition.new(index, &parser) }
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
it "yields the value to the parser" do
|
41
|
+
expect(parser).to have_received(:call).with("quick")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "as a parse option" do
|
46
|
+
let(:index) { 10...15 }
|
47
|
+
let(:definition) { Pikelet::FieldDefinition.new(index, parse: parser) }
|
48
|
+
|
49
|
+
it "yields the value to the parser" do
|
50
|
+
expect(parser).to have_received(:call).with("brown")
|
51
|
+
end
|
52
|
+
end
|
42
53
|
end
|
43
54
|
|
44
|
-
context "
|
45
|
-
let(:
|
46
|
-
|
55
|
+
context "given a shorthand parser" do
|
56
|
+
let(:parser) { :upcase }
|
57
|
+
|
58
|
+
context "as a block" do
|
59
|
+
let(:index) { 10...15 }
|
60
|
+
let(:definition) { Pikelet::FieldDefinition.new(index, &parser) }
|
61
|
+
|
62
|
+
it "invokes the named method on the value" do
|
63
|
+
expect(parsed).to eq "BROWN"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "as a parse option" do
|
68
|
+
let(:index) { 4...9 }
|
69
|
+
let(:definition) { Pikelet::FieldDefinition.new(index, parse: parser) }
|
47
70
|
|
48
|
-
|
49
|
-
|
71
|
+
it "invokes the named method on the value" do
|
72
|
+
expect(parsed).to eq "QUICK"
|
73
|
+
end
|
50
74
|
end
|
51
75
|
end
|
52
76
|
|
53
|
-
context "
|
54
|
-
let(:index)
|
55
|
-
let(:definition) { Pikelet::FieldDefinition.new(index, parse: parser) }
|
77
|
+
context "given an index not covered in the data" do
|
78
|
+
let(:index) { 999..999 }
|
56
79
|
|
57
|
-
it "
|
58
|
-
expect(
|
80
|
+
it "parses as nil" do
|
81
|
+
expect(parsed).to be_nil
|
59
82
|
end
|
60
83
|
end
|
61
84
|
end
|
62
85
|
|
63
|
-
|
64
|
-
let(:
|
86
|
+
describe "#insert" do
|
87
|
+
let(:index) { 4...9 }
|
88
|
+
let(:record) { "The _____ brown fox" }
|
89
|
+
let(:value) { "quick" }
|
90
|
+
let(:definition) { Pikelet::FieldDefinition.new(index) }
|
65
91
|
|
66
|
-
|
67
|
-
let(:index) { 10...15 }
|
68
|
-
let(:definition) { Pikelet::FieldDefinition.new(index, &parser) }
|
92
|
+
subject(:result) { definition.insert(value, record) }
|
69
93
|
|
70
|
-
|
71
|
-
|
72
|
-
end
|
94
|
+
before do
|
95
|
+
allow(definition).to receive(:format).with(value) { value }
|
73
96
|
end
|
74
97
|
|
75
|
-
|
76
|
-
|
77
|
-
|
98
|
+
it "formats the value" do
|
99
|
+
result
|
100
|
+
expect(definition).to have_received(:format).with(value)
|
101
|
+
end
|
78
102
|
|
79
|
-
|
80
|
-
|
81
|
-
end
|
103
|
+
it "inserts the formatted value into record" do
|
104
|
+
expect(result).to eq "The quick brown fox"
|
82
105
|
end
|
83
106
|
end
|
84
107
|
|
85
|
-
|
86
|
-
let(:index) {
|
108
|
+
describe "#format" do
|
109
|
+
let(:index) { 4...9 }
|
110
|
+
|
111
|
+
subject(:formatted) { definition.format(value) }
|
112
|
+
|
113
|
+
context "with the default formatter" do
|
114
|
+
let(:definition) { Pikelet::FieldDefinition.new(index) }
|
87
115
|
|
88
|
-
|
89
|
-
|
116
|
+
context "given a value that fits the field exactly" do
|
117
|
+
let(:value) { "quick" }
|
118
|
+
|
119
|
+
it "returns the value" do
|
120
|
+
expect(formatted).to eq "quick"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "given a value larger than the field" do
|
125
|
+
let(:value) { "quickk" }
|
126
|
+
|
127
|
+
it "truncates the value" do
|
128
|
+
expect(formatted).to eq "quick"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "givem a value smaller than the field" do
|
133
|
+
let(:value) { "quik" }
|
134
|
+
|
135
|
+
it "pads the the value with spaces at the left" do
|
136
|
+
expect(formatted).to eq " quik"
|
137
|
+
end
|
138
|
+
end
|
90
139
|
end
|
91
140
|
end
|
92
141
|
end
|
@@ -5,17 +5,25 @@ describe Pikelet::RecordDefinition do
|
|
5
5
|
let(:data) { "Hello world" }
|
6
6
|
let(:definition) do
|
7
7
|
Pikelet::RecordDefiner.new(nil, base_definition: nil).define do
|
8
|
-
hello 0...5
|
9
|
-
world 6
|
8
|
+
hello 0... 5
|
9
|
+
world 6...11
|
10
10
|
end
|
11
11
|
end
|
12
|
-
let(:record) { definition.parse(data) }
|
13
12
|
|
14
13
|
describe "#parse_hash" do
|
15
|
-
let(:
|
14
|
+
let(:record) { definition.parse(data) }
|
15
|
+
let(:record_hash) { Hash[record.to_h.to_a.reverse] }
|
16
16
|
|
17
17
|
subject { definition.parse_hash(record_hash) }
|
18
18
|
|
19
19
|
it { is_expected.to eq record }
|
20
20
|
end
|
21
|
+
|
22
|
+
describe "#format" do
|
23
|
+
let(:record) { OpenStruct.new(hello: "Hello", world: "world") }
|
24
|
+
|
25
|
+
subject { definition.format(record) }
|
26
|
+
|
27
|
+
it { is_expected.to eq "Hello world" }
|
28
|
+
end
|
21
29
|
end
|
data/spec/pikelet_spec.rb
CHANGED
@@ -9,190 +9,205 @@ describe Pikelet do
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
subject { records }
|
15
|
-
|
16
|
-
describe "for a simple flat file" do
|
12
|
+
describe "#format" do
|
17
13
|
let(:definition) do
|
18
14
|
Pikelet.define do
|
19
|
-
|
20
|
-
|
15
|
+
type_signature 0...4
|
16
|
+
|
17
|
+
record "NAME" do
|
18
|
+
first_name 4...14
|
19
|
+
last_name 14...24
|
20
|
+
end
|
21
|
+
|
22
|
+
record "ADDR" do
|
23
|
+
street_address 4...24
|
24
|
+
city 24...44
|
25
|
+
postal_code 44...54
|
26
|
+
state 54...74
|
27
|
+
end
|
21
28
|
end
|
22
29
|
end
|
23
30
|
|
24
|
-
let(:
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
31
|
+
let(:records) do
|
32
|
+
[
|
33
|
+
{ type_signature: 'NAME', first_name: "Nicolaus", last_name: 'Copernicus' },
|
34
|
+
{ type_signature: 'ADDR', street_address: "123 South Street", city: "Nowhereville", postal_code: "45678Y", state: "Someplace" }
|
35
|
+
].map(&OpenStruct.method(:new))
|
29
36
|
end
|
30
37
|
|
31
|
-
|
38
|
+
subject(:formatted) { definition.format(records) }
|
32
39
|
|
33
|
-
|
34
|
-
|
40
|
+
it { is_expected.to have(2).lines }
|
41
|
+
|
42
|
+
its(:first) { is_expected.to eq "NAME NicolausCopernicus " }
|
43
|
+
its(:last) { is_expected.to eq "ADDR 123 South Street Nowhereville 45678Y Someplace" }
|
35
44
|
end
|
36
45
|
|
37
|
-
describe "
|
38
|
-
let(:definition)
|
39
|
-
Pikelet.define do
|
40
|
-
type_signature 0...1
|
46
|
+
describe "#parse" do
|
47
|
+
let(:records) { definition.parse(data).to_a }
|
41
48
|
|
42
|
-
|
43
|
-
name 1... 5
|
44
|
-
number 5...14
|
45
|
-
end
|
49
|
+
subject { records }
|
46
50
|
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
describe "for a simple flat file" do
|
52
|
+
let(:definition) do
|
53
|
+
Pikelet.define do
|
54
|
+
name 0... 4
|
55
|
+
number 4...13
|
50
56
|
end
|
51
57
|
end
|
52
|
-
end
|
53
58
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
+
let(:data) do
|
60
|
+
<<-FILE.split(/[\r\n]+/).map(&:lstrip)
|
61
|
+
John012345678
|
62
|
+
Sue 087654321
|
63
|
+
FILE
|
64
|
+
end
|
65
|
+
|
66
|
+
it { is_expected.to have(2).records }
|
67
|
+
|
68
|
+
its(:first) { is_expected.to match_hash(name: "John", number: "012345678") }
|
69
|
+
its(:last) { is_expected.to match_hash(name: "Sue", number: "087654321") }
|
59
70
|
end
|
60
71
|
|
72
|
+
describe "for a file with heterogeneous records" do
|
73
|
+
let(:definition) do
|
74
|
+
Pikelet.define do
|
75
|
+
type_signature 0...1
|
61
76
|
|
62
|
-
|
77
|
+
record 'A' do
|
78
|
+
name 1... 5
|
79
|
+
number 5...14
|
80
|
+
end
|
63
81
|
|
64
|
-
|
65
|
-
|
66
|
-
|
82
|
+
record 'B' do
|
83
|
+
number 1...10
|
84
|
+
name 10...14
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
67
88
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
89
|
+
let(:data) do
|
90
|
+
<<-FILE.split(/[\r\n]+/).map(&:lstrip)
|
91
|
+
AJohn012345678
|
92
|
+
B087654321Sue
|
93
|
+
FILE
|
73
94
|
end
|
74
|
-
end
|
75
95
|
|
76
|
-
let(:data) do
|
77
|
-
CSV.parse <<-FILE.gsub(/^\s*/, "")
|
78
|
-
John,012345678
|
79
|
-
Sue,087654321
|
80
|
-
FILE
|
81
|
-
end
|
82
96
|
|
83
|
-
|
97
|
+
it { is_expected.to have(2).records }
|
84
98
|
|
85
|
-
|
86
|
-
|
87
|
-
|
99
|
+
its(:first) { is_expected.to match_hash(name: "John", number: "012345678", type_signature: "A") }
|
100
|
+
its(:last) { is_expected.to match_hash(name: "Sue", number: "087654321", type_signature: "B") }
|
101
|
+
end
|
88
102
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
103
|
+
describe "inheritance" do
|
104
|
+
let(:definition) do
|
105
|
+
Pikelet.define do
|
106
|
+
type_signature 0...6
|
93
107
|
|
94
|
-
|
95
|
-
|
108
|
+
record 'SIMPLE' do
|
109
|
+
name 6...10
|
96
110
|
|
97
|
-
|
98
|
-
|
111
|
+
record 'FANCY' do
|
112
|
+
number 10...19
|
113
|
+
end
|
99
114
|
end
|
100
115
|
end
|
101
116
|
end
|
102
|
-
end
|
103
117
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
118
|
+
let(:data) do
|
119
|
+
<<-FILE.split(/[\r\n]+/).map(&:lstrip)
|
120
|
+
SIMPLEJohn012345678
|
121
|
+
FANCY Sue 087654321
|
122
|
+
FILE
|
123
|
+
end
|
110
124
|
|
111
|
-
|
125
|
+
it { is_expected.to have(2).records }
|
112
126
|
|
113
|
-
|
114
|
-
|
115
|
-
|
127
|
+
its(:first) { is_expected.to match_hash(name: "John", type_signature: "SIMPLE") }
|
128
|
+
its(:last) { is_expected.to match_hash(name: "Sue", number: "087654321", type_signature: "FANCY") }
|
129
|
+
end
|
116
130
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
131
|
+
describe "given a block for field parsing" do
|
132
|
+
let(:definition) do
|
133
|
+
Pikelet.define do
|
134
|
+
value(0...4) { |value| value.to_i }
|
135
|
+
end
|
121
136
|
end
|
122
|
-
end
|
123
137
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
138
|
+
let(:data) do
|
139
|
+
<<-FILE.split(/[\r\n]+/).map(&:lstrip)
|
140
|
+
5637
|
141
|
+
FILE
|
142
|
+
end
|
129
143
|
|
130
|
-
|
144
|
+
subject { records.first }
|
131
145
|
|
132
|
-
|
133
|
-
|
146
|
+
its(:value) { is_expected.to eq 5637 }
|
147
|
+
end
|
134
148
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
149
|
+
describe "given a parse option" do
|
150
|
+
let(:definition) do
|
151
|
+
Pikelet.define do
|
152
|
+
value 0...4, parse: ->(value) { value.to_i }
|
153
|
+
end
|
139
154
|
end
|
140
|
-
end
|
141
155
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
156
|
+
let(:data) do
|
157
|
+
<<-FILE.split(/[\r\n]+/).map(&:lstrip)
|
158
|
+
5637
|
159
|
+
FILE
|
160
|
+
end
|
147
161
|
|
148
|
-
|
162
|
+
subject { records.first }
|
149
163
|
|
150
|
-
|
151
|
-
|
164
|
+
its(:value) { is_expected.to eq 5637 }
|
165
|
+
end
|
152
166
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
167
|
+
describe "given a shorthand parse option" do
|
168
|
+
let(:definition) do
|
169
|
+
Pikelet.define do
|
170
|
+
value 0...4, parse: :to_i
|
171
|
+
end
|
157
172
|
end
|
158
|
-
end
|
159
173
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
174
|
+
let(:data) do
|
175
|
+
<<-FILE.split(/[\r\n]+/).map(&:lstrip)
|
176
|
+
5637
|
177
|
+
FILE
|
178
|
+
end
|
165
179
|
|
166
|
-
|
180
|
+
subject { records.first }
|
167
181
|
|
168
|
-
|
169
|
-
|
182
|
+
its(:value) { is_expected.to eq 5637 }
|
183
|
+
end
|
170
184
|
|
171
|
-
|
172
|
-
|
185
|
+
describe "given a block when parsing" do
|
186
|
+
let(:collected_records) { [] }
|
173
187
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
188
|
+
let(:definition) do
|
189
|
+
Pikelet.define do
|
190
|
+
name 0... 4
|
191
|
+
number 4...13
|
192
|
+
end
|
178
193
|
end
|
179
|
-
end
|
180
194
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
195
|
+
let(:data) do
|
196
|
+
<<-FILE.split(/[\r\n]+/).map(&:lstrip)
|
197
|
+
John012345678
|
198
|
+
Sue 087654321
|
199
|
+
FILE
|
200
|
+
end
|
187
201
|
|
188
|
-
|
189
|
-
|
190
|
-
|
202
|
+
before do
|
203
|
+
definition.parse(data) do |record|
|
204
|
+
collected_records << record.to_h
|
205
|
+
end
|
191
206
|
end
|
192
|
-
end
|
193
207
|
|
194
|
-
|
195
|
-
|
208
|
+
it 'yields each record to the block' do
|
209
|
+
expect(collected_records).to contain_exactly(*records.map(&:to_h))
|
210
|
+
end
|
196
211
|
end
|
197
212
|
end
|
198
213
|
|
@@ -205,7 +220,7 @@ describe Pikelet do
|
|
205
220
|
end
|
206
221
|
|
207
222
|
let(:data) do
|
208
|
-
<<-FILE.
|
223
|
+
<<-FILE.split(/[\r\n]+/).map(&:lstrip)
|
209
224
|
John012345678
|
210
225
|
Sue 087654321
|
211
226
|
FILE
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pikelet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Carney
|
@@ -151,9 +151,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
151
151
|
version: 2.1.0
|
152
152
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
153
|
requirements:
|
154
|
-
- - "
|
154
|
+
- - ">"
|
155
155
|
- !ruby/object:Gem::Version
|
156
|
-
version:
|
156
|
+
version: 1.3.1
|
157
157
|
requirements: []
|
158
158
|
rubyforge_project:
|
159
159
|
rubygems_version: 2.4.3
|