2

I have two classes List and Task:

class List
  attr_reader :all_tasks

  def initialize
    @all_tasks = []
  end

  def add (task)
    @all_tasks << task
  end

  def show
    all_tasks
  end
end

class Task
  attr_reader :description

  def initialize (description)
    @description = description
  end
end

And the following code:

breakfast = Task.new("Make Breakfast")

my_list = List.new
my_list.add(breakfast)
my_list.add(Task.new("Wash the dishes!"))
my_list.add("Send Birthday Gift to Mom")

puts "Your task list:"
puts my_list.show

Output:

Your task list:
#<Task:0x00007fd9e4849ed0>
#<Task:0x00007fd9e4849e30>
Send Birthday Gift to Mom

I want to be able to show the tasks of the to-do list as a string and in the same time have the Task instances as objects inside the array. How do I do that?

1
  • Note that although attr_reader :all_tasks looks like read-only, it allows the caller to modify all_tasks, e.g. my_list.all_tasks << 'another task'. Commented Oct 17, 2017 at 7:17

2 Answers 2

3

Considering the code in your question, it would suffice to simply redefine method to_s of Task.

class Task
    attr_reader :description
    def initialize (description)
      @description = description
    end

    def to_s
      "Task: #{description}"
    end
end

Output

Your task list:
Task: Make Breakfast
Task: Wash the dishes!
Send Birthday Gift to Mom
Sign up to request clarification or add additional context in comments.

4 Comments

It might be worth noting that this works because puts prints each element on a new line if called with an array. To have more control over the output, List#show should return a string.
Thank you that really helped. Since I am only started to learn ruby(my second week), i would like to now, why the moment I write the def to_s, ruby doesn't display the string representing the output anymore?
@Stefan Can you please also explain what List#show is/means and how to implement it? It might be stupid question but I won't learn anything if i don't ask :-) Thank You again for your help
@SebastianPeter List#show refers to the show instance method within your List class. It currently returns an array, whereas it probably should return a string. I've posted an answer showing a slightly different approach.
1

You call add with Task instances:

my_list.add(Task.new("Wash the dishes!"))

and with String instances:

my_list.add("Send Birthday Gift to Mom")

Having a mixture of both, Task and String instance in one array makes it harder to work with. Unless you really want or need this, I would change add, so it converts string arguments to Task instances:

class List
  # ...

  def add(task)
    task = Task.new(task) unless task.is_a? Task
    @all_tasks << task
  end
end

is_a? checks whether task is (already) a Task. If not, it is passed as an argument to Task.new which returns such instance. This ensures, that @all_tasks only contains Task instances.

Your current implementation of List#show simply returns all_tasks, i.e. an array. Although puts is able to print arrays ...

If called with an array argument, writes each element on a new line.

... I would change show to return a formatted string:

class List
  # ...

  def show
    all_tasks.map { |task| "[ ] #{task.description}" }.join("\n")
  end
end

map returns a new array with a string for each task instance. Each string contains the corresponding task's description, prefixed by [ ] which should resemble a little check box. join then concatenates these string elements using "\n" (newline) as a separator.

Output:

Your task list:
[ ] Make Breakfast
[ ] Wash the dishes!
[ ] Send Birthday Gift to Mom

1 Comment

Thank You again. This is even better. I feel like i made a big jump in understanding Ruby.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.