Skip to content

Instantly share code, notes, and snippets.

@ericallam
Created September 12, 2011 23:13
Show Gist options
  • Save ericallam/1212735 to your computer and use it in GitHub Desktop.
Save ericallam/1212735 to your computer and use it in GitHub Desktop.
Using module_function instead of extend self
# a lot of people in ruby do this
module Foo
extend self
def bar
'bar'
end
end
Foo.bar
# => 'bar'
class Baz; include Foo; end
Baz.new.bar
# => 'bar'
# but what they really should be doing is this:
module Foo
def bar
'bar'
end
module_function :bar
end
Foo.bar
# => 'bar'
class Baz; include Foo; end
Baz.new.bar
# => 'bar'
@FlowerWrong
Copy link

ruby version 2.1.5, just focus the last line. It cause NoMethodError.

# a lot of people in ruby do this
module Foo
  extend self
  def bar
    'bar'
  end
end

puts Foo.bar # => 'bar'
class Baz; include Foo; end
puts Baz.new.bar # => 'bar'

# but what they really should be doing is this:
module Foo
  def bar
    'bar'
  end
  module_function :bar
end

puts Foo.bar # => 'bar'
class Baz; include Foo; end
puts Baz.new.bar # => private method `bar' called for #<Baz:0x00000001032ae0> (NoMethodError)

@yesnik
Copy link

yesnik commented Feb 6, 2017

Thank you for this example.
Also notice than it's important to place module_function :method_name after method definition:

module World
  module_function :hello
  def hello
    'Hey!'
  end
end

# You'll see error: NameError: undefined method `hello' for module `World'
# from (pry):8:in `module_function'

And it works:

module World
  def hello
    'Hey!'
  end
  module_function :hello
end

World.hello
# => 'Hey!'

By the way, we can omit passing argument to module_function. It works too:

module World
  module_function
  def hello
    'Hey!'
  end
end

World.hello
# => 'Hey!'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment