Ruby: module, require and include

RubyModuleMixins

Ruby Problem Overview


I'm trying to use Ruby modules (mixins).

I have test.rb:

#!/usr/bin/env ruby
require_relative 'lib/mymodule'

class MyApp
  include MyModule
  self.hallo
end

and lib/mymodule.rb:

module MyModule
  def hallo
    puts "hallo"
  end
end

Quite simple setup. But it does not work :( :

ruby test.rb
test.rb:8:in `<class:MyApp>': undefined method `hallo' for MyApp:Class (NoMethodError)
        from test.rb:6:in `<main>'

Where is my error?

Ruby Solutions


Solution 1 - Ruby

In short: you need to extend instead of include the module.

class MyApp
  extend MyModule
  self.hallo
end

include provides instance methods for the class that mixes it in.

extend provides class methods for the class that mixes it in.

Give this a read.

Solution 2 - Ruby

The issue is that you are calling hallo in the class definition, while you add it as an instance method (include).

So you could either use extend (hallo would become a class method):

module MyModule
  def hallo
    puts "hallo"
  end
end

class MyApp
  extend MyModule
  self.hallo
end

Or either call hallo in an instance of MyApp:

module MyModule
  def hallo
    puts "hallo"
  end
end

class MyApp
  include MyModule
end

an_instance = MyApp.new
an_instance.hallo

Solution 3 - Ruby

Your code is working - but including a module does not do what you think it does. The class including the module will not get the methods - the objects from this class will.

So this will work :

class MyApp
  include MyModule
end

my_app_object = MyApp.new
my_app_object.hallo # => hallo

my_app_object is an object of class MyApp, which has a mixins of module MyModule. Take a look there for a complete explanation of modules and mixins.

Solution 4 - Ruby

class MyApp
  class << self
    include MyModule
  end
  self.hallo
end

is the same as

class MyApp
  extend MyModule
  self.hallo
end

extends just opens the class object and include the module methods. "hallo" becomes a class object aka. static method of class MyApp.

So "include" inject the methods to the instances of the receiver, in your case being "self" NOT to the object itself. "extend" inject the methods to the receiver in your case being "self".

self.include MyModule // inject the methods into the instances of self
self.extend MyModule // inject the methods into object self

At class level "self" will point to your class object which is MyApp.

Also remember that "include" and "extend" are just methods defined in module.rb. "include" is a class object method (static-method) and "extend" is an instance method.

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
QuestionDakkarView Question on Stackoverflow
Solution 1 - RubyKyleView Answer on Stackoverflow
Solution 2 - RubyCCDView Answer on Stackoverflow
Solution 3 - RubyMartinView Answer on Stackoverflow
Solution 4 - RubyViorelView Answer on Stackoverflow