Skip to content

Instantly share code, notes, and snippets.

@xpepper
Last active December 16, 2015 05:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xpepper/5387650 to your computer and use it in GitHub Desktop.
Save xpepper/5387650 to your computer and use it in GitHub Desktop.

Ruby #4.

class_eval vs. instance_eval

Module#class_eval:

  1. set self to the receiver for the duration of the block
  2. set the current class to class/module which is the receiver
  3. can be called only on classes and modules
  • => it's like re-opening the class/module
  • => the scope of the block is that class
  • => the methods defined in the block go directly in that class, so they become instance methods of that class (or module)

Object#instance_eval

  1. set self to the receiver
  2. set the current class to the singleton class of the receiver
  3. can be called on any object
  • => the scope of the block is the instance itself
  • => the methods defined in the block becomes singleton methods of the instance object (in case of classes, they become so-called "class-level methods")
  • => DSLs in a block: execute a block in the context of an object

Passing a string to eval instead of a block can avoid the closure and the memory footprint of all the captured bindings

Ruby #6.

Modules in Ruby are just objects (instance of class "Module"): there's no surprise here, since everything in Ruby is an object. But modules differ from classes, in that a class (instance of class "Class") is a specialized version of a module (someone would say "a subtype") which can instantiate objects (through Class#new method) and can have a parent superclass (Class#superclass).

So if I'd like to add or modify methods on all modules, what I have to do is re-open the Module class:

class Module
  def included(mod)
    puts "I'm re-writing a default implementation of Module#included hook method!"
  end
end

But you know what? Module is a class too! Don't belive to me? Ask to Ruby:

Module.is_a? Class 
# => true

Why that? Because Module is an object, so it has a class. And what is Module's class? The class Class:

Module.class 
# => Class

Ok, so Module is an instance of class Class, so it's lookup path will go "one to the right" in its class, Class, than up through Module, Object and so on... Here you have the lookup path (which includes also singleton classes, between squared brackets):

BasicObject
Kernel
Object
Module
Class
[BasicObject]
[Object]
[Module]

which means that while going up in the lookup chain, Module will pass through its instance methods! The same is true for Class, and this is simply because a Class is at the same time an object and a class.

How can you tell a module from Module?

Well, every module is an instance of Module, created with the "module <module_name>" syntax or with Module.new, while Module is a class (actually the superclass of Class).

1.9.3p385 :026 > Module.is_a? Class
 => true
 
 1.9.3p385 :005 > Math.is_a? Class
 => false

By the way, this is the official definition of Module (http://www.ruby-doc.org/core-2.0/Module.html):

A Module is a collection of methods and constants. The methods in a module may be instance methods or module methods. Instance methods appear as methods in a class when the module is included, module methods do not. Conversely, module methods may be called without creating an encapsulating object, while instance methods may not. (See Module#module_function)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment