Robert Klemme
10/5/2004 3:18:00 PM
"James B Crigler" <james.b.crigler@lmco.com> schrieb im Newsbeitrag
news:4162AC3A.2BF27AC@lmco.com...
> I need to read a file into memory and parse it for information on
> demand as a kind of ad hoc query mechanism. (The file is
> a non-tabular report from a database.)
>
> Though there are other field types, for the time being, I only
> want to consider fields that appear with a tag on a single line,
> e.g.,
>
> Title: A Tale Of Two Cities
>
> Author: Charles Dickens
>
> There are various classes of files representing different object
> types as reported from the database. The tags, even for fields
> like title and author, are not consistent among report types. (I
> don't have control of the database, so I can't fix it.)
>
> My original implementation approximated the code you'll find below.
>
> There are some annoyances in the code:
>
> 1. The deferred lookups have to be written individually (def
> title, def author, etc.), though they only have to be written
> once if they belong in the base class.
>
> 2. I pass the variable into find_tagged_one_line to see whether
> it already has a value, but I can't assign it there.
>
> Is there a way, e.g., with missing_method, to create
> a table-driven caching dispatch on the field names that performs
> assignment in the find_... method?
>
>
> class Literature
> Tags = {
> 'title' => %r[^Title:\s*],
> 'author' => %r[^Author:\s*],
> # etc
> }
>
> def initialize(path)
> @text = Array.new
> @tags = Tags
> @title = nil
> @author = nil
> if File.exists? path
> File.open(path).each do |line|
> @text.push line.chomp
> end
Btw, you don't close the file handle properly here.
How about:
class TaggedItem
def initialize(tags)
@tags = tags
@values = {}
end
def push(tag, value)
(key = get_key tag) and @values[key] = value
end
def [](key) @values[key] end
def value?(key) @values.has_key? key end
def method_missing(s,*a)
super unless a.empty?
@values[s]
end
private
def get_key(tag) @tags[tag] end
end
lit = TaggedItem.new(
"Title" => :title,
"Author" => :author
)
nov = TaggedItem.new(
"Novel Title" => :title,
"Novel Author" => :author,
"Year of publication" => :year
)
all=[lit, nov]
while ( line = gets )
line.chomp!
if %r{^([^:]+):\s*(.*)$} =~ line
all.each {|x| x.push( $1, $2 )}
end
end
p all
p lit.author
Of course you can do all sorts of changes here, for example, you could
inherit OpenStruct and thus get rid of @values.
Kind regards
robert