Learning Ruby with Exercism

Ed Packard
5 min readJul 9, 2021

It was a fairly long journey to get from the point where I decided I wanted to change careers and undertake a coding bootcamp (late 2019) and actually starting at Makers (summer 2021). While I counted down the months at my previous job, I spent a lot of my free time learning Ruby, first via Chris Pine’s excellent tutorial, followed by Codecademy, then by completing a large number of katas on Codewars.

After I finished my interview with Jonny at Makers earlier this year, he suggested that I might also enjoy the Ruby track on Exercism and said that it would help me to gain familiarity with the command line and test-driven development. He was right on all counts.

Exercism is a really interesting concept: a free platform where users can choose to undertake learning tracks across a large number of programming languages. Each track consists of various core exercises (you have to complete your current exercise to unlock the next one) as well as side exercises which are unlocked as you go along. The pace of Exercism is slower than, say, Codewars because after the first couple of automated core exercises you are reliant on how quickly human mentors can review your code: these mentors offer feedback, and either progress you to the next exercise or tell you what you need to do for your next iteration.

I’ve used Exercism on both Windows and Mac, and it works well on both although it can be a bit tricky to set up (there is a step-by-step guide on getting started here). It encourages a solid workflow mentality: you ‘pull’ the exercises from the Exercism website via the command line and ‘push’ your answers when they are completed. You figure out answers to the tasks on your local machine and then check your code against the test files which are included in each exercise package. I’m now at the end of the second week of the Makers pre-course, and most of this week has involved a similar workflow in terms of completing Ruby challenges (although we haven’t started messing around with classes and methods to the same extent as Exercism yet).

The instructions for each Exercism task are typically quite concise and you have to get used to figuring out failed test messages: I often deliberately fail the tests a few times just to work out the required names of the class and methods for a particular challenge. You could always peek inside the test files but I try to work out as much as possible from the failure messages. You do eventually have to start messing around with the test files as usually a few of the required tests skip at first: this means that once you pass the first test, you comment out skip on the next test, pass that, and so on.

To show the value of Exercism, I’d like to highlight how good mentoring helped me develop my coding skills for the following challenge:

Manage a game player’s High Score list.

Your task is to build a high-score component of the classic Frogger game, one of the highest selling and addictive games of all time, and a classic of the arcade era. Your task is to write methods that return the highest score from the list, the last added score and the three highest scores.

In this exercise you’re going to instantiate a class and add some instance methods. http://ruby-for-beginners.rubymonstas.org/writing_classes/initializers.html

A HighScore accepts an array with one or more numbers, each representing one ‘game score’. The Array class can offer inspiration for working with arrays. https://ruby-doc.org/core-2.5.1/Array.html

For my first effort at this exercise, I found the hardest part was keeping track of the instance and local variables. My thinking was that the input array of scores (I called it scores_list below) should be turned into an instance variable in the initialize method, and then I could use that when writing the required methods (although once I’d defined the scores method to return the value of @scores_list I then used scores in the following methods):

class HighScores
def initialize scores_list
@scores_list = scores_list
end

def scores
@scores_list
end

def latest
scores[-1]
end

def personal_best
scores.max
end

def latest_is_personal_best?
latest == personal_best
end

def personal_top_three
scores.max(3)
end
end

My mentor, while liking my use of the .maxmethod and saying that my code was “pretty nice” overall offered some sage advice on improving this. They suggested that I use attr_reader to deal with the strange way I’d handled scores_list and the scores method, and also encouraged me to think of a way to “avoid having to do the work every time each of these methods are called”, in other words generating all the answers when a new object of the HighScores class is initialized (of course, the assumption is that the scores don’t change — which for the purposes of this exercise is true). I’ll confess that I’m not super confident with classes in Ruby yet, but this was a good chance to practice. Here’s what I came up with for my second go:

class HighScores
attr_reader :scores, :latest, :personal_top_three, :personal_best

def initialize scores
@scores = scores
@latest = scores.last
@personal_top_three = scores.max(3)
@personal_best = personal_top_three.first
end

def latest_is_personal_best?
latest == personal_best
end
end

This is much more concise than my original effort: the only problem I had was the latest_is_person_best? method which I could not get to work with attr_reader owing to the question mark at the end. While not spoon-feeding me, my mentor pushed me in the right direction, suggesting that I look at alias and undef. I went through a few more iterations, with my mentor mainly offering advice on formatting at this stage (they were especially displeased at the amount of trailing whitespace in my code). In any case, my final iteration looked like this:

class HighScores
attr_reader :scores,
:latest,
:latest_is_personal_best,
:personal_best,
:personal_top_three

alias latest_is_personal_best? latest_is_personal_best
undef latest_is_personal_best

def initialize(scores)
@scores = scores
@latest = scores.last
@personal_top_three = scores.max(3)
@personal_best = personal_top_three.first
@latest_is_personal_best = latest == personal_best
end
end

I was really pleased! Although my original submission had worked, I couldn’t help but feel it was rather amateurish compared to my final effort. My mentor, by encouraging me slightly outside my comfort zone, helped me to get to grips with classes and writing code in a more ‘functional’ way.

I’d strongly recommend Exercism for anyone learning Ruby (and, I assume, any of the other supported languages) with two provisos: one is that Exercism is going to upgrade to v3 later this year, which means that the experience as I have described it is likely to change (and this also means that time is being diverted away from mentoring at present). The other is that every mentor is unique (and you will typically get a different mentor for each individual exercise): while almost all of my mentoring experiences have been valuable, some mentors are happy to pass code as long as it passes the tests (though they will still offer feedback), while others will help you to improve before sending you on your way.

I hope you have found this blog useful, and please do take a look at Exercism!

--

--