If you have been hacking ruby for a while you should have heard that “Everything is an object”. To understand this concept knowing what a singleton class is important. Yehuda Katz’s post is a good source for it.
My ruby version 1.9.2.
$ ruby -v | |
ruby 1.9.2p136 (2010-12-25 revision 30365) [i686-linux] |
First I’m going to show you how to add methods to instances by using define_method
.
class Message | |
[:hello, :goodbye].each do |method_name| | |
define_method method_name do |arg| | |
"#{method_name} #{arg}" | |
end | |
end | |
end | |
#irb | |
Message.instance_methods false #=> [:hello, :goodbye] | |
Message.new.hello 'emre' #=> "hello emre" | |
Message.new.goodbye 'emre' #=> "goodbye emre" |
You can also write an instance method to create instance methods. send
must be used because define_method
is private.
class Message | |
def create_instance_methods *methods | |
methods.each do |method_name| | |
self.class.send :define_method, method_name do |arg| | |
"#{method_name} #{arg}" | |
end | |
end | |
end | |
end | |
#irb | |
Message.instance_methods false #=> [:create_instance_methods] | |
Message.new.create_instance_methods 'fork' #=> ["fork"] | |
Message.instance_methods false #=> [:create_instance_methods, :fork] | |
Message.new.fork 'emre' #=> "fork emre" |
Write a singleton method to create instance methods.
class Message | |
def self.create_instance_methods *methods | |
methods.each do |method_name| | |
define_method method_name do |arg| | |
"#{method_name} #{arg}" | |
end | |
end | |
end | |
end | |
#irb | |
Message.singleton_methods #=> [:create_instance_methods] | |
Message.create_instance_methods 'follow' #=> ["follow"] | |
Message.instance_methods false #=> [:follow] | |
Message.new.follow 'emre' #=> "follow emre" |
Now it is time to add singleton methods. When we call define_method
, it creates an instance method. What we have to do is call define_method
on class’ singleton class.
Getting singleton class of a class:
#ruby 1.9.2 | |
class Message | |
end | |
#irb | |
Message.singleton_class #=> #<Class:Message> | |
#ruby 1.8.x | |
class Message | |
#define this method to get singleton class | |
def self.singleton_class | |
class << self | |
self | |
end | |
end | |
end | |
#irb | |
Message.singleton_class #=> #<Class:Message> |
First defining singleton method to create singleton methods.
class Message | |
def self.create_singleton_methods *methods | |
methods.each do |method_name| | |
singleton_class.send :define_method, method_name do |arg| | |
"#{method_name} #{arg}" | |
end | |
end | |
end | |
end | |
#irb | |
Message.singleton_methods false #=> [:create_singleton_methods] | |
Message.create_singleton_methods 'like' #=> ["like"] | |
Message.singleton_methods false #=> [:create_singleton_methods, :like] | |
Message.like 'emre' #=> "like emre" |
Then defining instance method to create singleton methods.
class Message | |
def create_singleton_methods *methods | |
methods.each do |method_name| | |
self.class.singleton_class.send :define_method, method_name do |arg| | |
"#{method_name} #{arg}" | |
end | |
end | |
end | |
end | |
#irb | |
Message.instance_methods false #=> [:create_singleton_methods] | |
Message.new.create_singleton_methods 'poke' #=> ["poke"] | |
Message.singleton_methods false #=> [:poke] | |
Message.poke 'emre' #=> "poke emre" |