Newbie Alert

I am a brand new Ruby beginner, and I have what is undoubtedly a
painfully simple newbie question.

I’m starting my learning by using the online “Programming Ruby, HTML
Help Edition (v0.3a)”, and I’m having trouble getting one of the
earliest code samples in the “Classes, Objects, and Variables” chapter
to work. Here is my slightly modified version (with line numbers added)
of the tutorial code that I’ve saved in a file called RubyTutorial.rb:

01 class Song
02 def initialize(name, artist, duration)
03 @name = name
04 @artist = artist
05 @duration = duration
06 end
07 def to_s
08 puts “Song: #{@name}–#{@artist} (#{@duration})”
09 end
10 end
11
12 aSong = Song.new(“My Way”, “Sinatra”, 225)
13 print “aSong.to_s ==> "
14 aSong.to_s
15
16 class KaraokeSong < Song
17 def initialize(name, artist, duration, lyrics)
18 super(name, artist, duration)
19 @lyrics = lyrics
20 end
21 def to_s
22 super + " [#{@lyrics}]”
23 end
24 end
25
26 kSong = KaraokeSong.new(“My Way”, “Sinatra”, 225, “And now, the…”)
27 print "kSong.to_s ==> "
28 kSong.to_s

When I try to run this from the Windows XP Command Prompt I get the
following result:

C:\Documents and Settings\jl2351\My Documents\Ruby_Scripts>ruby
RubyTutorial.rb
aSong.to_s ==> Song: My Way–Sinatra (225)
kSong.to_s ==> Song: My Way–Sinatra (225)
RubyTutorial.rb:22:in to_s': undefined method+’ for nil:NilClass
(NoMethodError)
from RubyTutorial.rb:28

C:\Documents and Settings\jl2351\My Documents\Ruby_Scripts>

Obviously the “kSong.to_s” call is supposed to be displaying the
additional lyric information. Since I have no clue, can someone tell me
how to correct this? And why is ‘+’ erroring out as an undefined
method? And any other insights into this error that a rank beginner
might find helpful?

Thanks much.

This is actually easy to fix. ‘+’ is an undefined method for
nil:Nilclass, which means that the super on line 22 is returning nil.
‘super’ refers to the to_s of the parent class which is, Song#to_s:

01 class Song

07 def to_s
08 puts “Song: #{@name}–#{@artist} (#{@duration})”
09 end
10 end

The problem is the ‘puts’. puts prints a string and a “\n” to
standard out and returns nil. You actually don’t usually want to_s to
print anything, so if you change Song#to_s to read
def to_s
“Song: #{@name}–#{@artist} (#{@duration})”
end
That will fix the bug, but your program won’t print anything, because
aSong.to_s will just return a string (which is what you want). So
you’ll need to change lines 13 and 14:

13 print "aSong.to_s ==> "
14 aSong.to_s

to
print "aSong.to_s ==> " + aSong.to_s + “\n”
or
puts “aSong.to_s ==> #{aSong.to_s}”
and do something similar with lines 26 and 27.

John Legate wrote:

01 class Song
02 def initialize(name, artist, duration)
03 @name = name
04 @artist = artist
05 @duration = duration
06 end
07 def to_s
08 puts “Song: #{@name}–#{@artist} (#{@duration})”

Here is your problem. #puts prints out the String but it
returns nil.

09 end
10 end
11
12 aSong = Song.new(“My Way”, “Sinatra”, 225)
13 print “aSong.to_s ==> "
14 aSong.to_s
15
16 class KaraokeSong < Song
17 def initialize(name, artist, duration, lyrics)
18 super(name, artist, duration)
19 @lyrics = lyrics
20 end
21 def to_s
22 super + " [#{@lyrics}]”

So here you have printed it out but have gotten a
nil back, whence your error since nil does not
respond to #+.

23 end
24 end
25
26 kSong = KaraokeSong.new(“My Way”, “Sinatra”, 225, “And now, the…”)
27 print "kSong.to_s ==> "
28 kSong.to_s

On Sep 12, 2006, at 11:23 PM, John Legate wrote:

08 puts “Song: #{@name}–#{@artist} (#{@duration})”

This line is the culprit. You really don’t want ‘puts’ here – it
writes to stdout and returns nil, which is why you’re getting the
error. Try

08 “Song: #{@name}–#{@artist} (#{@duration})”

Regards, Morton

D’OH!

I mean, thanks very much to all of you who helped me solve this problem.
I’m also kind of new at searching for answers on a Help Forum like this,
and I’m pleasantly surprised and impressed with how quickly the answer
can be found in this venue.

1337p337 wrote:

This is actually easy to fix. ‘+’ is an undefined method for
nil:Nilclass, which means that the super on line 22 is returning nil.
‘super’ refers to the to_s of the parent class which is, Song#to_s:

01 class Song

07 def to_s
08 puts “Song: #{@name}–#{@artist} (#{@duration})”
09 end
10 end

The problem is the ‘puts’. puts prints a string and a “\n” to
standard out and returns nil. You actually don’t usually want to_s to
print anything, so if you change Song#to_s to read
def to_s
“Song: #{@name}–#{@artist} (#{@duration})”
end
That will fix the bug, but your program won’t print anything, because
aSong.to_s will just return a string (which is what you want). So
you’ll need to change lines 13 and 14:

13 print "aSong.to_s ==> "
14 aSong.to_s

to
print "aSong.to_s ==> " + aSong.to_s + “\n”
or
puts “aSong.to_s ==> #{aSong.to_s}”
and do something similar with lines 26 and 27.