module_function

moduleに普通にメソッドを定義するとインスタンスメソッドとして定義される。

module Foo
  def foo
  end

  puts instance_methods.include?(:foo)         #=> true
  puts private_instance_methods.include?(:foo) #=> false
  puts singleton_methods.include?(:foo)        #=> false
end

classにincludeして使う。

class Bar
  include Foo
end

Bar.new.foo

module_functionを使うと、instance_methodsから消えてprivate_instance_methodssingleton_methodsに追加される。

module Foo
  module_function
  def foo
  end

  puts instance_methods.include?(:foo)         #=> false
  puts private_instance_methods.include?(:foo) #=> true
  puts singleton_methods.include?(:foo)        #=> true
end

モジュールから直接呼んだり

Foo.foo

includeしたclassでレシーバーなしでアクセスできるようになる。

class Bar
  include Foo

  def hoge
    foo
  end
end

ただしpublicなインスタンスメソッドにはならない。

Bar.new.foo #=> NoMethodError

includeする使い方をしないのであればsingleton_methodだけ定義するだけでもいい。

module Foo
  def self.foo
  end

  puts instance_methods.include?(:foo)         #=> false
  puts private_instance_methods.include?(:foo) #=> true
  puts singleton_methods.include?(:foo)        #=> false
end
Foo.foo