Dynamic attr_accessor?

hello

I like to create methods for my class dynamically based on
strings I pass to initialize

It should look like this:

class Cl
def initialize(name)
@name = name
attr_accessor :@name # wrong syntax but how to do it?
end
end

c = Cl.new(“temp”)

It seems that I can not call attr_accessor within initialize

is there a way to achive what I want??

markus

class Cl
   def initialize(name)
          @name = name
          attr_accessor :@name # wrong syntax but how to do it?

use type.send

   end
end

Guy Decoux

Hi,

···

At Mon, 3 Jun 2002 20:31:22 +0900, Markus Jais wrote:

I like to create methods for my class dynamically based on
strings I pass to initialize

class Cl
def initialize(name)
class << self;self;end.class_eval {attr_accessor name}
end
end


Nobu Nakada

Hi,

I like to create methods for my class dynamically based on
strings I pass to initialize

a) attr_accessor is a method of a class
b) attr_accessor takes names of accessors
c) attr_accessor just defines two methods

So the answer should be

easier one:

class Cl
def initialize(name)
@name = name
self.instance_eval "
def #{name}; @#{name}; end
def #{name}=(val); @#{name}=val; end
"
end
end

trickier one:

class Cl
def initialize(name)
@name = name
class <<self
self
end.module_eval{attr_accessor name}
end
end

						matz.
···

In message “dynamic attr_accessor??” on 02/06/03, Markus Jais mjais@web.de writes:

thanks!
one more question.
what is the “self” between “class << self;” and “end.clas_eval…”
good for???
it does not work without it, but I do not understand how
this works.

markus

···

nobu.nokada@softhome.net wrote:

Hi,

At Mon, 3 Jun 2002 20:31:22 +0900, > Markus Jais wrote:

I like to create methods for my class dynamically based on
strings I pass to initialize

class Cl
def initialize(name)
class << self;self;end.class_eval {attr_accessor name}
end
end

thanks for your tip.

does one of the two possible solutions have any significant
advantages over the other or is this just a matter of style??

is one more like “the ruby way” ??

markus

Yukihiro Matsumoto wrote:

···

Hi,

In message “dynamic attr_accessor??” > on 02/06/03, Markus Jais mjais@web.de writes:

I like to create methods for my class dynamically based on
strings I pass to initialize

a) attr_accessor is a method of a class
b) attr_accessor takes names of accessors
c) attr_accessor just defines two methods

So the answer should be

easier one:

class Cl
def initialize(name)
@name = name
self.instance_eval "
def #{name}; @#{name}; end
def #{name}=(val); @#{name}=val; end
"
end
end

trickier one:

class Cl
def initialize(name)
@name = name
class <<self
self
end.module_eval{attr_accessor name}
end
end

matz.

Hallo,

I like to create methods for my class dynamically based on
strings I pass to initialize

class Cl
def initialize(name)
class << self;self;end.class_eval {attr_accessor name}
end
end

what is the “self” between “class << self;” and “end.clas_eval…”
good for???

just a wild guess by a newbie:

“class<<self; def …; end” would perform the method def of the
class of the object in question (and it would add a method to it).
(This is probably not exactly true, since “def” probably isn’t real
method, but it wouldn’t matter at the moment.)

So between “class<<self” and “end” you speak to the sigleton class of
the object (and perhaps you create it if it doesn’t exist yet).

Thus “class<<self;self;end” tells the singleton class to return itself.

HTH,
Stepan

···

On Mon, 03 Jun 2002 14:26:54 +0200, Markus Jais mjais@web.de wrote:

nobu.nokada@softhome.net wrote:

At Mon, 3 Jun 2002 20:31:22 +0900, Markus Jais wrote:

I personally prefer the non-eval way that Guy Decoux recommend of using
type.send. Try and not use eval whenever you can IMO - plus I think the
clarity is enhanced in many non-eval solutions.

irb(main):019:0> class A
irb(main):020:1> def initialize(name)
irb(main):021:2> @name = name
irb(main):022:2> type.send(:attr_accessor, “name”)
irb(main):023:2> end
irb(main):024:1> end
nil
irb(main):025:0> a = A.new(‘billy’)
#<A:0x404f4318 @name=“billy”>
irb(main):026:0> a.name
“billy”
irb(main):027:0> a.name = ‘Freddy’
“Freddy”
irb(main):028:0> a.inspect
“#<A:0x404f4318 @name="Freddy">”

···

On Tue, 04 Jun 2002 02:58, you wrote:

thanks for your tip.

does one of the two possible solutions have any significant
advantages over the other or is this just a matter of style??

is one more like “the ruby way” ??

markus

Yukihiro Matsumoto wrote:

Hi,

In message “dynamic attr_accessor??” > > > > on 02/06/03, Markus Jais mjais@web.de writes:

I like to create methods for my class dynamically based on
strings I pass to initialize

a) attr_accessor is a method of a class
b) attr_accessor takes names of accessors
c) attr_accessor just defines two methods

So the answer should be

easier one:

class Cl
def initialize(name)
@name = name
self.instance_eval "
def #{name}; @#{name}; end
def #{name}=(val); @#{name}=val; end
"
end
end

trickier one:

class Cl
def initialize(name)
@name = name
class <<self
self
end.module_eval{attr_accessor name}
end
end

matz.


Signed,
Holden Glova

Hi,

···

At Mon, 3 Jun 2002 22:38:04 +0900, Stepan Kasal wrote:

“class<<self; def …; end” would perform the method def of the
class of the object in question (and it would add a method to it).
(This is probably not exactly true, since “def” probably isn’t real
method, but it wouldn’t matter at the moment.)

So between “class<<self” and “end” you speak to the sigleton class of
the object (and perhaps you create it if it doesn’t exist yet).

Thus “class<<self;self;end” tells the singleton class to return itself.

That’s right, thank you.

And a singleton method of the object is defined in the
singleton class context by class_eval.


Nobu Nakada

“Holden Glova” dsafari@xtra.co.nz wrote in

I personally prefer the non-eval way that Guy Decoux recommend of using
type.send. Try and not use eval whenever you can IMO - plus I think
the
clarity is enhanced in many non-eval solutions.

The ``type’’ solution defines new A instances methods wether you use
class_eval or send -

irb(main):019:0> class A
irb(main):020:1> def initialize(name)
irb(main):021:2> @name = name
irb(main):022:2> type.send(:attr_accessor, “name”)

class << self; self end.send(:attr_accessor, name)

irb(main):023:2> end

/Christoph

Hi,

nobu.nokada@softhome.net nobu.nokada@softhome.net writes:

:> Thus “class<<self;self;end” tells the singleton class to return itself.
:
:That’s right, thank you.
:
:And a singleton method of the object is defined in the
:singleton class context by class_eval.

“class<<self;self;end” is equivalent to “self.type”.
And “self.type” is equivalent to “type”.

class Cl
def initialize(name)
type.class_eval {attr_accessor, name}
end
end

···


eban

I don’t understand, can you please explain?

···

On Wed, 05 Jun 2002 01:19, you wrote:

“Holden Glova” dsafari@xtra.co.nz wrote in

I personally prefer the non-eval way that Guy Decoux recommend of using
type.send. Try and not use eval whenever you can IMO - plus I think

the

clarity is enhanced in many non-eval solutions.

The ``type’’ solution defines new A instances methods wether you use
class_eval or send -

irb(main):019:0> class A
irb(main):020:1> def initialize(name)
irb(main):021:2> @name = name
irb(main):022:2> type.send(:attr_accessor, “name”)

class << self; self end.send(:attr_accessor, name)

irb(main):023:2> end

/Christoph


Signed,
Holden Glova

Hi,

···

At Tue, 4 Jun 2002 01:17:22 +0900, WATANABE Hirofumi wrote:

“class<<self;self;end” is equivalent to “self.type”.
And “self.type” is equivalent to “type”.

class Cl
def initialize(name)
type.class_eval {attr_accessor, name}
end
end

Once make an accessor, all instances come to have it. Does he
intend it?


Nobu Nakada

“Holden Glova” dsafari@xtra.co.nz wrote in

I don’t understand, can you please explain?

Well assuming

···

class A
def initialize(name)
type.send(:attr_accessor,name)
send(“#{name}=”,name)
end
end

mamas = A.new(‘cat’)
papas = A.new(‘dog’)

p papas.dog # => nil
p mamas.cat # => nil

since cat and dog are A instance methods


on the other hand

class A
def initialize(name)
class << self; self end.send(:attr_accessor,name)
send(“#{name}=”, name)
end
end

mamas = A.new(‘cat’)
papas = A.new(‘dog’)

p papas.dog #
p mamas.cat #

both raise a non-method errors since cat and dog are

singleton methods of mama and papa respectively.


Thus, as in the class_eval'' situation (see Nabu's comments in another branch of the thread) , you have two semantically different send’’ solutions …

/Christoph

“Christoph” chr_news@gmx.net wrote in
Blush;-)

class A
def initialize(name)
type.send(:attr_accessor,name)
send(“#{name}=”,name)
end
end

mamas = A.new(‘cat’)
papas = A.new(‘dog’)

p papas.dog # => nil
p mamas.cat # => nil

p papas.cat # => nil
p mamas.dog # => nil

class A
def initialize(name)
class << self; self end.send(:attr_accessor,name)
send(“#{name}=”, name)
end
end

mamas = A.new(‘cat’)
papas = A.new(‘dog’)

p papas.cat #
p mamas.cat #

both raise a non-method error since cat and dog are

singleton methods of mama and papa respectively.


/Christoph

Hallo,

class A
def initialize(name)
type.send(:attr_accessor,name)
send(“#{name}=”,name)
end
end

mamas = A.new(‘cat’)
papas = A.new(‘dog’)

p papas.cat # => nil
p mamas.dog # => nil

class A
def initialize(name)
class << self; self end.send(:attr_accessor,name)
send(“#{name}=”, name)
end
end

mamas = A.new(‘cat’)
papas = A.new(‘dog’)

p papas.cat #
p mamas.cat #

both raise a non-method error since cat and dog are

singleton methods of mama and papa respectively.

mamas.cat returns “cat” while mamas.dog raises a non-method error.

But I have to admit that this approximation was much better than
the previous one! :wink:

It probably wasn’t deliberate but it was very good paedagogically.
You mail made me to actually try these examples :slight_smile:

Thank you for lovely example.

Stepan

···

On Thu, 6 Jun 2002 13:57:14 +0200, Christoph chr_news@gmx.net wrote: