Trans
9/7/2007 11:25:00 AM
On Sep 7, 2:24 am, "Giles Bowkett" <gil...@gmail.com> wrote:
> 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_accessor(:bar)
>
> 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_xsor(:need)
> 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.
module Kernel
def meta
class << self; self; end
end
end
class Module
public :attr_accessor, :attr_reader, :attr_writer
end
then
def foo
meta.attr_accessor :x
end
T.