flat 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +14 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +15 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +106 -0
- data/Rakefile +18 -0
- data/flat.gemspec +36 -0
- data/lib/flat/errors.rb +33 -0
- data/lib/flat/field.rb +171 -0
- data/lib/flat/file.rb +18 -0
- data/lib/flat/file_data.rb +123 -0
- data/lib/flat/layout.rb +30 -0
- data/lib/flat/read_operations.rb +50 -0
- data/lib/flat/record.rb +99 -0
- data/lib/flat/version.rb +3 -0
- data/lib/flat.rb +79 -0
- data/spec/flat_file_helper.rb +27 -0
- data/spec/lib/flat/field_spec.rb +126 -0
- data/spec/lib/flat/file_data_spec.rb +46 -0
- data/spec/lib/flat/file_spec.rb +5 -0
- data/spec/lib/flat/record_spec.rb +40 -0
- data/spec/lib/flat_spec.rb +28 -0
- data/spec/spec_helper.rb +17 -0
- metadata +247 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b8dda342a45881d96ffeec6a23b57f9697d820a0
|
4
|
+
data.tar.gz: 2d4a6c80305e3cf117f145d45ed789671e1934c7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 70a2839490d96e0dbcc8b32376c816b5f833bbd9935aa81b97bf79ed0ce7d3e21dbe916b7e2339de5c56bb14070af71a9da4b619707af96ddeabb62985794fea
|
7
|
+
data.tar.gz: faec279d9e961e3de45ad854527a4d4d5107c68720500b08c56d67c1364d0f12c4f7b4c9312df98b6bb12431a2903ad3848f363b97ba472205d4705c496626da
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
flat
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.2
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Mel Riffe
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# Flat
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/juicyparts/flat.svg?branch=develop)](https://travis-ci.org/juicyparts/flat)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/juicyparts/flat/badge.png?branch=develop)](https://coveralls.io/r/juicyparts/flat)
|
5
|
+
|
6
|
+
Flat is a library to make processing Flat Flies as easy as CSV files. Easily process flat files with Flat. Specify the format in a subclass of Flat::File and read and write until the cows come home.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'flat'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install flat
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
A simple example for a flat file class for grabbing information about
|
27
|
+
people might look like this:
|
28
|
+
|
29
|
+
# Actual plain text, flat file data, 29 bytes
|
30
|
+
#
|
31
|
+
# 10 20
|
32
|
+
# 012345678901234567890123456789
|
33
|
+
# Walt Whitman 18190531
|
34
|
+
# Linus Torvalds 19691228
|
35
|
+
|
36
|
+
class People < Flat::File
|
37
|
+
|
38
|
+
add_field :first_name, width: 10, filter: :trim
|
39
|
+
add_field :last_name, width: 10, filter: ->(v) { v.strip }
|
40
|
+
add_field :birthday, width: 8, filter: BirthdayFilter
|
41
|
+
pad :autoname, width: 2
|
42
|
+
|
43
|
+
def self.trim(v)
|
44
|
+
v.trim
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
p = People.new
|
50
|
+
|
51
|
+
p.each_record(open('somefile.dat')) do |person|
|
52
|
+
|
53
|
+
puts "First Name: #{person.first_name}"
|
54
|
+
puts "Last Name : #{person.last_name}"
|
55
|
+
puts "Birthday : #{person.birthday}"
|
56
|
+
|
57
|
+
puts person.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
Consult the [RDocs](http://rubydoc.info/github/juicyparts/flat) for additional examples, and information on Filters and
|
61
|
+
Formatters.
|
62
|
+
|
63
|
+
## Contributing
|
64
|
+
|
65
|
+
1. Fork it ( https://github.com/juicyparts/flat/fork )
|
66
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
67
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
68
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
69
|
+
5. Create a new Pull Request
|
70
|
+
|
71
|
+
## Inspiration
|
72
|
+
|
73
|
+
I had been looking for a library to handle flat files in a manner similar to
|
74
|
+
the CSV library and stumbled upon the following:
|
75
|
+
|
76
|
+
* flat_filer (http://rubygems.org/gems/flat_filer)
|
77
|
+
* flat_filer (https://github.com/xforty/flat_filer)
|
78
|
+
* flat_filer (https://github.com/cheapRoc/flat_filer)
|
79
|
+
|
80
|
+
They all appeared to be abandoned so I decided to resurrect them with my own
|
81
|
+
spin on the implementation.
|
82
|
+
|
83
|
+
# LICENSE
|
84
|
+
|
85
|
+
Copyright (c) 2014 Mel Riffe
|
86
|
+
|
87
|
+
MIT License
|
88
|
+
|
89
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
90
|
+
a copy of this software and associated documentation files (the
|
91
|
+
"Software"), to deal in the Software without restriction, including
|
92
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
93
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
94
|
+
permit persons to whom the Software is furnished to do so, subject to
|
95
|
+
the following conditions:
|
96
|
+
|
97
|
+
The above copyright notice and this permission notice shall be
|
98
|
+
included in all copies or substantial portions of the Software.
|
99
|
+
|
100
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
101
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
102
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
103
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
104
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
105
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
106
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rdoc/task'
|
4
|
+
|
5
|
+
# Default directory to look in is `/specs`
|
6
|
+
# Run with `rake spec`
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
8
|
+
task.rspec_opts = ['--color', '--format', 'documentation']
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => :spec
|
12
|
+
|
13
|
+
RDoc::Task.new(:rdoc => "doc", :clobber_rdoc => "doc:clean", :rerdoc => "doc:force") do |rdoc|
|
14
|
+
rdoc.rdoc_dir = 'doc'
|
15
|
+
rdoc.title = 'Flat Library Documentation'
|
16
|
+
rdoc.main = "README.md"
|
17
|
+
rdoc.rdoc_files.include("README.md", "lib/**/*.rb")
|
18
|
+
end
|
data/flat.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'flat/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "flat"
|
8
|
+
spec.version = Flat::VERSION
|
9
|
+
spec.authors = ["Mel Riffe"]
|
10
|
+
spec.email = ["mriffe@gmail.com"]
|
11
|
+
spec.summary = %q{Library to make processing Flat Flies as easy as CSV files.}
|
12
|
+
spec.description = %q{Easily process flat files with Flat. Specify the format in a subclass of Flat::File and read and write until the cows come home.}
|
13
|
+
spec.homepage = "http://rubydoc.info/github/juicyparts/flat"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "extlib", "~> 0.9.0"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", ">= 1.6.2" # was "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rdoc", "~> 4.1.0"
|
26
|
+
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.1.0"
|
28
|
+
spec.add_development_dependency "rspec-nc", "~> 0.2.0"
|
29
|
+
spec.add_development_dependency "guard", "~> 2.6.0"
|
30
|
+
spec.add_development_dependency "guard-rspec", "~> 4.3.0"
|
31
|
+
spec.add_development_dependency "pry", "~> 0.10.0"
|
32
|
+
spec.add_development_dependency "pry-remote", "~> 0.1.0"
|
33
|
+
spec.add_development_dependency "pry-nav", "~> 0.2.0"
|
34
|
+
|
35
|
+
spec.add_development_dependency "coveralls", "~> 0.7.0"
|
36
|
+
end
|
data/lib/flat/errors.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Errors #:nodoc:
|
2
|
+
|
3
|
+
# = FlatFileError
|
4
|
+
#
|
5
|
+
# Generic error class and superclass of all other errors raised by Flat.
|
6
|
+
#
|
7
|
+
class FlatFileError < StandardError; end
|
8
|
+
|
9
|
+
# = LayoutConstructorError
|
10
|
+
#
|
11
|
+
# The specified layout definition was not valid.
|
12
|
+
#
|
13
|
+
class LayoutConstructorError < FlatFileError; end
|
14
|
+
|
15
|
+
# = RecordLengthError
|
16
|
+
#
|
17
|
+
# Generic error having to do with line lengths not meeting expectations.
|
18
|
+
#
|
19
|
+
class RecordLengthError < FlatFileError; end
|
20
|
+
|
21
|
+
# = ShortRecordError
|
22
|
+
#
|
23
|
+
# The incoming line was shorter than expections defined.
|
24
|
+
#
|
25
|
+
class ShortRecordError < RecordLengthError; end
|
26
|
+
|
27
|
+
# = LongRecordError
|
28
|
+
#
|
29
|
+
# The incoming line was longer than expections defined.
|
30
|
+
#
|
31
|
+
class LongRecordError < RecordLengthError; end
|
32
|
+
|
33
|
+
end # => module Errors
|
data/lib/flat/field.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
##
|
2
|
+
# = Field
|
3
|
+
#
|
4
|
+
# A field definition tracks information that's necessary for
|
5
|
+
# FlatFile to process a particular field. This is typically
|
6
|
+
# added to a subclass of FlatFile like so:
|
7
|
+
#
|
8
|
+
# class SomeFile < FlatFile
|
9
|
+
# add_field :some_field_name, :width => 35
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
module Field
|
13
|
+
##
|
14
|
+
# = Class Methods
|
15
|
+
#
|
16
|
+
# Defines behavior for subclasses of Flat::File regarding the specification
|
17
|
+
# of the line structure contained in a flat file.
|
18
|
+
#
|
19
|
+
module ClassMethods
|
20
|
+
|
21
|
+
##
|
22
|
+
# Add a field to the FlatFile subclass. Options can include
|
23
|
+
#
|
24
|
+
# :width - number of characters in field (default 10)
|
25
|
+
# :filter - callack, lambda or code block for processing during reading
|
26
|
+
# :formatter - callback, lambda, or code block for processing during writing
|
27
|
+
#
|
28
|
+
# class SomeFile < FlatFile
|
29
|
+
# add_field :some_field_name, :width => 35
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# == Options
|
33
|
+
#
|
34
|
+
def add_field name = nil, options = {}, &block
|
35
|
+
fields << field_def = Field::Definition.new(name, options, self)
|
36
|
+
|
37
|
+
yield field_def if block_given?
|
38
|
+
|
39
|
+
pack_format << "A#{field_def.width}"
|
40
|
+
flat_file_data[:width] += field_def.width
|
41
|
+
# width += field_def.width # doesn't work for some reason
|
42
|
+
|
43
|
+
# TODO: Add a check here to ensure the Field has a name specified; it can be a String or Symbol
|
44
|
+
return field_def
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Add a pad field. To have the name auto generated, use :autoname for
|
49
|
+
# the name parameter. For options see +add_field+.
|
50
|
+
#
|
51
|
+
def pad name, options = {}
|
52
|
+
add_field ( name == :autoname ? new_pad_name : name ), options.merge( padding: true )
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
##
|
58
|
+
# Used to generate unique names for pad fields which use :autoname.
|
59
|
+
#
|
60
|
+
def new_pad_name #:nodoc:
|
61
|
+
"pad_#{unique_id}".to_sym
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Increments an id counter which is used to generate unique pad names
|
66
|
+
#
|
67
|
+
def unique_id #:nodoc:
|
68
|
+
@unique_id = (@unique_id || 0) + 1
|
69
|
+
end
|
70
|
+
|
71
|
+
end # => module ClassMethods
|
72
|
+
|
73
|
+
module InstanceMethods #:nodoc:
|
74
|
+
end # => module InstanceMethods
|
75
|
+
|
76
|
+
def self.included receiver #:nodoc:
|
77
|
+
receiver.extend ClassMethods
|
78
|
+
receiver.send :include, InstanceMethods
|
79
|
+
end
|
80
|
+
|
81
|
+
# = Definition
|
82
|
+
# Used in Flat::File subclasses to define how a Record is defined.
|
83
|
+
#
|
84
|
+
# class SomeFile < Flat::File
|
85
|
+
# add_field :some_field_name, :width => 35
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
class Definition #:nodoc:
|
89
|
+
attr_accessor :parent, :name, :width, :padding, :aggressive
|
90
|
+
attr_accessor :filters, :formatters, :map_in_proc
|
91
|
+
|
92
|
+
##
|
93
|
+
# Create a new FieldDef, having name and width. parent is a reference to the
|
94
|
+
# FlatFile subclass that contains this field definition. This reference is
|
95
|
+
# needed when calling filters if they are specified using a symbol.
|
96
|
+
#
|
97
|
+
# Options can be :padding (if present and a true value, field is marked as a
|
98
|
+
# pad field), :width, specify the field width, :formatter, specify a formatter,
|
99
|
+
# :filter, specify a filter.
|
100
|
+
#
|
101
|
+
def initialize name = null, options = {}, parent = {}
|
102
|
+
@parent, @name = parent, name
|
103
|
+
|
104
|
+
@width = options.fetch(:width, 10)
|
105
|
+
@padding = options.fetch(:padding, false)
|
106
|
+
@aggressive = options.fetch(:aggressive, false)
|
107
|
+
|
108
|
+
@filters = @formatters = Array.new
|
109
|
+
|
110
|
+
add_filter options[:filter]
|
111
|
+
add_formatter options[:formatter]
|
112
|
+
|
113
|
+
@map_in_proc = options[:map_in_proc]
|
114
|
+
end
|
115
|
+
|
116
|
+
def padding?
|
117
|
+
@padding
|
118
|
+
end
|
119
|
+
|
120
|
+
def aggressive?
|
121
|
+
@aggressive
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Add a filter. Filters are used for processing field data when a flat file is
|
126
|
+
# being processed. For fomratting the data when writing a flat file, see
|
127
|
+
# add_formatter
|
128
|
+
#
|
129
|
+
def add_filter filter = nil, &block
|
130
|
+
@filters.push( filter ) unless filter.blank?
|
131
|
+
@filters.push( block ) if block_given?
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# Add a formatter. Formatters are used for formatting a field
|
136
|
+
# for rendering a record, or writing it to a file in the desired format.
|
137
|
+
#
|
138
|
+
def add_formatter formatter = nil, &block
|
139
|
+
@formatters.push( formatter ) unless formatter.blank?
|
140
|
+
@formatters.push( block ) if block_given?
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Passes value through the filters defined on this Field::Definition
|
145
|
+
#
|
146
|
+
def filter value
|
147
|
+
@filters.each do |filter|
|
148
|
+
value = case filter
|
149
|
+
when Symbol
|
150
|
+
@parent.public_send filter, value
|
151
|
+
when Proc
|
152
|
+
if filter.arity == 0
|
153
|
+
value
|
154
|
+
else
|
155
|
+
filter.call value
|
156
|
+
end
|
157
|
+
when Class, Object
|
158
|
+
unless filter.respond_to? 'filter'
|
159
|
+
value
|
160
|
+
else
|
161
|
+
filter.filter value
|
162
|
+
end
|
163
|
+
else
|
164
|
+
value
|
165
|
+
end
|
166
|
+
end
|
167
|
+
value
|
168
|
+
end
|
169
|
+
end # => class Definition
|
170
|
+
|
171
|
+
end # => module Field
|
data/lib/flat/file.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'flat/errors'
|
2
|
+
require 'flat/file_data'
|
3
|
+
require 'flat/field'
|
4
|
+
require 'flat/layout'
|
5
|
+
require 'flat/record'
|
6
|
+
require 'flat/read_operations'
|
7
|
+
|
8
|
+
# = Flat::File
|
9
|
+
#
|
10
|
+
class Flat::File
|
11
|
+
include Errors
|
12
|
+
include FileData
|
13
|
+
include Layout
|
14
|
+
include Field
|
15
|
+
include Record
|
16
|
+
include ReadOperations
|
17
|
+
|
18
|
+
end # => class Flat::File
|
@@ -0,0 +1,123 @@
|
|
1
|
+
##
|
2
|
+
# = FileData
|
3
|
+
#
|
4
|
+
# Defines structures and accessors for the internal FileData required by Flat::File
|
5
|
+
# and its successful operations.
|
6
|
+
#
|
7
|
+
module FileData
|
8
|
+
##
|
9
|
+
# = Class Methods
|
10
|
+
#
|
11
|
+
# Defines behavior for subclasses of Flat::File regarding the management of
|
12
|
+
# its internal data structures.
|
13
|
+
#
|
14
|
+
module ClassMethods
|
15
|
+
|
16
|
+
##
|
17
|
+
# Container for various points of data as defined in the Flat::File subclass.
|
18
|
+
#
|
19
|
+
# Returns a +Hash+ with the following keys:
|
20
|
+
# * +:width+ - The overall width, or length, of a line in the flat file.
|
21
|
+
# * +:pack_format+ - A format +String+ for use by String#unpack.
|
22
|
+
# * +:fields+ - An +Array+ of Field::Definitions
|
23
|
+
# * +:layouts+ - An +Array+ of Layout::Definitions
|
24
|
+
#
|
25
|
+
def flat_file_data
|
26
|
+
@data ||= {
|
27
|
+
:width => 0,
|
28
|
+
:pack_format => '',
|
29
|
+
:fields => [],
|
30
|
+
:layouts => [],
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Convenience method for accessing <tt>flat_file_data[:fields]</tt>
|
36
|
+
#
|
37
|
+
# Returns an +Array+ of Field::Definitions
|
38
|
+
#
|
39
|
+
def fields
|
40
|
+
flat_file_data[:fields]
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Convenience method for accessing <tt>flat_file_data[:width]</tt>
|
45
|
+
#
|
46
|
+
# Returns the overall length of a line to text in the flat file.
|
47
|
+
#
|
48
|
+
def width
|
49
|
+
flat_file_data[:width]
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Added setter to support +=, -= constructs; also allows direct
|
54
|
+
# assignment.
|
55
|
+
#
|
56
|
+
def width=(value) #:nodoc:
|
57
|
+
flat_file_data[:width] = value
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Convenience method for accessing <tt>flat_file_data[:pack_format]</tt>
|
62
|
+
#
|
63
|
+
# Returns a +String+ sutiable for use with String#unpack
|
64
|
+
#
|
65
|
+
def pack_format
|
66
|
+
flat_file_data[:pack_format]
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Convenience method for accessing <tt>flat_file_data[:layouts]</tt>
|
71
|
+
#
|
72
|
+
# Returns an +Array+ of Layout::Definitions
|
73
|
+
#
|
74
|
+
def layouts
|
75
|
+
flat_file_data[:layout]
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Added for test purposes, primarily. DESTRUCTIVE!
|
80
|
+
#
|
81
|
+
def reset_file_data #:nodoc:
|
82
|
+
@data = nil
|
83
|
+
end
|
84
|
+
|
85
|
+
end # => module ClassMethods
|
86
|
+
|
87
|
+
##
|
88
|
+
# = Instance Methods
|
89
|
+
#
|
90
|
+
# Defines behavior for instances of subclasses of Flat::File regarding the
|
91
|
+
# accessing of its internal data structures.
|
92
|
+
#
|
93
|
+
module InstanceMethods
|
94
|
+
|
95
|
+
##
|
96
|
+
# Returns the +width+ of this Flat::File subclass as defined in its class
|
97
|
+
#
|
98
|
+
def width
|
99
|
+
self.class.width
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# Returns the +pack_format+ of this Flat::File subclass as defined in its class
|
104
|
+
#
|
105
|
+
def pack_format
|
106
|
+
self.class.pack_format
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Returns the +fields+ of this Flat::File subclass as defined in its class
|
111
|
+
#
|
112
|
+
def fields
|
113
|
+
self.class.fields
|
114
|
+
end
|
115
|
+
|
116
|
+
end # => module InstanceMethods
|
117
|
+
|
118
|
+
def self.included receiver #:nodoc:
|
119
|
+
receiver.extend ClassMethods
|
120
|
+
receiver.send :include, InstanceMethods
|
121
|
+
end
|
122
|
+
|
123
|
+
end # => module FileData
|
data/lib/flat/layout.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# = Layout
|
2
|
+
# *EXPERIMENTAL*
|
3
|
+
#
|
4
|
+
# If a flat file contains several different record structures, defining
|
5
|
+
# more than one Layout::Definition allows Flat::File to easily process
|
6
|
+
# the file.
|
7
|
+
#
|
8
|
+
# *EXPERIMENTAL*
|
9
|
+
#
|
10
|
+
module Layout
|
11
|
+
module ClassMethods #:nodoc:
|
12
|
+
end # => module ClassMethods
|
13
|
+
|
14
|
+
module InstanceMethods #:nodoc:
|
15
|
+
end # => module InstanceMethods
|
16
|
+
|
17
|
+
def self.included receiver #:nodoc:
|
18
|
+
receiver.extend ClassMethods
|
19
|
+
receiver.send :include, InstanceMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
# = Definition
|
23
|
+
# Add the ability to have multiple layouts per flat flat.
|
24
|
+
#
|
25
|
+
# EXPERIMENTAL
|
26
|
+
#
|
27
|
+
class Definition #:nodoc:
|
28
|
+
end # => class Definition
|
29
|
+
|
30
|
+
end # => module Layout
|
@@ -0,0 +1,50 @@
|
|
1
|
+
##
|
2
|
+
# = ReadOperations
|
3
|
+
#
|
4
|
+
# Defines functionality required for the successful reading, parsing and
|
5
|
+
# interpreting of a line of text contained in a flat file.
|
6
|
+
#
|
7
|
+
module ReadOperations
|
8
|
+
module ClassMethods #:nodoc:
|
9
|
+
end # => module ClassMethods
|
10
|
+
|
11
|
+
##
|
12
|
+
# = Instance Methods
|
13
|
+
#
|
14
|
+
# Defines behavior for instances of a subclass of Flat::File regarding the
|
15
|
+
# reading and parsing of the file contents, line by line.
|
16
|
+
#
|
17
|
+
module InstanceMethods
|
18
|
+
|
19
|
+
# Iterate through each record (each line of the data file). The passed
|
20
|
+
# block is passed a new Record representing the line.
|
21
|
+
#
|
22
|
+
# s = SomeFile.new
|
23
|
+
# s.each_record(open('/path/to/file')) do |r|
|
24
|
+
# puts r.first_name
|
25
|
+
# end
|
26
|
+
#--
|
27
|
+
# NOTE: Expects an open valid IO handle; opening and closing is out of scope
|
28
|
+
#++
|
29
|
+
#
|
30
|
+
def each_record io, &block
|
31
|
+
io.each_line do |line|
|
32
|
+
line.chop!
|
33
|
+
next if line.length.zero?
|
34
|
+
|
35
|
+
unless (self.width - line.length).zero?
|
36
|
+
raise Errors::RecordLengthError, "length is #{line.length} but should be #{self.width}"
|
37
|
+
end
|
38
|
+
|
39
|
+
yield create_record(line, io.lineno), line
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end # => module InstanceMethods
|
44
|
+
|
45
|
+
def self.included receiver #:nodoc:
|
46
|
+
receiver.extend ClassMethods
|
47
|
+
receiver.send :include, InstanceMethods
|
48
|
+
end
|
49
|
+
|
50
|
+
end # => module ReadOperations
|