« Return to Thread: simple way to encapsulate class << self ; attr_accessor :xyz ; end?

simple way to encapsulate class << self ; attr_accessor :xyz ; end?

by Giles Bowkett :: Rate this Message:

Reply to Author | View in Thread

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.

--
Giles Bowkett

Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com/

 « Return to Thread: simple way to encapsulate class << self ; attr_accessor :xyz ; end?