G
Giles Bowkett
I'm writing some code which works in the context of a very popular Web
framework and yet bumps against limitations in that framework several
times a day. One thing I have to do **constantly** is this:
def foo
class << bar
attr_accessor :baz
end
do_stuff(bar.baz)
end
or sometimes even
def foo
instance_eval do
class << self
attr_accessor :bar
end
end
do_stuff(bar)
end
This pattern gets ugly fast. It would be so much easier if I could just do
foo.add_accessorbar)
and get the same functionality as
class << foo
attr_accessor :bar
end
so I tried to graft this onto the base object:
class BaseObject
def add_methods(methods)
class << self
attr_accessor methods
end
end
end
But that blew up on me. There's two flaws in that. The first is that
methods is already a method name, so using it as a variable name was a
pretty dumb idea. The second is that the arg to the method isn't
visible once you're inside that class << self block.
It doesn't seem as if there's any way to do it without using #eval,
and frankly, using #eval is so last month. Who uses #eval any more?
That's like Fred Flintstone style.
Nonetheless, here's how you can do it with eval:
class Base
def add_xsor(xsor)
eval("class << self ; attr_accessor :#{xsor} ; end")
end
end
class Boat < Base ; end
boat = Boat.new
boat.add_xsorneed)
boat.need = "bigger"
The big flaw here, of course, is that it only works on instances, but
in practical terms I always seem to use it in an instance context.
I'm going to have to use this code for the time being but I'm
definitely on the lookout for a better way to do it. It's clean, but
not totally satisfying.
--
Giles Bowkett
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com/
framework and yet bumps against limitations in that framework several
times a day. One thing I have to do **constantly** is this:
def foo
class << bar
attr_accessor :baz
end
do_stuff(bar.baz)
end
or sometimes even
def foo
instance_eval do
class << self
attr_accessor :bar
end
end
do_stuff(bar)
end
This pattern gets ugly fast. It would be so much easier if I could just do
foo.add_accessorbar)
and get the same functionality as
class << foo
attr_accessor :bar
end
so I tried to graft this onto the base object:
class BaseObject
def add_methods(methods)
class << self
attr_accessor methods
end
end
end
But that blew up on me. There's two flaws in that. The first is that
methods is already a method name, so using it as a variable name was a
pretty dumb idea. The second is that the arg to the method isn't
visible once you're inside that class << self block.
It doesn't seem as if there's any way to do it without using #eval,
and frankly, using #eval is so last month. Who uses #eval any more?
That's like Fred Flintstone style.
Nonetheless, here's how you can do it with eval:
class Base
def add_xsor(xsor)
eval("class << self ; attr_accessor :#{xsor} ; end")
end
end
class Boat < Base ; end
boat = Boat.new
boat.add_xsorneed)
boat.need = "bigger"
The big flaw here, of course, is that it only works on instances, but
in practical terms I always seem to use it in an instance context.
I'm going to have to use this code for the time being but I'm
definitely on the lookout for a better way to do it. It's clean, but
not totally satisfying.
--
Giles Bowkett
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com/