pikelet 1.1.2 → 2.0.0.beta.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.
- 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
|