module Test
def self.model_method
puts \"this is a module method\"
end
end
class A
include Test
end
A.model_method
this will be error w
Including a module is analogous to copying its instance methods over.
In your example, there are no instance methods to copy to A
. model_method
is actually an instance method of Test
's singleton class.
Given:
module A
def method
end
end
This:
module B
include A
end
Is analogous to this:
module B
def method
end
end
When you think of it this way, this makes perfect sense:
module B
class << self
include A
end
end
B.method
Here, the methods are being copied to the B
module's singleton class, which makes them the "class methods" of B
.
Note that this is exactly the same thing as:
module B
extend A
end
In reality, the methods are not being copied; there is no duplication. The module is simply included in the method lookup list.
If you want to have both class methods and instance methods mixed into a class when including a module, you may follow the pattern:
module YourModule
module ClassMethods
def a_class_method
puts "I'm a class method"
end
end
def an_instance_method
puts "I'm an instance method"
end
def self.included(base)
base.extend ClassMethods
end
end
class Whatever
include YourModule
end
Whatever.a_class_method
# => I'm a class method
Whatever.new.an_instance_method
# => I'm an instance method
Basically to over-simplify it, you extend
to add class methods and you include
to add instance methods. When a module is included, it's #included
method is invoked, with the actual class it was included in. From here you can extend
the class with some class methods from another module. This is quite a common pattern.
See also: http://api.rubyonrails.org/classes/ActiveSupport/Concern.html