Include Module gives Uninitialized Constant error

I am learning Ruby, but no beginner in computers. If this belongs in
Ruby on Rails, then please move it, but since I am using Cuba, a
micro-framework, I did not put it into R-on-R. I seem to have tried
quite a number of alternatives to cure this problem, with no success.
This is a scaled-down sample which preserves the error. In the final
system the included module will be generated by algorithm. It contains
the data for drawing parts of a game, as an array of hashes. The
generated code works when it is manually copied to the equivalent of
“samp.erb”. Now, I want to include it there automatically as sampMod.rb.
The files: 1. samp.erb: the file which includes the module
2. sampMod: the file containing the module
3. terminal.txt: the console output

I am learning Ruby

Then you probably aren’t going to understand this…

  1. Get rid of ‘require rubygems’ unless you are using old versions of
    ruby and rubygems.

  2. Name the file that contains the module “samp_mod.rb”–it’s ruby code
    afterall.

  3. You define a module with the ‘module’ keyword NOT “Module”.

  4. module definitions, like class definitions are terminated with the
    “end” keyword.

  5. @ variables attach themselves to whatever object is self at the
    instant the @ variable is created. Similarly, when you try to retrieve
    the value of an @variable, ruby looks at whatever object is self at that
    instant and tries to lookup the @ variable in self.

module A
p self
@x = ‘hello’
end

p self
p @x

–output:–
A
main
nil

Based on that output, @x attaches itself to A, but when @x is retrieved
an object called ‘main’ is self, and ‘main’ does not have an @x instance
variable, so nil is returned.

  1. A def starts a new scope, and nothing outside the def can be seen
    inside the def. In your def here:

def getsamp(index, attr)
return @samp[index][attr]
end

@samp will be looked up in whatever object is self when the def
executes, and when the def executes self will be the object that called
the def. What object is that? If you add some code to the erb
file, you can find out:

<% require ‘./samp_mod’; include SampMod %>

self is equal to: <%= self %>

~/ruby_programs$ erb samp.erb > erb_result.txt
~/ruby_programs$ cat erb_result.txt

self is equal to: main

So you have the same problem as above with @x: namely, @samp is being
looked up
in an object called main, yet when you defined @samp it attached itself
to SampMod.

Note that in ruby, ALL methods are called by some object. If no
object is explicitly specified to the left of the method call, then
ruby uses whatever object is self to call the method.

A first attempt to correct the problem might look something like this:

module SampMod
@samp = [‘hello’]

def getsamp
return SampMod.samp
end
end

But that will produce the error:

getsamp': undefined methodsamp’ for SampMod:Module (NoMethodError)

You get that error because @ variables are private by default, so you
need to provide an accessor for the variable:

module SampMod
@samp = [“hello”]

attr_reader :samp

def getsamp
return SampMod.samp
end
end

–output:–
~/ruby_programs$ erb samp.erb > erb_result.txt
~/ruby_programs$ cat erb_result.txt

self is equal to: main
Result: [“hello”]

Because all of the above is probably too complicated to comprehend,
if you can, the easiest thing to do is just make @samp a constant:

module SampMod
SAMP = [“hello”]

def getsamp
return SAMP
end
end

Lookups for constants work differently: the lookup starts in the inner
scope (the def) and moves outwards to the surrounding scopes (the
module). And you can always
specify the absolute constant name: SampMod::SAMP to retrieve the
constant from anywhere.

Thank you so very much. I am hard at work understanding this, and when I
do, I am sure it will be salutary to all of my future ruby efforts. I
may bring bad habits of thought to ruby from a long history with
assembly code, PL/I, C, C++, COBOL, FORTRAN, Perl Tcl/Tk, Objective C
and Java, and while I seem to understand the surface of all that you
have written (maybe some others I’ve forgotten), and believe it is
within my grasp to work through their implications, one thing baffles
me: why is it needed to remove the "require rubygems’; or
,alternatively, when is it required to add it?

Even more important than the code is the manner in which you have taken
the time to explain the underlying effects This Creates both extreme
gratitude and admiration. It is very easy to get a smattering of Ruby
from books, but without this sort of code practice, fluency will never
be achieved. We need to be allowed to stumble, hurt, get up, and retry.
Thanks so much again.