Dynamic methods / accessors

F

Frodo Larik

Hi all,

I'm trying to setup some kind of dynamic method / accessor assignment to
objects. But I don't want the other objects from the same class to know
about "personal" methods. I'm just learning Ruby, so it could be I'm
missing some crucial knowledge.

For example:

class MyThing
def create_method(method)
# I found two things on internet which can acchieve this
# self.class.class_eval { attr_accessor method }
# AND
# self.class.send:)define_method, method, &block)
# but I'm not sure which is the best one to use, but I think
# I prefer the attr_accessor, because that's the functionality
# I need
end
end


# Create first object
a = MyThing.new
a.create_method('box') # Adds a method box to a
a.box = 'something inside'

# The nicest thing would be if I could do something like this:
a.create_method('box','some_value'), so a.box is populated with 'some value'


# Create second object
b = MyThing.new

# I don't want the following to happen
b.box = 'something other'

I don't want the method 'box' be available to b, only to a

How can I achieve this?

I saw it was possible to achieve this with something like this:

class YourThing < MyThing
# A placeholder class for the dynamic methods
end

but I don't know the name of the class on forehand, so if something like
this is possible:

class #{i_want_this_class} < MyThing
# A placeholder class for the dynamic methods
end

That would be nice.





Sincerely,

Frodo Larik
 
R

Robert Klemme

Frodo Larik said:
Hi all,

I'm trying to setup some kind of dynamic method / accessor assignment
to objects. But I don't want the other objects from the same class to
know about "personal" methods. I'm just learning Ruby, so it could be
I'm missing some crucial knowledge.

For example:

class MyThing
def create_method(method)
# I found two things on internet which can acchieve this
# self.class.class_eval { attr_accessor method }
# AND
# self.class.send:)define_method, method, &block)
# but I'm not sure which is the best one to use, but I think
# I prefer the attr_accessor, because that's the functionality
# I need
end
end


# Create first object
a = MyThing.new
a.create_method('box') # Adds a method box to a
a.box = 'something inside'

# The nicest thing would be if I could do something like this:
a.create_method('box','some_value'), so a.box is populated with 'some
value'

# Create second object
b = MyThing.new

# I don't want the following to happen
b.box = 'something other'

I don't want the method 'box' be available to b, only to a

How can I achieve this?
You need so called singleton methods. These are present in just a single
instance. You define them via the singleton class. (Disclaimer: there has
been some debate about the naming of these because "singleton" can be
misleading here, but AFAIK this is still the officiel term.) You access the
singleton class (a class that is associated with a single instance only)
like this

class <<some_instance
end

So you can do:

class MyThing
end
a = MyThing.new
class <<a
attr_accessor :box
end
a.box = 'something inside'

If you want to have it a bit more convenient you can pack this into a method
like this:

class MyThing
def add_attribute(name, val=nil)
class <<self;self;end.send( :attr_accessor, name )
self.send("#{name}=", val)
end
end
a = MyThing.new
a.add_attribute :foo, "hello"
a.foo # returns "hello"

Kind regards

robert
 
R

Robert Klemme

Robert Klemme said:
You need so called singleton methods. These are present in just a
single instance. You define them via the singleton class.
(Disclaimer: there has been some debate about the naming of these
because "singleton" can be misleading here, but AFAIK this is still
the officiel term.) You access the singleton class (a class that is
associated with a single instance only) like this

class <<some_instance
end

So you can do:

class MyThing
end
a = MyThing.new
class <<a
attr_accessor :box
end
a.box = 'something inside'

If you want to have it a bit more convenient you can pack this into a
method like this:

class MyThing
def add_attribute(name, val=nil)
class <<self;self;end.send( :attr_accessor, name )
self.send("#{name}=", val)
end
end
a = MyThing.new
a.add_attribute :foo, "hello"
a.foo # returns "hello"

Kind regards

robert

PS: There is also OpenStruct which adds methods on the fly. So you can
directly do

o = OpenStruct.new
o.bar = 10

Kind regards

robert
 

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

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top