Techioz Blog

Ruby- モジュール間で NoMethodError が発生する

概要

モジュールを正しく使用する方法を理解するのにいくつかの問題があります。

私は持っている:

module Utilities
  def file_search()
    # some code
    return x
  end
end


module Remake_Components
  require 'csv'
  include Utilities

  f = Utilities.file_search()
end

これにより、次のエラーが発生します: #<NoMethodError: Utilities:Module の未定義メソッド “file_search”> 私は f が file_search 関数を実行した結果であると予想していました。

他のメソッドで関数を使用するには include キーワードを使用する必要があると理解していましたが、そうではないようです。

解決策

他のメソッドで関数を使用するには include キーワードを使用する必要があると理解していましたが、そうではないようです。

Module#include は、モジュールを包含オブジェクトの階層チェーンに挿入し、包含オブジェクトのインスタンスが包含モジュールのインスタンス メソッドにアクセスできるようにします。

あなたの場合、 file_search は Utilities で定義されたインスタンス メソッドであり、 include Utilities を呼び出すことで、このメソッドを Remake_Components のインスタンスで利用できるようにしました (ただし、モジュールには (それ自体) インスタンスがありません)。

ユーティリティモジュールをレシーバーとして使用して file_search を呼び出そうとしている方法では、インクルードの呼び出しは必要ありませんが、メソッドを「クラスインスタンスメソッド」または「モジュール関数」として定義する必要があります。

このように動作させたい場合は、2 つのオプションがあります。

module Utilities
  def file_search 
    # some code
    return x
  end
  module_function :file_search
end

どちらのオプションでも、Utilities.file_search を呼び出すことができます。ただし、後者では、Module#include を使用するときに、このメソッドをプライベート インスタンス メソッドとして「含める」こともできます。

例として:

module A 
  def self.foo = 'Foo'
  def bar = 'Bar'
  module_function :bar
end 

class B 
  include A 
  def test_foo = A.foo
  def test_bar = bar
end 

A.foo
#=> "Foo"
A.bar 
#=> "Bar"
B.new.test_foo
#=> "Foo"
B.new.test_bar
#=> "Bar" 
B.new.foo
#=> undefined method `foo' for #<B:0x00007f0c7785e528> (NoMethodError)
B.new.bar
#=> private method `bar' called for #<B:0x00007ff5a5dbe5a0> (NoMethodError)

その他、それほど重要ではないメモをいくつか挙げておきます。