[info] Using Ruby Modules
This is an informational thread.
Please do not use this thread to discuss issues relating to Using Ruby Modules,
instead please use the talk thread: [talk] Using Ruby Modules
ben.doherty in Re: entering components wrote: I am having lots of trouble with modules though, if I ask the ruby console for Voyeur::FaceMaker::instance_methods it gives me back a list of the methods as I'd expect, but if I say Voyeur::FaceMaker.makeAnalysisFaces it throws a #<NoMethodError.... any idea how to fix that?
OK...
(1) instance methods are really meant for Classes, where an instance (a child copy,) of a class inherits the method, that is always evaluated within the context of the instance copy, and not the Class itself. This is the opposite of a Class method.
(2) "But why.." you ask "then are instance methods allowed to be declared within modules?"
The answer is that modules can be used in a special purpose library way, called a "Mixin Module". Where you can encapsulate a set of instance methods in the "Mixin", and then mix it into a normal module, a class defintion, and even a specific instance object; and they will then have those methods.
However what "kind" of method that the resultant method becomes in the "mixee" object, depends on:
- what kind of method it was in the Mixin Library module
- whether the "mixee" is a Module or Class or Instance
- and whether the "mixing" is done by include or extend.
(3) Your not doing a mixin module, so you don't want to worry about that right now. What you want, when you wish to call methods from outside the module, is called a "module method" or a "module function". Where the name of the specfic module (with or without namespace qualification,) is used as the "receiver" in the call, as your example shows:
Voyeur::FaceMaker.makeAnalysisFaces
There are 3 ways, within the module definition to explicitly, define a method as a module method:
- def Facemaker.makeAnalysisFaces
- def self.makeAnalysisFaces
- use module_function(:makeAnalysisFaces) after the method definition. The arg list can list more than one methodname. Or you can use it at the top (without an argument,) before multiple method def blocks and all of them are effected until you declare public or private again. However, that feature actually creates two copies of each method within the module, which doubles it's memory cost.
Example:
- Code: Select all
module Voyeur
module FaceMaker
if( not file_loaded?("makeTheFaces.rb") )
# menu setup
file_loaded("makeTheFaces.rb") # <<-- NEED
end
class << self
private
def methOne
return "This is from methOne "
end
def methTwo
return "and from methTwo."
end
public
def methExternal
return methOne << methTwo
end
# etc.
end # self
end # Facemaker
end # Voyeur
Nope.. not right. Cannot be done that way. Instance methods are just only meant for Mixin Modules.As a sidenote, it can be done as is (I think,) in a convoluted way, via:
Voyeur::FaceMaker.method('makeAnalysisFaces').call
but of course that's silly, and defeats the purpose of modular programmimg and elegance.
So my advice is:
(a) In normal modules: wrap ALL methods in a class << self block.
(b) use the methods public and private to mark which ones are externally called and only internally called (respectively.)
(c) Ruby likes to have methods defined before they get called, so probably those that are private will be at the top of the block.
[Example above shows this...]
NOW.. most important to coders migrating to using modules: intenal private methods can now be called from other internal methods without qualificaton (ie: methodname instead of self.methodname )
Please do not use this thread to discuss issues relating to Using Ruby Modules,
instead please use the talk thread: [talk] Using Ruby Modules

