[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Passing parameters into a singleton class def?

Doug Glidden

8/24/2008 1:10:00 AM

Hi,

I'm a little new to Ruby, so please feel free to suggest a completely
different and better way to do this, if you have one. I'm trying to
figure out a way to access a variable within a singleton class
definition that is defined outside the singleton class definition.
Basically, I want to be able to add new, user-defined instance variables
and readers and writers for the instance variables to an object. I can
do it fine if I construct the list of instance variables inline. Given
a definition of MyClass, of course, the following code works
beautifully:

var = MyClass.new
class << var
attr_accessor :field1, :field2, :field3
end

However, I need to be able to build the list prior to doing the
singleton class definition (ideally, I want to be able to pass the list
of instance variables into an instance method and have it take care of
the singleton class definition on itself). This is the way code is
written right now:

class MyClass
...

def add_fields(*field_list)
class << self
attr accessor *field_list
end
end
end

I've also tried the following in irb (identical to the above code that
works, except that the list of fields is assigned to a variable instead
of being constructed inline):

var = MyClass.new
list = :field1, :field2, :field3
class << var
attr_accessor list
end

Both throw an error because field_list is not defined within the
singleton class definition? Am I making a simple mistake, or should I
be doing this differently?

Thanks,
Doug G.
--
Posted via http://www.ruby-....

3 Answers

David Masover

8/24/2008 1:26:00 AM

0

On Saturday 23 August 2008 20:09:52 Doug Glidden wrote:
> class MyClass
> ...
>
> def add_fields(*field_list)
> class << self
> attr accessor *field_list
> end
> end
> end
[snip]
> Both throw an error because field_list is not defined within the
> singleton class definition? Am I making a simple mistake, or should I
> be doing this differently?

Well, if you actually have fields called :field1, :field2, and :field3, I
might suggest an array... Assuming that's not the case.

I don't even remember the actual Ruby way to do this, but _why's metaid gem
would let you do it like this:

def add_fields(*field_list)
meta_eval do
attr_accessor *field_list
end
end

The key, however, is that it's some sort of _eval method -- that it's taking a
block, which means you get to inherit the parent scope. In fact, if it's
actually a singleton (as in, only one instance of this class will be
defined), you can do this:

def add_fields(*field_list)
self.class.class_eval do
attr_accessor *field_list
end
end

In this case, self.class refers to the actual class that the current object is
an instance of. On the other hand, self.metaclass or meta_eval (both from
metaid) refer to the current object's metaclass, or eigenclass.

Given that you were doing "class << foo" stuff, I'm assuming you wanted the
metaclass.

One more hack before I'm through:

def add_fields(*field_list)
self.metaclass.send :attr_accessor, *field_list
end

I haven't tested any of this. Let me know how it works for you.

Sean O'Halpin

8/24/2008 1:38:00 AM

0

On Sun, Aug 24, 2008 at 2:09 AM, Doug Glidden <41mortimer@gmail.com> wrote:
> Hi,
>
> I'm a little new to Ruby, so please feel free to suggest a completely
> different and better way to do this, if you have one. I'm trying to
> figure out a way to access a variable within a singleton class
> definition that is defined outside the singleton class definition.
> Basically, I want to be able to add new, user-defined instance variables
> and readers and writers for the instance variables to an object. I can
> do it fine if I construct the list of instance variables inline. Given
> a definition of MyClass, of course, the following code works
> beautifully:
>
> var = MyClass.new
> class << var
> attr_accessor :field1, :field2, :field3
> end
>
> However, I need to be able to build the list prior to doing the
> singleton class definition (ideally, I want to be able to pass the list
> of instance variables into an instance method and have it take care of
> the singleton class definition on itself). This is the way code is
> written right now:
>
> class MyClass
> ...
>
> def add_fields(*field_list)
> class << self
> attr accessor *field_list
> end
> end
> end
>
> I've also tried the following in irb (identical to the above code that
> works, except that the list of fields is assigned to a variable instead
> of being constructed inline):
>
> var = MyClass.new
> list = :field1, :field2, :field3
> class << var
> attr_accessor list
> end
>
> Both throw an error because field_list is not defined within the
> singleton class definition? Am I making a simple mistake, or should I
> be doing this differently?
>
> Thanks,
> Doug G.
> --
> Posted via http://www.ruby-....
>
>
Something like this?

class A
end

a = A.new
fields = [:a, :b]
(class << a; self; end).class_eval do
attr_accessor *fields
end
a.a = 1
a.b = 2
p a
b = A.new
b.a = 3
__END__
#<A:0x25094 @a=1, @b=2>
rt.rb:13: undefined method `a=' for #<A:0x24f40> (NoMethodError)

Regards,
Sean

Doug Glidden

8/24/2008 2:05:00 AM

0

Sean O'halpin wrote:
> Something like this?
>
> class A
> end
>
> a = A.new
> fields = [:a, :b]
> (class << a; self; end).class_eval do
> attr_accessor *fields
> end
> a.a = 1
> a.b = 2
> p a
> b = A.new
> b.a = 3
> __END__
> #<A:0x25094 @a=1, @b=2>
> rt.rb:13: undefined method `a=' for #<A:0x24f40> (NoMethodError)
>
> Regards,
> Sean

David Masover wrote:
> Well, if you actually have fields called :field1, :field2, and :field3,
I
> might suggest an array... Assuming that's not the case.

> I don't even remember the actual Ruby way to do this, but _why's metaid
gem
> would let you do it like this:

> def add_fields(*field_list)
> meta_eval do
> attr_accessor *field_list
> end
> end

> The key, however, is that it's some sort of _eval method -- that it's
taking a
> block, which means you get to inherit the parent scope. In fact, if it's
> actually a singleton (as in, only one instance of this class will be
> defined), you can do this:

> def add_fields(*field_list)
> self.class.class_eval do
> attr_accessor *field_list
> end
> end

> In this case, self.class refers to the actual class that the current
object is
> an instance of. On the other hand, self.metaclass or meta_eval (both
from
> metaid) refer to the current object's metaclass, or eigenclass.

> Given that you were doing "class << foo" stuff, I'm assuming you wanted
the
> metaclass.

> One more hack before I'm through:

> def add_fields(*field_list)
> self.metaclass.send :attr_accessor, *field_list
> end

> I haven't tested any of this. Let me know how it works for you.

Thanks very much to both of you! I'm not using why's metaid gem, but I
am familiar with the way he does things. I had tried using class_eval,
as Sean suggested, but I wasn't using it quite correctly. Sean's code
worked perfectly, but I wanted to make it a little more
compartmentalized, so I used some of why's strategy. Here's the final
working example code:

class MyClass
def metaclass
class << self
self
end
end
...

def add_fields(*field_list)
metaclass.class_eval do
attr_accessor *field_list
end
end
end

Of course, it would be better to move the metaclass method into a mixin,
or just use why's metaid gem.

Thanks again,
Doug
--
Posted via http://www.ruby-....