0

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)
Dylan Frye
  • 15
  • 1
  • 6
  • 1
    `@example` is an instance of a hash, do you want to add `my_method` to the hash class? – Anthony Apr 27 '18 at 20:17
  • 1
    `@example` is a `Hash` and you are trying to call `MyModule::my_method` on it this will not work. Additionally `my_method` is a method specifically of that module due to the `self` declaration. There are other issues as well and I hate to be that guy but maybe read up on `Module`s a bit http://ruby-for-beginners.rubymonstas.org/advanced/modules.html – engineersmnky Apr 27 '18 at 20:19

2 Answers2

1

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}"
lacostenycoder
  • 10,623
  • 4
  • 31
  • 48
  • Okay, I think I get it. So as long as I'm creating a module that functions on a certain class, I have to state the inclusion, right? – Dylan Frye Apr 27 '18 at 23:03
  • 1
    Yes, although are you sure you really want to modify the `Hash` class? This is called [monkey-patching](https://stackoverflow.com/questions/394144/what-does-monkey-patching-exactly-mean-in-ruby?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa). – Daryll Santos Apr 28 '18 at 02:21
  • @DaryllSantos answer updated to deter monkey patching Hash class. – lacostenycoder May 04 '18 at 17:31
  • Ah okay. I think I would actually just create a class to create the Person object with a hash in the constructor, just so I don't inherit from `Hash`. (Check out Primitive Obsession). – Daryll Santos May 04 '18 at 19:21
0

@example is a instance of a hash, while the module isn't included in the Hash class at all. You would need to add it to the Hash class first.

class Hash
  include MyModule
end

I would recommend you read the basics of Ruby classes and modules.

thesimpledev
  • 69
  • 1
  • 10