Accessing Class Variables in mixed in define_method

J

Jamie Quint

I am using define_method inside a module to dynamically create a class
after the module is mixed in. The module is writing out class variables
for the class it is mixed into (yes I am aware that class variables are
generally frowned upon but they are necessary in this instance) and then
subsequently trying to access them through the method being created with
define_method.

The problem here is that define method is not able to access the class
variables through class_variable_get or through accessing them directly.
In the first case it fails because 'class_variable_get' is not a method
on the class (oMethodError: undefined method ‘class_variable_get’ for
#<Foo:0x100124638>) In the second instance it fails because it thinks
the class variable is uninitialized (NameError: uninitialized class
variable @@c in M)

It seems to be evaluating the '@@c' call in the context of the module
and the class_variable_get call in the context of the class in which
define_method is being called after it is mixed in. Does anyone know how
I can get at the class variable here in define_method? Sample code
below:

Best,
Jamie

module M
def cv(methodname)
if class_variable_defined?:)@@c)
classvar = class_variable_get:)@@c)
classvar[rand(10000)] = "random"
class_variable_set:)@cc,classvar)
else
class_variable_set:)@@c,{})
end
define_method(methodname.to_sym) do
# need to be able to get class variables for this class
# @@c does not work because it tries to get the variable for the
module and it exists only in the class
#class_variable_get:)@@c) #does not work because its an invalid
class method
#@cc and class_variable_get:)@@c) are getting evaluated in
different contexts which is strange
end
end
end

class Foo
extend M
cv("mfoo")
end

f = Foo.new
f.mfoo # want this to be able to access and operate on class variables
 
J

Jesús Gabriel y Galán

I am using define_method inside a module to dynamically create a class
after the module is mixed in. The module is writing out class variables
for the class it is mixed into (yes I am aware that class variables are
generally frowned upon but they are necessary in this instance) and then
subsequently trying to access them through the method being created with
define_method.

The problem here is that define method is not able to access the class
variables through class_variable_get or through accessing them directly.
In the first case it fails because 'class_variable_get' is not a method
on the class (oMethodError: undefined method =91class_variable_get=92 for
#<Foo:0x100124638>) In the second instance it fails because it thinks
the class variable is uninitialized (NameError: uninitialized class
variable @@c in M)

It seems to be evaluating the '@@c' call in the context of the module
and the class_variable_get call in the context of the class in which
define_method is being called after it is mixed in. Does anyone know how
I can get at the class variable here in define_method? Sample code
below:

Best,
Jamie

module M
=A0def cv(methodname)
=A0 =A0if class_variable_defined?:)@@c)
=A0 =A0 =A0classvar =3D class_variable_get:)@@c)
=A0 =A0 =A0classvar[rand(10000)] =3D "random"
=A0 =A0 =A0class_variable_set:)@cc,classvar)

There's a typo here: it should be :mad:@c

This "works" for me:

module M
def cv(methodname)
if class_variable_defined?:)@@c)
classvar =3D class_variable_get:)@@c)
classvar[rand(10000)] =3D "random"
class_variable_set:)@@c,classvar)
else
class_variable_set:)@@c,{})
end
define_method(methodname.to_sym) do
self.class.send:)class_variable_get,:mad:@c)
end
end
end

class Foo
extend M
cv("mfoo")
end

I say "works" because the first time, @@c is initialized to {} but no
value is set. You need to call cv again inside class Foo in order to
create a value in the hash:

irb(main):021:0* f =3D Foo.new
=3D> #<Foo:0xb74aeb30>
irb(main):022:0> f.mfoo
=3D> {}

if you call it again:

irb(main):024:0> class Foo
irb(main):025:1> cv("mfoo")
irb(main):026:1> end
=3D> #<Proc:0xb74bb8d0@(irb):10>
irb(main):027:0> f.mfoo
=3D> {9035=3D>"random"}

Then it creates an entry in the hash, and then accessing it through
mfoo retrieves it.

Hope this helps,

Jesus.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top