The Difference Between include and extend in Ruby

Written by on Aug 2 2012

To illustrate the difference I’m going to use a simple example of trying to get a Logger module into a class for use in the class.

Example 1 demonstrates  include :

module Logger
  def log str
    p str
  end  
end

class Thing1
  include Logger

  begin
    log "this doesn't work from class"
  rescue Exception => e
    p e                           # => #<NoMethodError: undefined method `log' for Thing1:Class>
  end

  def test_log
    log "this does work from instance"
  end
end


Thing1.new.test_log               # => "this does work from instance"
begin
  Thing1.log "this doesn't work from class again"
rescue Exception => e
  p e                             # => #<NoMethodError: undefined method `log' for Thing1:Class>
end

When you use  include , the module’s methods are added to the  instances  of the class. The log method is:

  1. Not available at the class level
  2. Available at the instance level
  3. Not available at the class level again

Example 2 demonstrates extend :

module Logger
  def log str
    p str
  end  
end

class Thing2
  extend Logger

  log "this does work from class"   # => "this does work from class"

  def test_log
    begin
      log "this doesn't work from instance"
    rescue Exception => e
      p e                           
    end
    Thing2.log "this does work from class (via class in instance)"
  end
end

Thing2.new.test_log                 # => #<NoMethodError: undefined method `log' for #<Thing2:0x007fcb391016a0>>
                                    # => "this does work from class (via class in instance)"

When you use extend , the module’s methods are added to the class itself. The log method is:

  1. Available at the class level.
  2. Not available at the instance level.
  3. Available at the class level.

Example 3 demonstrates using both include and extend :

module Logger
  def log str
    p str
  end  
end

class Thing3
  include Logger
  extend Logger

  log "this does work from class"   # => "this does work from class"

  def test_log
    log "this does work from instance"
    Thing3.log "this does work from class (via class in instance)"
  end
end

Thing3.new.test_log                 # => "this does work from instance"
                                    # => "this does work from class (via class in instance)"

When you use both, the module’s methods are added twice, both to the class and to the instances, so they are available anywhere.

You don’t really want to do it this way. Not because it’s bad, if you want the methods available to both you have to either add them to both or have the instance methods call the class methods, which is basically the same thing. So the reason you don’t want to both include and extend is because your friends will think you rubyfu is weak. In an upcoming post I’ll show you how to master this, so you can be strong.

Meet
Steven

Hi I'm Steven,

I wrote the article you're reading... I lead the developers, write music, used to race motorcycles, and help clients find the right features to build on their product.

Get Blog Updates