If you are here, then most probably you want to know more about ruby reflection interface. Well that’s true, but I always find myself in need to explain few things before I get started with my posts, and this time I find myself in need of explaining few things related to ruby’s OOP.
I’m pretty sure that you always heard that “in ruby: everything is an object.” , but have you ever thought of that carefully?
The first thing that comes to a one’s mind is something like :
5.class #=> Fixnum "hello".class #=> String
But have you thought of your class as an object? Well that seems odd, but that’s how ruby works:
class Foo;end #=> nil Foo.class #=> Class
What does the above snippet of code mean exactly?
It means 2 things : Foo is a constant and that constant holds(refers to) an object of Class type.
Let me prove that 2 you:
Foo = Class.new (irb):8 warning: already initialized constant Foo => Foo
As you can see, I got a warning because I tried to initialize the constant Foo again.
So ,when you define some class ‘Foo’ in ruby, all you are doing is:
1-instantiating an object of type Class.
2-initializing a constant Foo that refers to that created object .
So bear in mind that when I say “object” ,then I do mean any object; an object of Class type, or any object of any type.
Now, let’s move to another point. What about the ‘Singleton Class’, did you have the chance to work with it before?
Simply it’s the class that holds all singleton methods of an object, whether it’s a class object , or any other object.
Let’s start by defining 2 class methods (a class method is nothing but: a singleton method of an object of Class type) :
class Foo def self.hi ; p "hi" ;end def self.bye ; p "bye" ; end end Foo.singleton_methods #=> ["hi","bye"]
You could also have written that in this way:
class Foo class << self def hi ; p "hi" ; end def bye ; p "bye" ; end end end Foo.singleton_methods #=> ["hi","bye"]
The above inner class mentioned with “class << self" is what we call : a singleton class.
Let's define a method that returns back the singleton class for us :
class Object def singleton_class class << self self end end end
Now try this :
Foo.singleton_methods #=> ["bye", "hi"] Foo.singleton_class.instance_methods(false) #=> ["bye", "hi"]
As you can see, the singleton class is the class that holds all singleton methods.
We will use the singleton class later in this series, so keep the concept in mind.
Let’s now get back to our topic on ruby’s reflection api , i will introduce 3 methods in this post: eval , instance_eval and class_eval.
eval
‘eval’ is a method that evaluates a ruby string :
eval "3+4" #=> 7 eval "def multiply(x,y) ; x*y; end" multiply(4,7) #=> 28
eval can also work in the scope of bindings ; a binding is an object that encapsulates the execution context at some particular place in the code and retain this context for future use. Look at this example of using bindings with eval :
class Demo def initialize(n) @secret = n end def getBinding return binding()# a method defined in Kernel module end end k1 = Demo.new(99) #get the value of the instance variable @secrete stored in the binding of object k1 eval("@secret", k1.getBinding) #=> 99
Also can work with proc objects :
def greeting(name) lambda{|greetings| greetings.collect {|g| "#{g} #{name}"} } end greeter = greeting("dude") #=> #<Proc:0xb752b810@(irb):2> greeter.call ["hi","hello","hola"] #=> ["hi dude", "hello dude", "hola dude"] eval("name='khelll'",greeter) #=> "khelll" greeter.call ["hi","hello","hola"] #=> ["hi khelll", "hello khelll", "hola khelll"]
instance_eval
This method works in the context of the object :
class Klass def initialize @secret = 99 end end k = Klass.new k.instance_eval { @secret } #=> 99 , notice the @
And could be used to define singleton methods :
Fixnum.instance_eval "def zero; 0 ;end" Fixnum.zero #=> 0
you can pass it a block instead of the string :
Fixnum.instance_eval{ def ten ;10;end } Fixnum.ten #=> 10
class_eval
Evaluates a string or a block in the context of the receiver
Foo.class_eval{@@x=1} #=> 1 Foo.class_eval{@@x} #=> 1
And it defines instance methods when called on some object
Fixnum.class_eval "def number ; self ;end" 5.number #=> 5
And as instance_eval, a block instead of the string could be passed
Fixnum.class_eval{ def number;self;end} 7.number #=> 7
You can use class_eval to dynamically use private methods, for example to use the private method ‘include’:
module M; end String.include M #=> NoMethodError: private method `include' called for String:Class String.class_eval{include M} #=> you could do it with String.send(:include,M)
Now let’s make use of our knowledge,let’s try to redefine the attr_accessor method in our way, I will make a similar method called attr_access :
class Class def attr_access(*attrs) attrs.each do |attr| class_eval %Q{ def #{attr} @#{attr} end def #{attr}=(value) @#{attr} = value end } end end end class Foo attr_access :a,:b end Foo.instance_methods(false) #=> ["b=", "a=", "b", "a"]
in a similar way we can define class attribute accessors :
class Class def cattr_access(*attrs) attrs.each do |attr| class_eval %Q{ def self.#{attr} @@#{attr} end def self.#{attr}=(value) @@#{attr} = value end } end end end
Or with we can use the singleton class :
class Class def singleton_class class << self self end end def cattr_access(*attrs) attrs.each do |attr| singleton_class.class_eval %Q{ def #{attr} @@#{attr} end def #{attr}=(value) @@#{attr} = value end } end end end
And in both cases we can do :
class Foo ; cattr_access :cx,:cy end Foo.singleton_methods(false) #=> ["cy", "cy=", "cx", "cx="]
Give it a try and try to define attr_reader and attr_writer for both object and class variables.
I think it’s enough for this post, the next post will contain more methods to look at. See you then.
Update 1: fixing some typos.
Update 2: second part is here.


Thanks! Nice Post.
Pingback: 7 Ruby Articles to Read Over The Holiday Season
Small typo defining multiply:
eval "def mulitply(x,y) ; x*y; end"
Pingback: Ruby reflection 2 - Khaled alHabache’s official blog
@Len Lattanzi
Fixed, thanks for notifying me….
Excellent tutorial, something solid to start ruby’s reflection.
Pingback: روابـــ(2)ــط « Mutati0N
Pingback: Fun with Ruby’s instance_eval and class_eval « I like stuff
Pingback: Undefining class at runtime « My explorations in rails
Wonderful article. Made the world of eval very friendly to me.
Pingback: Python vs Ruby, slighty more in-depth « Rudimentary Art of Programming & Development
Good article. I do think it would be clearer linguistically if you said “…..an object of type Class” instead of “…an object of Class type” !
For completeness it might be helpful to mention that the last example could as well be implemented using instance_eval instead of singleton_class.class_eval.
awesome – thanks
Nice Article.Help me to clear what exactly eval,class_eval and instace_eval methods
Thanks Buddy
I had a question on Reflection. Assuming that I have an ActiveRecord object (Post). I know as an object we can do Post.find_by , Post.where . Can we do something like
s= “Post”
s.find_by
s.where