Skip to content

Instantly share code, notes, and snippets.

@caius
Created March 18, 2009 00:34
Show Gist options
  • Save caius/80858 to your computer and use it in GitHub Desktop.
Save caius/80858 to your computer and use it in GitHub Desktop.
require "date"
require "time"
class FixedRow
attr_accessor :formats
def initialize
@columns = []
@formats = {
:datetime => lambda {|x| Date.parse(x) }
}
@data = {}
yield(self) if block_given?
end
# Define a column to parse out
# <b>Name</b>: name of column. Eg: <tt>:first</tt>
# <b>Range</b>: Array of starting element and length of substring. <tt>Eg: [0, 5]</tt>
# <b>parse_block</b>: block takes one param and returns Object to store for column.
# Eg: <tt>{|col| Date.parse(col) }</tt>
#
def column name, range, type=nil, &parse_block
rf = {:name => name, :range => range, :type => type}
rf[:block] = parse_block if block_given?
@columns << rf
end
# Parse the actual row into columns
# Raises RuntimeError if a block raises an error.
def parse text
@columns.each do |r|
# Pull out the sub string
substr = text[*r[:range]]
# See if theres a type
if r.has_key?(:type) && @formats.has_key?(r[:type])
substr = @formats[r[:type]].call(text)
# Check if there's a block
elsif r.has_key?(:block)
# Make sure we catch any errors in the block
begin
substr = r[:block].call(substr)
rescue Exception => e
raise "Error parsing col '#{r[:name].inspect}': #{e.message}"
end
end
#
@data[r[:name]] = substr
end
end
# Return the data for the column name.
# Returns nil if column unknown.
def get col_name
@data[col_name]
end
# Lets us grab columns as if they were attributes of the object
def method_missing(name, *args)
self.get(name) || super
end
end
# Define the columns when creating the object
a = FixedRow.new do |r|
r.column :first, [0, 5]
r.column :last, [6, 7]
end
# Or add them afterwards
a.column(:dob, [14, 10], :datetime)
a.column(:time, [25, 5]) {|x| Time.parse(x) }
a.parse("caius durling 1987-11-09 15:15")
a.get(:first) # => "caius"
a.first # => "caius"
a.get(:last) # => "durling"
a.last # => "durling"
a.get(:dob) # => #<Date: 4894217/2,0,2299161>
a.dob # => #<Date: 4894217/2,0,2299161>
a.get(:dob).to_s # => "1987-11-09"
a.time # => Wed Mar 18 15:15:00 +0000 2009
a.get(:"doesn't exist") # => nil
a.whoop! # =>
# ~> -:60:in `method_missing': undefined method `whoop!' for #<FixedRow:0x7c948> (NoMethodError)
# ~> from -:86
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment