Class doesn't know about calling program's libraries?


#1

I’m still in my first 24 hours of seriously using classes, so am still
pretty ignorant. I’ve read a lot, but that only goes so far.

I have a main program which loads some libraries, then calls my main
method, which call a class -

%w(rubygems ruby-debug readline strscan logger fileutils).each{ |lib|
require lib }
main

Inside the class is this line -

opt = Readline::readline( ":: " )

which generates this error -
uninitialized constant SetLogLevel::Readline (NameError)

Two questions:

  1. Is my class really so unaware of the calling program’s namespace (I
    rather think yes).
  2. If so, what is the best way to make sure the class has access to the
    libraries already loaded in the calling program?

Thanks for any help!

T.

Tom C., MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< removed_email_address@domain.invalid >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)

#2

Tom C. wrote:

opt = Readline::readline( ":: " )

which generates this error -

please post the entire code snippet for help

ilan


#3

Tom C. wrote:

Inside the class is this line -

opt = Readline::readline( ":: " )

which generates this error -
uninitialized constant SetLogLevel::Readline (NameError)

At a guess: you are running this before you have done require
‘readline’

The easiest solution is to put

require 'readline'

at the top of this source file. If it has already been required, this
will do nothing; but if it has not already been required, it will load
it in.

Two questions:

  1. Is my class really so unaware of the calling program’s namespace (I
    rather think yes).

I am not sure what you mean about this. Constants are searched for in
your own class, encoding classes/modules, and the top level.

You can say ::Readline instead of Readline if you mean “I must use the
one defined in the top level”, but this will only make a difference if
your class has its own Readline as well, in which case a bare ‘Readline’
will use the one within your class.

  1. If so, what is the best way to make sure the class has access to the
    libraries already loaded in the calling program?

require ‘filename_containing_library’ at the top of each source file
which makes use of the class(es) defined in that library.


#4

And the exact exception, with backtrace?


#5

Ilan B. wrote:

ilan

Sorry - I thought I’d included enough to justify my questions. Here’s a
full source file, which produces the problem, minus all methods and
classes not relevant to the immediate problem -

SetNet.rb

def main

Set up logging

run_log = Toggle_log.new( ‘logfile.txt’ )
run_log.open
@log = run_log.log
logging_now = run_log.lgg

[…]

end

class Toggle_log
attr_accessor :log, :lgg
def initialize( logFileName )
@logFileName = logFileName
end

def open
#create log file
log_main = File.open( @logFileName, File::WRONLY | File::APPEND )
@log = Logger.new( log_main )
@log.datetime_format = “%Y-%m-%d %H:%M:%S”
@lgg = true

# set logging level
@log.level = Logger::INFO # I.e., only INFO level and above will be

logged
@log.info( ‘===== START logging’ ) # just a program place indicator
puts ‘> logging started, at INFO level’
end

def close
@log.info( ‘===== STOP logging’ ) # just a program place indicator
puts ‘> logging stopped’
@log.close
@lgg = false
end
end

class SetLogLevel
def initialize( log )
@log = log
end
puts “> logging level options - from most to least grave -”
puts “> 5 = FATAL | 4 = ERROR | 3 = WARN | 2 = INFO | 1 - DEBUG | 0 =
off”
puts “> enter choice (x - exit logging level entry)”
while true
opt = Readline::readline( “:: " )
case opt
when ‘x’ then break # exit
when ‘5’ then
@log.warn( ‘logging level changed to FATAL’ )
@log.level = Logger::FATAL
puts ‘> logging level now FATAL’
break
when ‘4’ then
@log.warn( ‘logging level changed to ERROR’ )
@log.level = Logger::ERROR
puts ‘> logging level now ERROR’
break
when ‘3’ then
@log.warn( ‘logging level changed to WARN’ )
@log.level = Logger::WARN
puts ‘> logging level now WARN’
break
when ‘2’ then
@log.warn( ‘logging level changed to INFO’ )
@log.level = Logger::INFO
puts ‘> logging level now INFO’
break
when ‘1’ then
@log.warn( ‘logging level changed to DEBUG’ )
@log.level = Logger::DEBUG
puts ‘> logging level now DEBUG’
break
when ‘0’ then
@log.warn( ‘logging level changed to OFF; logging closed’ )
@log.close
puts ‘> logging stopped’
break
else puts “> '”+opt+”’ - ? [#2]"
end
end
end

%w(rubygems ruby-debug readline strscan logger fileutils).each{ |lib|
require lib }
#Debugger.start
#debugger # call to ruby-debug

main

end file

Tom C., MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< removed_email_address@domain.invalid >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)

#6

P.S. It would be extremely helpful if you could boil this down to a very
short program which replicates the problem, and then post that program
in its entirety.

For example, when I write this:

---- 8< -----

foo.rb

def main
Foo.new.bar
end

class Foo
def bar
Readline::readline(">>")
end
end

%w(readline).each{ |lib| require lib }
main
---- 8< -----

and type “ruby foo.rb” then it runs perfectly. The question is, what’s
different between this and what you posted? Does this program run
correctly for you? If so, I suspect the problem lies somewhere outside
what you posted.

This whole process is extremely useful:

  1. In the act of minimising the problem, you’ll probably find the
    solution yourself.

  2. Even if you don’t, then you have made it as easy as possible for
    other people on the list to understand and/or replicate the problem, and
    hence to find the solution.

The question then becomes simply: “The following piece of code raises
the exception shown. Why?” Since line numbers in the exception will
match up exactly to the posted code, an experienced coder will likely
see the problem at once.

Making life easy for other people makes them much more inclined to help
you (both now and in the future), as does demonstrating that you’ve done
your own homework. There’s a very good article on this topic at
http://www.catb.org/~esr/faqs/smart-questions.html

Regards,

Brian.


#7

Brian C. wrote:

end

  1. Even if you don’t, then you have made it as easy as possible for
    your own homework. There’s a very good article on this topic at
    http://www.catb.org/~esr/faqs/smart-questions.html

Regards,

Brian.

Brian, Thanks for your excellent recommendations. Though I did attempt
to present a succinct code excerpt containing my problem, I can see,
after reading your comments, that I could certainly have reduced it to
essentials, and did not. An excellent idea, and that’s how I’ll present
problems here in the future. Thanks for the correction!

And thanks for the link.

And thanks for answering my original question about classes’ having
knowledge of libraries loaded in the calling code.

t.

Tom C., MS MA, LMHC - Private practice Psychotherapist
Bellingham, Washington, U.S.A: (360) 920-1226
<< removed_email_address@domain.invalid >> (email)
<< TomCloyd.com >> (website)
<< sleightmind.wordpress.com >> (mental health weblog)

#8

Brian C. wrote:

If so, I suspect the problem lies somewhere outside
what you posted.

Looking again, I see it now. This boils down what you wrote and
replicates the problem:

---- 8< ----
def main
Foo.new.bar
end

class Foo
def initialize
puts “Not reached”
end
Readline::readline(">>")
end

require ‘readline’
main
---- 8< ----

Can you see what’s wrong with this?