Attr_reader for great number of instance vars

I’m building a parser class which uses a separate token class to store
regexes about to help recognize custom markup tags.

class Tokens
attr_reader( :start_link, :end_link, :bold )
def initialize
@start_link = /[[/
@end_link = /]]/
@bold = /**/
end
end

The attr_reader line looks clumsy to me. Is there a way to get the class to
automatically allow for any instance variable to be given the attr_reader
characteristic? This list could get quite long and while I am using
Test::Unit to keep from breaking things the more I fix them. Mostly I’m
lazy and I’d prefer not to have to add a variable name in two places.

Thanks for your help.

  • -michael libby

michael libby x@ichimunki.com writes:

The attr_reader line looks clumsy to me. Is there a way to get the class to
automatically allow for any instance variable to be given the attr_reader
characteristic?

THe class doesn’t know it’s instance variables: they only appear in
the actually instances when first used (that is, each instance could
potentially have a different set of instance variables). The code
below is kind of dangerous, but dynamically defines reader methods for
any otherwise unknown method call:

class Dave

  def method_missing(name, *args)
    fail "No one expects the extra args" unless args.empty?
    type.class_eval "attr_reader :#{name}"
    send name
  end

  def initialize
    @a = 1
    @b = "cat"
    @c = /abc/
  end

end

d = Dave.new

p d.a
p d.b
p d.c

If there was some point at which you knew all your instance variables
were set, you could always use the Object#instance_variables method to
iterate over them and create accessors.

Cheers

Dave

I’m building a parser class which uses a separate token class to store
regexes about to help recognize custom markup tags.

If these tokens are a static entity (ie. they are predefined), then you
can use a Struct.

In which case your Tokens class becomes:

Tokens = Struct.new(“Tokens”, :start_link, :end_link, :bold)
t = Tokens.new(/[[/, /]]/, /**/)

Which does the same thing as your Token class below, with the addition
that the Struct also provides “attr_writer” for each attribute of the
Tokens class.

class Tokens
attr_reader( :start_link, :end_link, :bold )
def initialize
@start_link = /[[/
@end_link = /]]/
@bold = /**/
end
end

The following is from ‘ri Struct’. “A Struct is a convenient way to
bundle a number of attributes together, using accessor methods, without
having to write an explicit class.” That seems to me to be what you
want.

-Michael