Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby Ruby Collections Build a Grocery List Program Build a Grocery List Program: Part 3

I can't understand what is going on in this video..

  def print_list(list)

    puts "List #{list['name']}"   #calling list name with string interpolation
  puts "------"

  list["items"].each do |item|    #takes each item in array of list items and assign it to a var called item
    puts "Item: " + item['name']
    puts "Quantity " + item['quantity'].to_s
    puts "-------"

  end

Why is name in square brackets? I thought name was a key in the hash. I don't understand why you write list["items"].each do | item|. Can someone explain this step by step. This is a moment where the lack of audio communication makes learning impossible.

3 Answers

Samuel Ferree
Samuel Ferree
31,722 Points

you're declaring your print_list function inside your add_list_item, and I don't think you want to.

def add_list_item
  #some code
  def print_list
    #print code
  end #ends the print_list function
end #ends the add_list_item function

I think you want this

def add_list_item
  #add list item code
end

def print_list
  #print list code
end

notice the values are variables and have no quotes

list_item= {"name"=> item_name, "quantity"=> quantity} 

Yes, this is because you want to store the value that those variables contain, which is whatever the user typed in.


The string is not wrapped in double quotes.... so I don't see how this is interpolation

# This isn't string interpolation
puts "Item: " + item['name']
puts "Quantity: " + item['quantity'].to_s

#This is
puts "Item: #{item['name']}"
puts "Quantity: #{item['quantity']}"

Still don't understand item['name']

item = {}
item['name'] = "Orange"
puts item['name'] #prints "Orange"

item is a hash, the string 'name' (or "name") is a key on that hash which happens be of the string type, and which has a corresponding value of "Orange" (also the string type)

I think I get it now. It just seems weird to me. So by typing list["name"] I am accessing the value of the name variable that is contained within the list variable. Also "List :" + list["name"] is the same as saying "List: #{list['name']}" Am I saying that right?

thanks

Samuel Ferree
Samuel Ferree
31,722 Points

yes, you are accessing the value in the list hash, that is mapped to the key "name"

and yes, those two lines behave slightly differently, but essentially product the same output.

Samuel Ferree
Samuel Ferree
31,722 Points

Ah okay, let me see if I can help.

string interpolation doesn't make sense to me

The main difference between single and double quotes that that double quoted strings allow you to do string interpolation.

Simply put, string interpolation allows you to concisely place values in a string

  name = "Sam"
  str1 = "Hello " + name
  str2 = "Hello #{name}"
  # str1 and str2 have the same value

Single quotes is useful for using strings, inside string interpolation

   "Hello hash["key"]" #not valid
   "Hello hash['key']" #valid

My output doesn't print grocery either

I can take a look at your code if you post it

Why is the name in square brackets. I thought item["name"] would return the corresponding value to that key in irb; so why is it single quoted and not double quoted?

It's single quoted, because it's inside a double quoted interpolated string. normally single vs double quotes doesn't make a difference, but in this case... the single quotes are needed to not confuse the interpreter

hash["key"] == hash['key'] # returns true

And on top of that I see that is says List['items'] in one place and List["items"] in another place but why are they written differently?

See above.

def create_list 

  print "What is the list name? "
  name = gets.chomp

  shopping_list= {"name"=> "name", "items"=> []}

  return shopping_list
  end

def add_list_item

  print "What is the item exactly? "
  item_name= gets.chomp

  print "How much is it? "
  quantity= gets.chomp.to_i


  list_item= {"name"=> item_name, "quantity"=> quantity} #notice the values are variables and have no quotes

  def print_list(list)

    puts "List:  #{list['name']}"   #calling list name with string interpolation
  puts "------"

  list["items"].each do |item|    #takes each item in array of list items and assign it to a var called item
    puts "Item: " + item['name']
    puts "Quantity " + item['quantity'].to_s
    puts "-------"

  end
    end



  return list_item

  end

list= create_list()
puts list.inspect   # essentially the user types in anything for the list name and it outputs the                           #shopping_list hash 
list['items'].push(add_list_item()) # item gets added on to end of array 
#puts add_list_item().inspect
puts list.inspect # the thing returns the hash shopping_list that contains an array. The array contains the list_item hash. {"name"=>"name", "items"=>[{"name"=> "butter", "quantity"=>2}]}

print_list(list)
puts "Item: " + item['name']
puts "Quantity: " + item['quantity'].to_s

#The string is not wrapped in double quotes.... so I don't see how this is interpolation
# Still don't understand  item['name']  . What name are we talking about: variable or key or string???
Samuel Ferree
Samuel Ferree
31,722 Points

So list is a hash, and list["items"] is a list.

list = { "items" => [] }

list["items"] gets the ruby list of items, which themselves are hashes... I know it's confusing, but it's done this way because the list has other attributes to, like name.

so once we have the ruby list of items, we can iterate through them with the .each method.

.each takes a block, you don't need to worry too much about blocks, but basically, the code between the do and end is run for each item in the list.

list["items"].each do |item|
  #all of the code here will execute for each item in the list
end

Consider the following trivial example, of using a list of numbers, and the .each method to count

nums = [ 1, 2, 3, 4, 5 ]
nums.each do |num|
  puts "#{num}..."
end

This would print the numbers counting up to 5. since there are 5 numbers in the list, the puts statement runs 5 times, each time through the loop, num is set equal to the next item in the list.

putting it all together, we're getting the ruby list of items in the ruby hash define by the variable list using the items key

list["items"] # returns a list of hashes representing grocery list items

Then we call the each method on this list, iterating through each item

list["items"].each do |item|
  # This code will run for each item in the list, accessible via the variable 'item'
end

Then, we access the values of the item hash by using their keys.

  list["items"].each do |item|    #takes each item in array of list items and assign it to a var called item
    puts "Item: " + item['name']
    puts "Quantity " + item['quantity'].to_s
    puts "-------"
  end

don't understand... I need to talk to someone to understand this. It's too confusing

also the string interpolation doesn't make sense to me. Where did we learn this? What video was that. My output doesn't print grocery either; it just says List name unlike the video that says List Groceries. Why is the name in square brackets. I thought item["name"] would return the corresponding value to that key in irb; so why is it single quoted and not double quoted? See I don't understand so much, I can't even articulate a question. And on top of that I see that is says List['items'] in one place and List["items"] in another place but why are they written differently?

so it's doing essentially items["name"] and items["quantity"] , getting the value for each key but using a newly created |item| variable instead. That item variable can be anything though. like food["name"] or food["quantity"] .

Am I correct?

Samuel Ferree
Samuel Ferree
31,722 Points

yeah, each pass through the loop, it assigns the current item in the list, to the variable specified between the pipes.

These are all the same.

  list["items"].each do |item|    #takes each item in array of list items and assign it to a var called item
    puts "Item: " + item['name']
    puts "Quantity " + item['quantity'].to_s
    puts "-------"
  end

  list["items"].each do |i|    #takes each item in array of list items and assign it to a var called item
    puts "Item: " + i['name']
    puts "Quantity " + i['quantity'].to_s
    puts "-------"
  end

  list["items"].each do |foobangbarbuzz|    #takes each item in array of list items and assign it to a var called item
    puts "Item: " + foobangbarbuzz['name']
    puts "Quantity " + foobangbarbuzz['quantity'].to_s
    puts "-------"
  end