1

I have a class called Product, which contains a name, price and count.

In another class called Shop (including the class Product), I initialize with an empty array. Then a add product to this array using the method push.

The problem happens to the method to_s of in the Shop class :

def to_s
  string = "Products in the shop:\n"
  @list.each do |list|
    #### how can i get access to the attributes of product like @list.name or something like that ?  I have tried loads of different methods but i cant get access to my attributes. (the array doesnt recognize the product class)
    puts @list.name
  end

If I create a Product without using Array, I can access to the attributes - I guess the problem comes because of the Array...

3
  • 1
    First show us the class you have created,then ask us the question pointing to the confusions you are having.. Commented Sep 29, 2013 at 19:34
  • Is the end in your code the end of the each block or the end of the def to_s block? Commented Sep 29, 2013 at 19:46
  • Whoever edited it, you may have changed the OP's question. Note my comment above about mismatched ends. =) Commented Sep 29, 2013 at 20:07

3 Answers 3

3

So first of all, your blocks don't match up.

You want:

def to_s
  string = "Products in the shop:\n"
  @list.each do |item|
    string << item.name + "\n"     # not @list.name! @list is an Array. item is an element of your list.
  end
  string # you could also say: return string
end

You don't want to use puts because that'll send it to the console -- when you're trying to store it in a String called string. You want to make sure you return that, too.

You don't have to call your block parameter item. You could call it list, but that would be confusing, because you have another variable called @list, and the block parameter is not a list at all -- just an item from the array.

Note that this is not the most efficient way to accomplish this. The preferred way is like so:

def to_s
  products_list = @list.map do |item|
    item.name
  end
  "Products in the shop:\n" + products_list.join("\n")
end
Sign up to request clarification or add additional context in comments.

3 Comments

You could also write John's suggested alternative as: def to_s() "Products in the shop:\n" + @list.map(&:name).join("\n") end
Doesn't that need a colon after the def to_s()? Also, the parens are optional. =)
If you remove the parens you'll need to insert one ; after to_s and another before end. Both work.
2

Each element in @list is yielded to the each block as list.

Assuming @list is an Enumerable with Product objects, you should be able to do list.name to get at the name attribute inside the block.

Comments

1

I'd prefer map and join over each and << (just a preference), and braces ({}) over do end because I like to imply a return value is important by using braces, and a do end block is there for side effects, e.g.

def to_s
  "Products in the shop:\n" << @list.map{|item| item.name}.join("\n")
end

I also wouldn't use puts because to_s should return a string, not output a string.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.