Ruby: extend self

Ruby

Ruby Problem Overview


In Ruby, I understand the basic idea of extend. However, what's happening in this segment of code? Specifically, what does extend do? Is it just a convenient way of making the instance methods into class methods? Why would you do it this way rather than specifying class methods from the beginning?

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

  # what does the next line do?
  extend self
end

Ruby Solutions


Solution 1 - Ruby

It is a convenient way to make instance methods into class methods. But you can also use it as a more efficient singleton.

Solution 2 - Ruby

In a module, self is the module class itself. So for example

puts self

will return Rake so,

extend self

basically makes the instance methods defined in Rake available to it, so you can do

Rake.run_tests

Solution 3 - Ruby

For me it always helps to think of extend as include inside the singleton class (also known as meta or eigen class).

You probably know that methods defined inside the singleton class are basically class methods:

module A
  class << self
    def x
      puts 'x'
    end
  end
end

A.x #=> 'x'

Now that we know that, extend will include the methods in the module inside the singleton class and thus expose them as class methods:

module A
  class << self
    include A

    def x
      puts 'x'
    end
  end

  def y
    puts 'y'
  end
end

A.x #=> 'x'
A.y #=> 'y'

Solution 4 - Ruby

To avoid link rot, the blog post of Chris Wanstrath linked by user83510 is reposted below (with his permission). Still, nothing beats an original, so use his link for as long as it continues to work.


→ singin' singletons 18 November 2008 There’s stuff I just don’t understand. David Bowie, for instance. Or the Southern Hemisphere. But nothing quite boggles my mind like Ruby’s Singleton. Because really, it’s totally unnecessary.

Here’s what they want you to do with your code:

require 'net/http'

# first you setup your singleton
class Cheat
  include Singleton

  def initialize
    @host = 'http://cheat.errtheblog.com/'
    @http = Net::HTTP.start(URI.parse(@host).host)
  end


  def sheet(name)
    @http.get("/s/#{name}").body
  end
end

# then you use it
Cheat.instance.sheet 'migrations'
Cheat.instance.sheet 'yahoo_ceo'

But that’s crazy. Fight the power.

require 'net/http'

# here's how we roll
module Cheat
  extend self

  def host
    @host ||= 'http://cheat.errtheblog.com/'
  end

  def http
    @http ||= Net::HTTP.start(URI.parse(host).host)
  end

  def sheet(name)
    http.get("/s/#{name}").body
  end
end

# then you use it
Cheat.sheet 'migrations'
Cheat.sheet 'singletons'

Any why not? The API is more concise, the code is easier to test, mock, and stub, and it’s still dead simple to convert into a proper class should the need arise.

(( copyright ought ten chris wanstrath ))

Solution 5 - Ruby

extend self includes all the existing instance methods as module methods. This is equivalent to saying extend Rake. Also Rake is an object of class Module.

Another way to achieve equivalent behavior will be:

module Rake
  include Test::Unit::Assertions

  def run_tests # etc.
  end

end 

Rake.extend(Rake)

This can be used to define self contained modules with private methods.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPeterView Question on Stackoverflow
Solution 1 - RubycldwalkerView Answer on Stackoverflow
Solution 2 - RubyennuikillerView Answer on Stackoverflow
Solution 3 - RubyfphilipeView Answer on Stackoverflow
Solution 4 - RubyforforfView Answer on Stackoverflow
Solution 5 - RubySulabh JainView Answer on Stackoverflow