includeとprependで読み込む順番の確認

includeとprependで読み込む順番を確認していきたい思います。

moduleの複数読み込みをした場合に、どのような順番で読み込まれるのかを確認していきます。

includeの順番に依存

何も考えないでincludeしていく場合は、読み込む順番に依存していることがわかります。

module Foo
  def foo
    puts 'foo'
  end
end

module Bar
  def foo
    puts 'foo bar'
  end
end

class Baz
  include Foo
  include Bar
end

Baz.ancestors
=> [Baz, Bar, Foo, Object, Kernel, BasicObject]
x = Baz.new
x.foo
=>foo bar

ancestorsで確認しても、[Baz, Bar, Foo, Object, Kernel, BasicObject]下から読み込みされていることがわかります。

prependで優先的に読む

prependで試してみます。

module Foo
  def foo
    puts 'foo'
  end
end

module Bar
  def foo
    puts 'foo bar'
  end
end

class Baz
  prepend Foo
  include Bar
end

Baz.ancestors
=> [Foo, Baz, Bar, Object, Kernel, BasicObject]
x = Baz.new
x.foo
=>foo

これを見るとBazより先に読み込まれていることがわかります。

ということは、同じメソッドを用意したらどうなるか確認してみます。

module Foo
  def foo
    puts 'foo'
  end
end

module Bar
  def foo
    puts 'foo bar'
  end
end

class Baz
  prepend Foo
  include Bar

  def foo
    puts 'foo baz'
  end
end

Baz.ancestors
=> [Foo, Baz, Bar, Object, Kernel, BasicObject]
x = Baz.new
x.foo
=>foo

Fooの方が先にあるので、当然moduleのFooのmethodが読まれます。

まとめ

既存のメソッドをオーバーライドする・優先的に読む必要があるのなら、prependを使うのがいいでしょう。