web-dev-qa-db-ja.com

Ruby-モジュール:: NoMethodError

私はこのようなモジュールを持っています:

module Prober
  def probe_invoke(type, data = {})
    p = Probe.new({:probe_type => type.to_s,
        :data => data.to_json, :probe_status => 0, :retries => 0})
    p.save
  end
end

そして、私は次のように私のメインプログラムからこれにアクセスしようとしています:

require 'prober'
Prober.probe_invoke("send_sms", sms_text)

しかし、それはエラーを生成します:

prober:Moduleの未定義のメソッド `probe_invoke '(NoMethodError)

27
Sayuj

関数をself.として定義するオプションを提供する回答とは別に、モジュールを含めて、次のようなモジュール参照なしで呼び出すという別のオプションがあります。

module Prober
  def probe_invoke(type, data = {})
    p = Probe.new({:probe_type => type.to_s,
        :data => data.to_json, :probe_status => 0, :retries => 0})
    p.save
  end
end

そして、あなたはそれをこのように呼ぶことができます:

require 'prober'
include Prober
probe_invoke("send_sms", sms_text)
23
rubyprince

最も簡単な方法は、メソッドをモジュールレベルのメソッドに変換することです。

module Prober
  def Prober.probe_invoke(type, data = {})
    p = Probe.new({:probe_type => type.to_s,
        :data => data.to_json, :probe_status => 0, :retries => 0})
    p.save
  end
end

def self.probe_invokeも機能します。これは、その行が実行されるときに、selfがモジュール定義であるためです。

14
Gareth

ここでの回答の横に、次のこともできます。

module Prober
  class << self
    def probe_invoke(type, data = {})
      p = Probe.new({:probe_type => type.to_s,
          :data => data.to_json, :probe_status => 0, :retries => 0})
      p.save
    end

    # more module instance methods ...
  end
end

class << selfブロックは、その中のすべてのメソッドもモジュールのインスタンスメソッドとして定義します。

(その機能は、すべてのメソッドをdef Prober.mymethod ...またはdef self.mymethod ...で定義するのと同じです)


更新(2014-11-22)

Rubyスタイルガイドによると 代わりにmodule_function を使用する必要があります:

module Prober
  module_function # <-- preferred style nowadays

  def probe_invoke(type, data = {})
    Probe.new(probe_type:   type.to_s,
              data:         data.to_json,
              probe_status: 0,
              retries:      0)
      .save # no need for a temporary variable
  end

  # more module methods ...
end

私はこれを ユーティリティモジュール と呼びます。

ところで:以前は、メソッドをextend selfブロックでラップする代わりにclass << selfを使用するのが一般的でした。

また、上記のコードを他のスタイルガイドの推奨事項に適合させました。

7
asaaki

答えは:

module Prober
  def Prober.probe_invoke(type, data = {})
    p = Probe.new({:probe_type => type.to_s,
        :data => data.to_json, :probe_status => 0, :retries => 0})
    p.save
  end
end

Prober.probe_invoke("send_sms", sms_text)

それ以外の場合は、メソッドをモジュールのインスタンスメソッドとして定義しますが、実際には静的に定義する必要があるためです。

3
grundprinzip