24

Consider the following code:

module ModName
  def aux
    puts 'aux'
  end
end

If we replace module with class, we can do the following:

ModName.new.aux

Modules cannot be instanced, though. Is there a way to call the aux method on the module?

kettlepot
  • 10,574
  • 28
  • 71
  • 100
freenight
  • 1,069
  • 3
  • 13
  • 19

6 Answers6

23

Think about what aux is. What object will respond to aux? It's an instance method, which means that instances of classes that include ModName will respond to it. The ModName module itself is not an instance of such a class. This would also not work if you had defined ModName as a class — you can't call an instance method without an instance.

Modules are very much like classes that can be mixed into other classes to add behavior. When a class mixes in a module, all of the module's instance methods become instance methods of the class. It's a way of implementing multiple inheritance.

They also serve as substitutes for namespaces, since each module defines a namespace. But that's somewhat unrelated. (Incidentally, classes also have their own namespaces, but making it a class implies that you'll create instances of it, so they're conceptually wrong for that purpose.)

Chuck
  • 234,037
  • 30
  • 302
  • 389
  • 2
    One real-world use case for this is with Sinatra's `helper` method that takes a module and mixes it into requests. If your module methods do not rely on state (e.g. a function that formats a string passed into it) they may also be appropriate called externally as `MyHelperModule.foo(bar)`. Using `module_function` (per the answer by @JPabloFernández below) allows a single module 'instance' method to be accessed as the OP requests. – Phrogz Apr 11 '11 at 22:03
23

You can do it this way:

module ModName
  def aux
    puts 'aux'
  end
  module_function :aux
end

and then just call it:

ModName.aux
Phrogz
  • 296,393
  • 112
  • 651
  • 745
Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622
  • 4
    Also: if you're using the module *exclusively* as a namespace, `extend self` is a cleaner option to defining each and every method as a module_function. – Ry Biesemeyer Jul 05 '12 at 21:14
  • 3
    @yaauie If you don't pass an argument to `module_funciton`, then any function below it will be made a module function. It works the same way as `private`. – LandonSchropp Sep 14 '14 at 01:34
17

You can also say

module ModName
  extend self

  def aux
    puts 'aux'
  end
end

Then you can include the module normally, but also call methods via ModName.

EdvardM
  • 2,934
  • 1
  • 21
  • 20
6

the module definition evaluates to 'this is...', why?

In Ruby, everything is an expression, there are no statements or declarations. Which means that everyhing evaluates to a value. (However, this doesn't necessarily mean that it evaluates to a useful value. For example, the puts method always evaluates to nil, just like a def method definition expression (except in Rubinius, where the def expression evaluates to a CompiledMethod object for the method being defined).)

So, if everything evaluates to a value, what should a module definition expression evaluate to? Well, there are a couple of candidates: it could evaluate to nil, just like a method definition expression. Or it could evaluate to the module object itself, after all, this is what we are defining, right? But actually, Matz chose a third option: module (and class) definition expressions actually evaluate to whatever the last expression inside the module definition body evaluates to. (This allows you to easily simulate the other two possibilities by just putting nil or self as the last expression inside a module definition body.)

In your case, the last expression inside the module definition body is an assignment. But, an assignment? What the heck does that return? Isn't that a statement? No, not in Ruby. Everything is an expression, and assignments are no exception: assignment expressions evaluate to whatever the right hand side evaluates to. Here, the right hand side of the assignment expression is a string literal, which evaluates to a string object.

So, the entire module definition expression evaluates to the string 'this is a const in module'.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • 6
    The question was heavily edited since Joerg's answer, if anyone's a little bit confused as to what he's talking about. – Andrew Grimm Apr 11 '11 at 22:16
2

And a little more...

module Y
  def Y.a
    puts "a"
  end

  def Y.b
    c
  end

  def self.c
    puts "b -- c"
  end
end

call (without '.new'):

Y.a #=> "a"
Y.b #=> "b -- c"
Y.c #=> "b -- c"
Michael De Silva
  • 3,808
  • 1
  • 20
  • 24
Ivan Black
  • 4,827
  • 1
  • 35
  • 33
  • 1
    `Y.c` works as well. You can also do `module Y; class << self; def c; puts "b -- c"; end; end;` and define `::c` on its eigenclass. – Michael De Silva Jul 11 '13 at 16:06
0
class Foo
  include ModName
end
Foo.new.aux
# output: aux
Bob Aman
  • 32,839
  • 9
  • 71
  • 95