Forum: Ruby Include Module gives Uninitialized Constant error

Announcement (2017-05-07): is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see and for other Rails- und Ruby-related community platforms.
9bee065effbfb81b82275deb4462626c?d=identicon&s=25 Daniel B. D. (danielbdavis)
on 2014-06-14 07:01
Attachment: samp.erb (371 Bytes)
Attachment: sampMod.rb (2 KB)
Attachment: terminal.txt (708 Bytes)
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
5989a003d261c0abe6d08570ff6cc3d0?d=identicon&s=25 7stud -. (7stud)
on 2014-06-15 19:32
> 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

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'

p self
p @x


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.

6)  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]

@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

But that will produce the error:

 `getsamp': undefined method `samp' 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

~/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

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.
9bee065effbfb81b82275deb4462626c?d=identicon&s=25 Daniel B. D. (danielbdavis)
on 2014-06-17 06:54
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.
This topic is locked and can not be replied to.