chris-tulip
chris-tulip

Reputation: 1830

Nested Modules and Method Hooks

I'm a total newbie at ruby (java background) so I'm sorry if this is a really dumb question.

I'm working through some tutorials on modules and they seem somewhat similar to static classes. The bit I'm having trouble wrapping my head around is why you would do something like the following:

module ExampleModule

  def self.included(base)
      base.extend(ClassMethods)
  end

  module ClassMethods
      def myMethod
      end
  end
end

Why wouldn't you just put the methods in ClassMethods into ExampleModule and save adding the method hook. I'm sure I'm missing something really basic but I've been at this for a while now so I feel the need to ask.

Upvotes: 1

Views: 1453

Answers (2)

Beat Richartz
Beat Richartz

Reputation: 9622

The patter you use here is common when both class methods and instance methods are included via a module in ruby. It gives you the advantage of just having to write

include ExampleModule

for including instance methods and extending class methods instead of

# include instance methods
include ExampleModule
# extend class methods
extend ExampleModule::ClassMethods

So, if used just to extend the class with some methods, my personal preference is to use extend directly.

module ExtensionAtClassLevel
  def bla
    puts 'foo'
  end
end

class A
  extend ExtensionAtClassLevel
end

A.bla #=> 'foo'

If both instance and class methods are added, I use the include hook you described.

Some rubyists tend to prefer using extend via the include hook to pure extend, which has no reason if you are just adding class methods like in your example.

Upvotes: 1

cthulhu
cthulhu

Reputation: 3726

It's a ruby idiom. It's useful when you want a module that:

  • adds some instance methods to a class
  • adds class methods in the same time /like Java static methods/

in the same time

Example:

module ExampleModule
  def self.included(base)
    puts 'included'
    base.extend(ClassMethods)
  end

  def foo
    puts 'foo!'
  end

  module ClassMethods
    def bar
      puts 'bar!'
    end
  end
end

class ExampleClass
  include ExampleModule
end

ExampleClass.bar

ExampleClass.new.foo

If you only want to add class methods, you don't need this idiom, you can just add a method to your module and 'extend' it instead of including it.

When on Rails, this idiom is obsolete and you should use ActiveSupport::Concern instead.

Upvotes: 3

Related Questions