views:

1212

answers:

5

I know I'm doing something stupid or failing to do something intelligent - I'm frequently guilty of both.

Here's an example of what's causing me pain:

I have a module saved in /lib as test_functions.rb that looks like this

module TestFunctions
  def abc
    puts 123
  end
end

Going into ruby script/runner, I can see that the module is loading automatically (good ol' convention over configuration and all that...)

>> TestFunctions.instance_methods
=> ["abc"]

so the method is known, let's try calling it

>> TestFunctions.abc
NoMethodError: undefined method `abc' for TestFunctions:Module from (irb):3

Nope. How about this?

>> TestFunctions::abc
NoMethodError: undefined method `abc' for TestFunctions:Module from (irb):4

Test Nope again.

defined?(TestFunctions::abc) #=> nil, but
TestFunctions.method_defined? :abc #=> true

Like I said at the top, I know I'm being dumb, can anyone de-dumb me?

+1  A: 

You need to include the module

include Testfunctions

Then 'abc' will return something.

james
+1  A: 

You can't call a method in a Module directly. You need to include it in a class. Try this:

>> class MyTest
>>   include TestFunctions
>> end
=> MyTest
>> MyTest.new.abc
123
=> nil
Sarah Mei
+4  A: 

If you want Module-level functions, define them in any of these ways:

module Foo
  def self.method_one
  end

  def Foo.method_two
  end

  class << self
    def method_three
    end
  end
end

All of these ways will make the methods available as Foo.method_one or Foo::method_one etc

As other people have mentioned, instance methods in Modules are the methods which are available in places where you've included the Module

Gareth
+2  A: 

You can also use module_function like so:

module TestFunctions
  def abc
    puts 123
  end

  module_function :abc
end

TestFunctions.abc  # => 123

Now you can include TestFunctions in class and call "abc" from within TestFunctions module.

Marcin Urbanski
+1  A: 

I'm going to try to summarise the various answers myself, since each had something valuable to say, but none really got to what I now realise is probably the best response:

I was asking the wrong question because I was doing it wrong.

For reasons I can no longer explain, I wanted a set of completely stand-alone functions in a library, which represented methods I was trying to DRY out of my classes. That can be achieved, using things like

module Foo
  def self.method_one
  end
  def Foo.method_two
  end
  class << self
    def method_three
    end
  end
  def method_four
  end
  module_function :method_four
end

I could also include my module, either within a class, in which case the methods become part of the class or outside, in which case they are defined on whatever class I'm running inside (Object? Kernel? Irb, if I'm interactive? Probably not a great idea, then)

The thing is, there was no good reason not to have a class in the first place - I'd somehow got on to a train of thought that took me down an seldom-used and frankly slightly weird branch line. Probably a flashback to the days before OO became mainstream (I'm old enough that up to today I've spent a lot more years writing procedural code).

So the functions have moved into a class, where they seem pretty happy, and the class methods thus exposed are being cheerfully used wherever necessary.

Mike Woodhouse