user2829131
user2829131

Reputation:

Questions about arrays in ruby

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...

Upvotes: 1

Views: 87

Answers (3)

Translunar
Translunar

Reputation: 3816

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

Upvotes: 3

ian
ian

Reputation: 12251

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.

Upvotes: 1

Jakob S
Jakob S

Reputation: 20125

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.

Upvotes: 2

Related Questions