Undefined method `+' for nil:NilClass (NoMethodError)

Hello, I’m just setting out on Ruby and my first little program is
generating an error (in the line @allwords = @allwords +
aword.reverse.capitalize + " ")

I’m trying to reverse a name, so it someone enters ‘Fred’ is will supply
‘Derf’ and if they enter ‘Fred S.’ it will supply ‘Derf Htims’

Here’s the code in full:

class Jumbler
#attr_accessor :fullname
def initialize(fullname)
@fullname = fullname
end

def jumblename
#if there is more than one word, reverse each one
if @fullname.split(" “).length > 1
@fullname = @fullname.split(” ")
@fullname.each do |aword|
@allwords = @allwords + aword.reverse.capitalize + " "
end
return @allwords
else
#just send back the single word
return @fullname.reverse.capitalize
end
end
end

puts “Please enter your name:”
$stdout.flush
yourname = gets.chomp

jumbleyou = Jumbler.new(yourname)
puts jumbleyou.jumblename

I’m not sure if instance variables that are private to the object should
appear in the initialization method (or whether they need to be denoted
with ‘@’ but that doesn’t seen to fix the problem anyway). It seems to
me that the error is because I’m trying to use ‘reverse’ or ‘capitalize’
on a ‘nil’ value but I can’t see why that’s happening.

Guidance appreciated, sorry if my code is offensive! :smiley:

Paul

This code is the reason for your error
@allwords = @allwords + aword.reverse.capitalize + " "

Since @allwords has no value in it, by default that instance variable is
initialized to nil. Thus creating this error. You need to add @allwords

“” before the loop.

@allwords = “”
@fullname.each do |aword|
@allwords = @allwords + aword.reverse.capitalize + " "
end

There is a simpler method to do the same thing
without initializing @allwords

return @fullname.map { |word| word.reverse.capitalize }.join(’ ’ )

the above could would yeild the same result.

Paul R. wrote in post #1137092:

def jumblename
#if there is more than one word, reverse each one
if @fullname.split(" “).length > 1
@fullname = @fullname.split(” ")
@fullname.each do |aword|
@allwords = @allwords + aword.reverse.capitalize + " "
end

@allwords is no initialised, so @allwords + a…try to addition
something to nil

this is perhaps more rubysh :slight_smile:

   @allwords = @fullname.split(" ").map {|w|
              w.reverse.capitalize
             }.join(" ")

Paul R. wrote in post #1137106:

Should all variables within an object be prefixed with ‘@’ even if they
are private to it’s methods?

yes !

In this case it doesn’t seem to make any difference whether I use > ‘allwords’
or ‘@allwords

without @ , ruby look for a method named ‘allwords’
It will found it if you have defined
attr_accessor :allwords

this call will create this 2 methods:
def allwords() @allwords end
def allwords=(v) @allwords=v end

I do not know why, but theses accessors are not accessible
in constructor code.

Thank you both, that explains it. I hadn’t come across the .map method,
it looks very handy!

Should all variables within an object be prefixed with ‘@’ even if they
are private to it’s methods? In this case it doesn’t seem to make any
difference whether I use ‘allwords’ or ‘@allwords’.

Thanks for the help, Ruby has been a revelation so far!

Paul

On Tue, Feb 18, 2014 at 10:50 PM, Regis d’Aubarede
[email protected] wrote:

Paul R. wrote in post #1137106:

Should all variables within an object be prefixed with ‘@’ even if they
are private to it’s methods?

yes !

The answer to the question I think he is asking should be: no !
I am in the assumption that when you mean “private to it’s methods”
you mean variables that are local to a method, that are not used in
any other method in the class. In this case, if you don’t use the @
prefix, Ruby will understand that this is a local variable, or a
method if it hasn’t found an assignment previously:

allwords = “”

As soon as the parser sees this, from this point on allwords is
considered a local variable.

In this case it doesn’t seem to make any difference whether I use > ‘allwords’
or ‘@allwords

without @ , ruby look for a method named ‘allwords’

or a local variable, if it has been previously assigned.

Jesus.

Hmmm, I was reading this page about ‘require’…

… and noticed that @engine_state isn’t initialised but the program
still works, presumably because ‘nil’ is considered to be ‘not true’ in
this case?

It also has the ‘@’ prefix even though it’s not accessible outside the
start_engine method.

Would it be better practice to add

@engine_state = false

to the initialize method or just remove the ‘@’? I realise this is a
trivial example but I’d like to pick up good habits from the start :smiley:

Paul

Thank you Regis & Jesus. I should have made the question clearer but,
yes, I meant variables that are local/private to the method in which
they appear.

Paul

Paul R. wrote in post #1137260:

Would it be better practice to add
@engine_state = false
to the initialize method or just remove the ‘@’?

aïe aïe aïe…

@var : is variable object instance, value is maintains with object life
var : method variable , value is lost after each methode evaluation
var=(); var() : method call, if set/return a @var, value are persisted

Great thank you both (again!). I’m ok with variable scope and object
orientation in general (Java etc) but this is a rather different!

Paul

On Wed, Feb 19, 2014 at 7:27 PM, Paul R. [email protected]
wrote:

Hmmm, I was reading this page about ‘require’…

Learn How to Blog and Build Websites for Profit!

… and noticed that @engine_state isn’t initialised but the program
still works, presumably because ‘nil’ is considered to be ‘not true’ in
this case?

This is exactly the case.

It also has the ‘@’ prefix even though it’s not accessible outside the
start_engine method.

This is not true. Precisely due to having the ‘@’ prefix it is
accesible in other methods of the same class.
If you modify the example like this:

class MotorCycle
def initialize(make, color)
# Instance variables
@make = make
@color = color
end
def engine_status
@engine_state
end
def start_engine
if @engine_state
puts ‘Engine is already Running’
else
@engine_state = true
puts ‘Engine Idle’
end
end
end

You could do:

m = MotorCycle.new(“honda”, “red”)
puts m.engine_status #=> nil
m.start_engine
puts m.engine_status #=> true

Would it be better practice to add

@engine_state = false

to the initialize method

It depends. In this example, it might make sense and make everything
clearer. If the engine_state is better defined as always being true or
false, it would be better to initialize it to false in the
constructor, I agree.

or just remove the ‘@’?

This will impact the function of the variable. If you remove the @,
then it’s simple local variable within the method. With the @, it’s an
instance variable that lives as long as the object to which it
belongs.

I realise this is a
trivial example but I’d like to pick up good habits from the start :smiley:

That’s a good thing, and I think you should read a little bit about
instance variables and object oriented programming in general to have
a clear understanding on the implications of being a local variable vs
an instance variable.

Jesus.

Thanks Marcus.

Paul

Am 19.02.2014 19:27, schrieb Paul R.:

… and noticed that @engine_state isn’t initialised but the program
still works, presumably because ‘nil’ is considered to be ‘not true’ in
this case?

Not only “in this case”.
In Ruby, exactly two things are considered false: false' andnil’.

Regards,
Marcus