Ruby metaprogramming: instance_eval and class_eval - ruby

Seems I am confused between the two methods though I have been using them for a while, I can't understand why the method passengers is not being added to the object in the following code:
class Bus
def number_of_seats
42
end
end
Bus.class_eval do
define_method :number_of_windows do
number_of_seats
end
def fuel_type
:diesel
end
end
Bus.instance_eval do
define_method :destination do
'Paris'
end
def passengers
12
end
end
bus = Bus.new
bus.number_of_windows # => 42
bus.fuel_type # => :diesel
bus.destination # => "Paris"
bus.passengers # => undefined method `passengers' (NoMethodError)
Notes:
Tried instance_eval first, just randomly used class_eval and then it too seemed to work!
My understanding of instance_eval's block: The code in the block is run with self set to the object calling instance_eval.
My understanding of class_eval's block: The code in the block is evaluated as if its placed by opening the class of the object calling it. Hence I am puzzled at the class_eval in the above case! I was expecting class_eval on Bus would mean evaluating the block in the class of Bus Class.

You can refer this awesome article on class and instance_eval as to why passengers is not being added to the object.
TL;DR:
Bus.class_eval will create instance methods and Bus.instance_eval will create class methods.
Now, regarding the behavior of destination(which could be called on instance).....define method when used inside either class_eval or instance_eval is immune to the usual behaviour. Why?.
Because the documentation says so. As per the documentation:
define method - Defines an instance method in the receiver.
Therefore, it does not matter if you use define_method inside class_eval or instance_eval it would always create an instance method.
Source for reference.
Hope this helped :-).

Basically you can't do an instance_eval on a class object when using def. Here's a general way you use instance_eval and class_eval. http://web.stanford.edu/~ouster/cgi-bin/cs142-winter15/classEval.php

Related

Understanding class_eval and instance_eval?

I'm confused as to when I should be using instance_eval and class eval.
I should or shouldn't use them?
Answer with simple examples on how to use them.
Thanks a lot.
The class_eval and instance_eval are both used to reopen an object and define additional behaviour.
They follows the open/closed principle.
class_eval
class_eval is used to define additional behaviour in the context of a class.
Let's use the following Person class:
class Person
def initialize(name)
#name = name
end
end
Person.class_eval do
def say_hello
puts "Hello! I'm #{#name}"
end
end
j = Person.new "John"
j.say_hello # Hello! I'm John
r = Person.new "Robert"
r.say_hello # Hello! I'm Robert
Both j and p can use a new method called say_hello that wasn't defined in the definition of the class Person, but on an extension of it.
instance_eval
instance_eval is used to define additional behavior in the context of a receiving object.
The previous example could be rewritten as:
class Person
def initialize(name)
#name = name
end
end
j = Person.new "John"
j.instance_eval do
def say_hello
puts "Hello! I'm #{#name}"
end
end
j.say_hello # Hello! I'm John
Since we used instance_eval on j, only the behavior of j has been redefined, in fact we can't use say_hello on another instance:
r = Person.new "Robert"
r.say_hello # undefined method `say_hello' for #<Person:0x00007fac43c15b28 #name="Robert"> (NoMethodError)
This is the opposite of class_eval.
Summary
class_eval allows you to open and redefine the behavior of a class in order to extend all instances of the class
instance_eval allows you to open and redefine the behavior of just an instance of a class
You should or shouldn't use them?
I'm of the idea that you shouldn't use them, because this can lead to code fragmentation.
But you have to use them when you want to add behavior on third parties code or when you want to add behavior dynamically.
Use ClassName.instance_eval to define a class method (one associated with the class object but not visible to instances).
Use ClassName.class_eval to define an instance method (one that applies to all of the instances of ClassName).
Source: RubyMonk
instance_eval
One of the major differences between eval and instance_eval is that
with instance_eval you have the choice of explicitly handling the
context of self. As instance_eval is a method on Object it is scoped
by the object you specify.
class_eval
class_eval is much simpler than instance_eval which works on
metaclasses (or the singleton object). It works on the class as if you
were opening it in a text editor and adding new state or behaviour to
it.

Why can some classes and/or methods be called without instances of their parent class?

I'm near the finish of the Ruby track in Code Academy, and I'm curious about a peculiar thing: I was under the impression that a class is a repository of constants, methods, etc... and that in order to access most of them, you would first need to create an instance of that class or in some cases the methods of themselves can be invoked (as in they are all technically part of the global object). And then I saw something like this:
#Worked
Time.now
I understood as this as the method [now] of instance of class [Time] being invoked. I then tried to invoke the method on its own:
#Failed
now
and that failed, and I assumed that while a method can be created in the general scope [as part of the global object], if it relies on initialized variables of "parent" class, it cannot be called on its own, because it would not know which object to search for those initialized variables. Following that I created a test class:
class Clock
def initialize
#hours = 1
#minutes = 30
end
def showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
#this worked
watch = Clock.new
watch.showTime
#this failed
showTime
I then just created a basic method (assuming it's in the global level)
def mymethod
puts "The mighty METHOD!"
end
#Works
mymethod
and calling this method the way I did, without referencing the global object worked. So... the questions I have are as follows:
How can [Time.now] be called in this fashion? Shouldn't there be an instance of Time first created?
Why can't I call the method [now] on its own? Am I right that it relies on resources that it cannot find when called this way?
Why could I not call the method showTime on its own? But if I define any method on the "global" level I can access it without referencing the global object
First of all, your intuition is correct.
Every methods must be an instance method of some receiver.
Global methods are defined as private instance methods on Object class and hence seem to be globally available. Why? From any context Object is always in the class hierarchy of self and hence private methods on Object are always callable without receiver.
def fuuuuuuuuuuun
end
Object.private_methods.include?(:fuuuuuuuuuuun)
# => true
Class methods are defined as instance methods on the "singleton class" of their class instance. Every object in Ruby has two classes, a "singleton class" with instance methods just for that one single object and a "normal class" with method for all objects of that class. Classes are no different, they are objects of the Class class and may have singleton methods.
class A
class << self # the singleton class
def example
end
end
end
A.singleton_class.instance_methods.include?(:example)
# => true
Alternative ways of defining class methods are
class A
def self.example
end
end
# or
def A.example
end
Fun fact, you can define singleton methods on any object (not just on class objects) using the same syntax def (receiver).(method name) as follows
str = "hello"
def str.square_size
size * size
end
str.square_size
# => 25
"any other string".square_size
# => raises NoMethodError
Some programming language history — Singleton classes are taken from the Smalltalk language where they are called "metaclasses". Basically all object-oriented features in Ruby (as well as the functional-style enumerators on Enumerable) are taken from the Smalltalk language. Smalltalk was an early class-based object-oriented language created in the 70ies. It was also the language that invented graphical user interfaces like overlapping windows and menus et cetera. If you love Ruby maybe also take a look at Smalltalk, you might fall in love yet again.
This is known as a class method. If CodeAcademy didn't cover it, that's a shame. Here's some examples:
# basic way
class Foo
def self.bar; :ok; end
end
Foo.bar # => :ok
# alternate syntax
class Foo
class << self
def bar; :ok; end
end
end
# alternate syntax, if Foo class already exists
def Foo.bar; :ok; end
# alternate approach if Foo class already exists
Foo.class_exec do
def bar; :ok; end
end
# to define a class method on an anonymous 'class' for a single instance
# you won't need to use this often
Foo.new.singleton_class.class_exec do
def bar; :ok; end
end
# to define a class method on an instance's actual class
Foo.new.class.class_exec do
def bar; :ok; end
end
Another way to get class methods is to extend a module.
module FooMethods
def bar; :ok; end
end
module Foo
extend FooMethods
end
Foo.bar # => :ok
Note that with Modules, the methods are always defined as instance methods. This way they can be either extended into class scope or included into instance scope. Modules can also have class methods, using the exact same syntax / examples as shown above with classes. However there's not such as easy to load a module's class methods via include or extend.
How can [Time.now] be called in this fashion? Shouldn't there be an
instance of Time first created?
The Time.now method is a class method, not an instance method and therefore can be called directly on the Time class rather than an instance of it Time.new
Class methods are defined on the class themselves using the self keyword:
class Time
def self.now
# code
end
end
Time.now # works
Why can't I call the method [now] on its own? Am I right that it
relies on resources that it cannot find when called this way?
When you call a method "on its own" you're actually implicitly calling it on self:
self.now
The above is the same as just doing:
now
Why could I not call the method showTime on its own? But if I define
any method on the "global" level I can access it without referencing
the global object
You defined the showTime method on a specific class so you have to send that method to that class. When you define a method in the "global" scope you're implicitly defining it on self and the subsequent call to mymethod is actually self.mymethod so it will work.
Time.now is a class method.
To define a class method, you need to define the method with self. : def self.method_name
class Clock
#hours = 1
#minutes = 30
def self.showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
Clock.showTime
#=> The time is: 1:30
If you want to call now on its own, you can do so inside Time class :
class Time
puts now
#=> 2017-01-19 22:17:29 +0100
end

Arguments to Class.new block

You can define classes as constants on Object, using the const_set method. Are there any interesting or instructive use cases where someone would pass arguments into the Class.new block?
Object.const_set(:Klass, Class.new do |can_i_use_this|
def ping
"pong"
end
end)
Klass.new.ping
Can you do anything with that?
It turns out that the block argument is the class you are creating. Run this snippet in irb
Class.new do |what|
p what
end
and you will see something like
#<Class:0x000000022b2698>
=> #<Class:0x000000022b2698>
The first line of output is given by p what, and the second line shows the return value of Class.new, which we know is the class. You can see that the what is the same object as the return value of Class.new.
Conclusion: the block argument is not very useful because you can get the class instance just using self in that class. The only usage I can imagine of is using the trick called flat scope to create methods.
Foo = Class.new do |klass|
define_method :class_name do
klass.name
end
end
Foo.new.class_name #=> "Foo"
Yet this is not very useful either because an object can easily access its class with self.class.

Ruby: difference between def and define_method

I'm learning ruby metaprogramming at the moment and while I was playing around and testing stuff, I stumbled upon something I can't seem to find the answer to. Let's say we have the following code:
class Foo
end
Foo.instance_eval do
define_method("bar") do
1
end
end
I would expect this to add a class method called bar to Foo but instead when I call the method it says it's undefined. What baffles me even more is that the same code works when I use def instead of define_method. Both ways seem to work when I try to define an instance method with class_eval as well. So what's really going on here?
Thanks in advance.
Let's make it simple.
define_method is a method. Or I should say a private class method of Object class. You invoke it by giving it an argument as instance method name you are going to define, and a block which contains the code of the method. apidock has very clear definition. You may want to read documentation.
def is a keyword. You use this to define methods just as you do all the time. Not really related to meta-programming.
If you are trying define class method, use class_eval, and give it a string. As its name indicates, instance_eval defines stuffs on instance level. In your code, if you do Foo.instance_methods, you will find the bar method. So if you do Foo.new.bar it returns 1, as TK-421 answered you. But since define_method defines instance_method, as indicated by documentation, regardless if you use class_eval or instance_eval, you will get instance method.
Here's the documentations you can read and they will answer all you question.
class_eval: http://apidock.com/ruby/v1_9_3_392/Module/class_eval
define_method: http://apidock.com/ruby/Module/define_method
instance_eval: http://apidock.com/ruby/Object/instance_eval
And don't forget this all mighty: http://www.google.com :D
Differences between def and define_method.
1:- define_method can use variables from the scope where it was defined.
local_var = "Hello World"
def greet1
local_var #undefined local_var
end
define_method(:greet2) do
local_var # returns local_var
end
2:- If you want to define method whose name is stored inside a variable, then you will have to use define_method. You can't declare methods dynamically using def.
So based on the requirement you will have to use def or define_method.
Explanation for your code.
Here you will have to use #define_singleton_method instead of #define_method to define class methods for Foo class. define_method will define instance methods for class Foo
So the expected code should be
class Foo
end
Foo.instance_eval do
define_singleton_method("bar") do
1
end
define_method("baz") do
2
end
end
Foo.bar #=> 1
Foo.new.baz #=> 2
It's an instance method. So:
f = Foo.new
f.bar # 1

Ruby's def and instance_eval vs. class_eval

I'm reading the Metaprogramming section of Programming Ruby 1.9 and I'm having trouble understanding what's going on internally between class_eval/class_exec vs. instance_eval/instance_exec.
So first of all, my understanding is that def adds a method to the method table of self (the class object):
class A
puts self # => A
def foo; 42; end # added to the method table of self, so becomes an instance method
end
A.new.foo # => 42
And if we use class_eval, we get the same behavior:
A.class_eval do
puts self # => A
def bar; 42; end # same as above
end
A.new.bar # => 42
But somehow in the instance_eval case, things are different:
A.instance_eval do
puts self # => A
def baz; 42; end # added to the method table of an anonymous
# singleton class of self, so becomes a class method
end
puts A.baz # => 42
s = 'string'
s.instance_eval do ... end # same behavior, so now def creates an instance method
So I understand the functional difference between class_eval and instance_eval.
But the contexts inside the class_eval and instance_eval blocks look exactly the same to me -- in particular, self points to the same object, and the local_variables are the same. So what's going on inside the blocks (internally) that's making def act different?
Is there some piece of documentation I could read? The RDoc for instance_eval and class_eval doesn't help. Looking at the source, instance_eval seems to set up a singleton class object whereas class_eval doesn't -- but is this difference visible outside the C code, on the Ruby level?
I think your confusion comes from the fact that def does not depend on the current self, you might think about it as being a "current class" that has it's own rules.
Following your examples:
class A
# defs here go to A
puts self # => A
class << self
#defs here go to A's eigenclass
end
end
A.class_eval do
#defs here go to A
end
A.instance_eval do
#defs here go to A's eigenclass
end
s = "Hello World"
class << s
#defs here go to s's eigenclass
end
Here's the portion of the chapter that talks about the issue and it's pretty clear about the behaviour
class_eval and instance_eval both set
self for the duration of the block.
However, they differ in the way they
set up the environment for method
definition. class_eval sets things up
as if you were in the body of a class
definition, so method definitions will
define instance methods In contrast,
calling instance_eval on a class acts
as if you were working inside the
singleton class of self. Therefore,
any methods you define will become
class methods.
The only thing I think is worth adding is that you can call instance_eval in any object, not just classes, and the behaviour doesn't change but has different consequences.
Some relevant reading:
Ruby: instance_eval and class_eval method definitions
Chapter 4 of this most excelent series
Just to add to #krusty.ar's answer: def and define_method add methods to the current method definition context (I believe that's what it's called, I'm not sure), not to the current self.
It's just that inside of a module, class or singleton class body, those two happen to be the same.
But, for example, in a script body (aka top-level), self is the main object, but the current method definition context is Object.

Resources