I'm having some issues with getting to grips with using modules correctly.
I have:
module Utilities
def file_search()
# some code
return x
end
end
module Remake_Components
require 'csv'
include Utilities
f = Utilities.file_search()
end
Which gives me the error: #<NoMethodError: undefined method "file_search" for Utilities:Module>
I would have expected f
to be the result of running the file_search
function.
My understanding was I had to use the include
keyword to use the functions in the other method but it doesn't seem to be so?
My understanding was I had to use the include keyword to use the functions in the other method but it doesn't seem to be so?
Module#include
will inject the Module into the including Object's hierarchical chain and will make instance methods of the included Module accessible to instances of the including Object.
In your case file_search
is an instance method defined in Utilities
and by calling include Utilities
you have made this method available to instances of Remake_Components
(however Module
s do not have instances (per se)).
The way you are trying to call file_search
with the Utilities
Module as a receiver does not require a call to include
but rather requires the method to be defined as a "class instance method" or a "module function".
If you would like it to work this way then you have 2 options:
Utilities
by changing the method declaration to def self.file_search
module_function
method (not generally a recommended approach) e.g.module Utilities
def file_search
# some code
return x
end
module_function :file_search
end
Both options will allow you to call Utilities.file_search
; however, the latter will also allow you to "include" this method as a private instance method when using Module#include
.
By way of Example:
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)
A few other less consequential notes:
def file_search()
- If there are no arguments the parenthesis can be omitted and as a general style are.return x
- ruby will always return the value of the last expression so unless you intend to return a value early the return
can be omitted.module Remake_Components
- While method names (and local/instance variables) are expressed in lower_snake_case, class and module constants are expressed in UpperCamelCase so this module would generally be named RemakeComponents
require 'csv'
- require statements do not have a lexical scope so whether or not this is contained within the module declaration has no bearing on its accessibility. For this reason require calls (especially to core libraries) are generally placed at the top of the file (outside of any declaration).