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 Booleans Build a Simple Todo List Program Part 6: Printing Todo Lists

Sean Flanagan
Sean Flanagan
33,235 Points

Problem with 'complete' items

Hi. I have a problem with the complete items.

todo_list.rb

require "./todo_item"

class TodoList
  attr_reader :name, :todo_items

  def initialize(name)
    @name = name
    @todo_items = []
  end

  def add_item(name)
    todo_items.push(TodoItem.new(name))
  end

  def remove_item(name)
    if index = find_index(name)
      todo_items.delete_at(index)
      return true
    else
      return false
    end
  end

  def mark_complete(name)
    if index = find_index(name)
      todo_items[index].mark_complete!
      return true
    else
      return false
    end
  end

  def find_index(name)
    index = 0
    found = false
    todo_items.each do |todo_item|
      if todo_item.name == name
        found = true
      end
      if found
        break
      else
        index += 1
      end
    end
    if found
      return index
    else
      return nil
    end
  end

  def print_list(kind='all')
    puts "#{name} List - #{kind} items"
    puts "-" * 30
    todo_items.each do |todo_item|
      case kind
      when 'all'
        puts todo_item
      when 'complete'
        puts todo_item if todo_item.complete?
      end
    end
    puts "\n"
  end
end

todo_list = TodoList.new("Groceries")
todo_list.add_item("Milk")
todo_list.add_item("Eggs")
todo_list.add_item("Bread")
todo_list.add_item("Butter")

if todo_list.remove_item("Eggs")
  puts "Eggs were removed from the list."
end

if todo_list.mark_complete("Milk")
  puts "Milk was marked as complete."
end
puts "\n"

todo_list.print_list
todo_list.print_list('complete')

Output:

Eggs were removed from the list.                                                                 
Milk was marked as complete.                                                                     

Groceries List - all items                                                                       
------------------------------                                                                   
[C] Milk                                                                                         
[I] Bread                                                                                        
[I] Butter                                                                                       

Groceries List - complete items                                                                  
------------------------------                                                                   
todo_list.rb:61:in `block in print_list': undefined method `complete?' for #<TodoItem:0x0055d41a0
903c8 @name="Milk", @complete=true> (NoMethodError)                                              
        from todo_list.rb:56:in `each'                                                           
        from todo_list.rb:56:in `print_list'                                                     
        from todo_list.rb:84:in `<main>'     

I would appreciate any help. :-)

2 Answers

John Steer-Fowler
PLUS
John Steer-Fowler
Courses Plus Student 11,734 Points

Hi Sean,

The error message from the console is telling you what is wrong:

todo_list.rb:61:in `block in print_list': undefined method `complete?' for #<TodoItem:0x0055d41a0
903c8 @name="Milk", @complete=true> (NoMethodError)

This error message is telling you that on line 61 of todo_list.rb you have an undefined method 'complete?' for the TodoItem Class instance 0x0055d41a0903c8.

This would either tell me that 'complete?' is a syntax error on the method you wanted to use, OR you have not yet defined a method called 'complete?' for use with the TodoItem class.

This line here (line 61):

puts todo_item if todo_item.complete?

Hope this helps sort the issue out

Sean Flanagan
Sean Flanagan
33,235 Points

Looks like I made the same mistake twice by putting in a question mark that shouldn't have been there, although the question mark worked fine for Jason.

Thanks again John. :-)

John Steer-Fowler
John Steer-Fowler
Courses Plus Student 11,734 Points

Hi Sean,

When you say it worked fine for Jason, did Jason define the complete method with a question mark?

When calling methods, you have to be exact with the spelling. If you define the method with a question mark you need to refer to it with a question mark also. I am guessing Jason defined the complete method with a question mark.

-- Off Topic --

Question marks can be useful in method names that seem as though they are asking a question. For example here we are using 'complete' in the context of asking the question 'is it complete?'. It feels natural to use complete? as the method name in this context when trying to determine the state something is in. Other examples are 'alive?' or 'dead?'.

Using a question mark doesn't make sense in some context. For example a method named 'find_names' to find the names of all the people in a room would not make sense to be called like this room.find_names?.

I am sure you already understand this, but it's sometimes nice to have things explained a little more.

Keep up the good work

Sean Flanagan
Sean Flanagan
33,235 Points

Hi John.

I looked at my code again and I noticed that the method was unfinished; there was no "incomplete" line that also had a question mark. I wonder if that had anything to do with my problem.

I think I understand what you say about "find_names". In plain English, "find names" isn't a question so a question mark would be inappropriate. Would "room.find_names" without the question mark be better?

Thanks John. :-)

John Steer-Fowler
John Steer-Fowler
Courses Plus Student 11,734 Points

That might have something to do with it. I am not too sure without seeing all of your code.

My find names example was a situation where a question mark would not make sense.

We usually use question marks in a method name when the method is used to find the state of something, ie. Dead or Alive, Complete or Incomplete, Exists or Doesn't Exist etc.

For example, rather than our find_names, if we were using a method to find whether a name existed in a room then we could call our method name_exists?. This would make a lot more sense than find_names? because it is as though we are asking the program a question, "Does this name exist?" rather than "Find all the names in the room" which is a statement not a question.

This might help clarify