Created
March 18, 2009 00:34
-
-
Save caius/80858 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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