From: Robert Klemme Date: 2004-10-06T00:19:51+09:00 Subject: Re: Table-driven dispatch "James B Crigler" 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