-8

I am getting an error when I create a class of Stats and another a container class. The error is

test.rb:43:in `<main>' undefined method `each' for #<Boyfriends:0x2803db8 @boyfriends=[, , , ]> (NoMethodError)

which makes absolute sense because that class indeed does not contain that method, but should ruby search the parents and grandparents classes for the method? The script displays the desired output; it just inlays the error with the output like so

test.rb:43:in `<main>'I love Rikuo because he is 8 years old and has a 13 inch nose
I love dolar because he is 12 years old and has a 18 inch nose
I love ghot because he is 53 years old and has a 0 inch nose
I love GRATS because he is unknown years old and has a 9999 inch nose
: undefined method `each' for #<Boyfriends:0x2803db8 @boyfriends=[, , , ]> (NoMethodError)

Here is the code

class Boyfriends
    def initialize
        @boyfriends = Array.new
    end

    def append(aBoyfriend)
        @boyfriends.push(aBoyfriend)
        self
    end

    def deleteFirst
        @boyfriends.shift
    end

    def deleteLast
        @boyfriends.pop
    end

    def [](key)
        return @boyfriends[key] if key.kind_of?(Integer)
        return @boyfriends.find { |aBoyfriend| aBoyfriend.name }
    end
end

class BoyfriendStats
    def initialize(name, age, nose_size)
        @name = name
        @age = age
        @nose_size = nose_size
    end

    def to_s
        puts "I love #{@name} because he is #{@age} years old and has a #{@nose_size} inch nose"
    end

    attr_reader :name, :age, :nose_size
    attr_writer :name, :age, :nose_size
end

list = Boyfriends.new
list.append(BoyfriendStats.new("Rikuo", 8, 13)).append(BoyfriendStats.new("dolar", 12, 18)).append(BoyfriendStats.new("ghot", 53, 0)).append(BoyfriendStats.new("GRATS", "unknown", 9999))

list.each { |boyfriend| boyfriend.to_s }
sawa
  • 165,429
  • 45
  • 277
  • 381
randy newfield
  • 1,221
  • 3
  • 25
  • 38

1 Answers1

1

Which makes absolute sense because that class indeed does not contain that method, but as I've been reading should ruby search the classes parents and grandparents for the method?

That's correct, but you didn't declare any superclasses so the superclass will be Object. Which also doesn't have an each method.

If you want an enumerable method, you'll have to define it yourself - you'll probably want to iterate over the array.

In that case, you could just define an own each method that just passes the passed block down to the arrays each method:

class Boyfriends
   def each(&block)
     @boyfriends.each(&block)
   end
end

The &block here let's you capture a passed block by name. If you're new to ruby, this probably doesn't mean much to you, and explaining how it works is somewhat beyond the scope of this question. The accepted answer in this Question does a pretty good job of explaining how blocks and yield work.

once you got an each method, you can also pull in Enumerable for a number of convenience methods:

class Boyfriends
    include Enumerable
end

Also, to_s is a method that should return a string, so you should remove the puts in BoyfriendStats#to_s.

Community
  • 1
  • 1
Cubic
  • 14,902
  • 5
  • 47
  • 92
  • Thank you for this. I knew it was an easy fix, but since I'm just starting ruby I couldn't quite figure it out. I marked your post as the answer, but I have a question. What does the `&` prefix do to a variable in ruby. I don't think I've read anything about it yet. – randy newfield May 04 '13 at 07:37
  • I want to know where that output is coming from, in the original example, though. That's the interesting part of the question. – xaxxon May 04 '13 at 07:39
  • @xaxxon I answered that at the end. He had a `puts` in his `BoyfriendStats#to_s` method, which caused output when Ruby tried to display the `Boyfriends` instance. – Cubic May 04 '13 at 07:44
  • @randynewfield Updated the answer with link to relevant question. – Cubic May 04 '13 at 07:45
  • Thank you for the `&block` answer. I've briefly read about code blocks and started to try to use them in my own code. I guess what I've read didn't include the `&` prefix. Thanks for the answer and the further reading material. – randy newfield May 04 '13 at 07:46
  • that's the empty strings between the commas here: @boyfriends=[, , , ], isn't it? i thought that looked weird. – xaxxon May 04 '13 at 07:48