does anyone else think that having attr_* keep track of the attributes might
be helpful? i’ve done it by hand many times. i’m thinking something like
this might be generally useful:
attr.rb
====CUT====
class Module
private
alias_method :__attr_reader, :attr_reader
alias_method :__attr_writer, :attr_writer
alias_method :__attr, :attr
def attr_reader(*symbols)
__attr_reader *symbols
(@reader_attributes ||= ).push *symbols
end
def attr_writer(*symbols)
__attr_writer *symbols
(@writer_attributes ||= ).push *symbols
end
def attr symbol, writable = false
__attr symbol, writable
(@reader_attributes ||= ).push symbol
(@writer_attributes ||= ).push symbol if writable
end
public
def attributes type = nil
case type.to_s
when %r/read|get/
@reader_attributes.clone
when %r/writ|set/
@writer_attributes.clone
else
@reader_attributes | @writer_attributes
end
end
end
if $0 == FILE
class Foo
attr_reader :foo
attr_writer :bar
attr :foobar
attr :barfoo, true
def not_an_attribute; end
end
p Foo.attributes # -> [:foo, :foobar, :barfoo, :bar]
p Foo.attributes :reader # -> [:foo, :foobar, :barfoo]
p Foo.attributes :writer # -> [:bar, :barfoo]
end
====CUT====
here’s an example where/why i’ve used it:
class CannotMarshal < RBTree
…
…
…
def _dump depth
Marshal.dump {:data => to_hash, :attributes => class.attributes(:reader).sort.map{|a| send a}}
end
class << self
def _load string
cm = CannotMarshal.new
loaded = Marshal.load string
cm.update loaded[:data]
cm.class.attributes(:writer).sort.map{|a| cm.send a, loaded[:attributes].shift}
cm
end
end
end
the above requires a writer for every reader, but you get the idea…
-a
···
–
Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ara.t.howard@noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
~ > ruby -e ‘p(%.\x2d\x29…intern)’
====================================