Search code examples
rubymodulenomethoderror

Module method returns NoMethodError


I'm trying to create a method inside my module that returns a hash with the given parameters.

module MyModule

  def self.my_method(*search_params)
    # do something...

    end
    self
  end
end

I've seen a lot of similar questions about this, where the issue is because I'm defining an instance method, but I called self in the definition and continue receiving the error, leading me to believe it might be something else.

@example = { :name => 'John', :quote => 'Great fun!', :rank => 5 }
@example.my_method(:name => 'John') 

NoMethodError: undefined method `my_method` (NoMethodError)

Solution

  • We can't understand what your method is trying to do because the logic doesn't make sense but here's how you add your method to the Hash class.

    module MyModule
      def my_method(*search_params)
        puts "search params: #{search_params}"
      end
    end
    
    
    class Hash
      include MyModule
    end
    
    @example = { :name => 'John', :quote => 'Great fun!', :rank => 5 }
    @example.my_method(:name => 'John')
    
    #=>search params: [{:name=>"John"}]
    

    However this is called "monkey patching" which is not recommended. It would probably be better to use inheritance

    module MyModule
      def monkey(*search_params)
        puts "search params: #{search_params}"
      end
    end
    
    
    class MonkeyHash < Hash
      include MyModule
    end
    
    @example = MonkeyHash.new(:name => 'John', :quote => 'Great fun!', :rank => 5)
    @example.monkey(:name => 'John')
    
    @example = { :name => 'John', :quote => 'Great fun!', :rank => 5 }
    
    begin
      @example.monkey(:name => 'John')
    rescue NoMethodError => e
      puts "Calling @exmaple.my_method raiesed: "
      puts e
      puts "@example is an instance of #{@example.class}. You may want to use MonkeyHash"
      puts "which includes the instance method 'monkey'"
    end
    

    Or you could define a singleton method

    puts "let's try it with a singleton method\n\n"
    
    @singleton_example = { :name => 'John', :quote => 'Great fun!', :rank => 5 }
    
    @singleton_example.define_singleton_method(:monkey) do |*search_params|
      puts "search params: #{search_params}"
    end
    
    puts "now @example has the monkey method see: \n"
    @singleton_example.monkey(:name => 'John')
    puts "@singleton_example is still an instance of #{@singleton_example.class}"