Search code examples
rubyoopirb

Ruby: Procs and Blocks in Classes, arrays as variables




I'm learning Ruby right now, using the tutorial from http://www.humblelittlerubybook.com/book/html/chapter2.html
The subchapter that I'm currently at is: "Methods and Variables"

I've made an array of instances of the Boogeyman class and I want to call each 'change_location' method of those instances and change their instance variable @location to a value specified by an array.

preceding code:

class Boogeyman
  def initialize(name, location)
    @name = name
    @location = location
    puts "Yes, Master?"
  end
  def change_location(newlocation)
    @location = newlocation
    puts "I moved to #{newlocation}."
    self.get_info
  end
  def change_name(newname)
    @name = newname
    puts "I shall be called #{newname} from now on!"
    self.get_info
  end
  def get_info
    puts "I am #{@name} in #{@location}."
  end
end

army = Array.new

army.push(Boogeyman.new("Mister Creepy", "New York, NY"))
army.push(Boogeyman.new("Loopy Lou", "Albuquerque, NM"))

locations = ["location1", "location2"]

In other words: I want to change the location of all the boogeymen in the army.
I've already learned the .each method and expect to provide the array 'locations' with all the locations in it in the following way:

Expected code:

army.each {|boogeyman| boogeyman.change_location(locations)}

or:

army.each(locations) {|boogeyman| boogeyman.change_location(locations)}

Expected result:

I moved to location1!
I am Mister Creepy in location1.
I moved to location2!
I am Loopy Lou in location2.

Actual result:

I moved to ["place1", "place2"]!
I am Mister Creepy in ["place1", "place2"].
I moved to ["place1", "place2"]!
I am Loopy Lou in ["place1", "place2"].

resp.

ArgumentError: wrong number of arguments (1 for 0)
  from (irb):158:in 'each'
  from (irb):158
  from /usr/local/bin/irb:11:in '<main>'



As you can see, the result isn't as I expected. I suspect there will be very little difference between my expectations and the actual code, but I can't find out what it actually is.

PS. Please notify me when you see something that needs to be clarified or corrected.


Solution

  • boogeyman.change_location(locations) is setting each Boogeyman's @location to the whole array. What you want is to iterate over pairs (zip) of boogeyman and his location:

    army.zip(locations).each { |boogeyman, location|
      boogeyman.change_location(location)
    }