Contributing to Open Source software can be overwhelming. There are a lot of projects that need help and welcome new contributors, but getting started can be hard.
Each ticket description and debate makes even the smartest software developer feel like only experts can solve the issue at hand. But it doesn’t have to be like this. You don’t need to start contributing by trying to fix bugs. Especially if the project is a library that you use regularly. Sometimes, the best contribution you can make is by solving a problem or a little annoyance that you havefound while using the library.
If the project is not one that you use regularly, you can start contributing by fixing the README file. Fixing typos in comments. Clarifying some piece of code. Every contribution of this type is usually welcomed and appreciated by project owners.
That said, I’ll share here my first two contributions to the open source world and what problems they helped to fix.
What does this error even mean?!
My first contribution was to the rspec-mocks gem. This is a library for the Ruby programming language that I regularly use at work to create mocks and stubs for classes and objects. It makes writing unit tests for different isolated components of your application easier and faster. It’s something I use every day.
One of the features that I use constantly is constant stubbing. Let’s say we have the following class:
In this snippet of code we’re paginating rows from the table SomeBigTable , and using a defined number of max elements per page of 2000.
How do we test this piece of code? Specifically, how do you test that the pagination is working effectively? Certainly, you won’t create more than 2000 records in your tests! That’s just madness. It would be nice if we could use a different MAX_PER_PAGE value only in the context of your tests. That’s what constant stubbing in RSpec gives you.
Let’s see what a simple test would look like for this class using this feature:
In this code we’re replacing the max per page value from 2000 to 2. We create 3 entries for the table SomeBigTable . Naturally, if the max per page value is 2, then the result[:items] array should have only two items and the number of pages should be 2.
We run this test and…
NoMethodError:
undefined method `sub' for 2000:FixnumWhat happened? Certainly this can’t be a bug in our code. We don’t even call sub anywhere in the Foo class or inside our test.
Finding the problem
After some frustrating minutes (read: hours) of debugging and trying to find the problem (note that this is a simplified version of the code: in the actual situation, I had several classes and methods being called), I decided to look under the hood of this stub_const method (which was the only possible place for the origin of this error).
Here’s the process I followed (which, is the general process you should follow when preparing to contribute to any open source project) in order to hopefully find and understand the origin of this error:

First step is to fork the project. You should now have a copy of the project in your github profile. Now we need to clone that copy to our machine.
$ git clone [email protected]:your_username/project_name.gitNow we need to create a new branch in our copy for our feature/bug fix.
$ git branch checkout -b my_bug_fixNow is the time to fix a bug, implement a feature, fix typos, etc. In my case, I wanted to see what the method stub_const was doing and hopefully find something that indicates why the error above was being raised.
First, I searched the project for the method stub_const and I quickly found its definition:
There’s our bug! We need to be passing a string to the method instead of an actual constant (tip: read the documentation of the method!). So I should be writing
stub_const("Foo::MAX_PER_PAGE", stubbed_max_per_page)Instead of
stub_const(Foo::MAX_PER_PAGE, stubbed_max_per_page)Anyone who would have carefully read this documentation would not incur this error. But we, as programmers, have the power to make life easier for other programmers. Why throw a cryptic error message in this case, which leaves the programmer confused as to what he did wrong, when we can quickly help him understand what he did wrong? So, I figured I should do something so that no other developer doing something similar would waste time trying to figure out what the problem was and avoid the need to dig through this gem’s source code. My simple fix was inside the method stub of the class ConstantMutator . The original method was:
And so I changed it to perform an additional check on the constant_name argument and to raise an informative error message if its type is not a string:
Every time the stub_const method is called with anything other than a string, the error stub_const requires a String, but you provided a ... is raised, which is enough to know how to use fix my original problem! Here’s the associated Pull Request on Github. Note that this contribution was nothing more than raising a helpful error in a specific situation to help my debugging process. I didn’t fix any bug or implement a new feature. I just tweaked something that was slowing down my development process when using this library.
This is not the result I was expecting.
When you’re using a third party library, you’re somewhat agreeing to a contract. As long as you provide the right parameters to a function/method, you expect to get a certain result. Sometimes, though, that’s not the case. When this happens, it’s usually a good time to think if the result that you got was because of your misuse of the API or maybe, there’s a bug somewhere in the library. The latter is not the most common case, but it happens. This situation led me to fix a nastybug in the languages list ruby gem.
This gem exposes a list of known languages and their isocodes and names. It’s simply a big array with every known language. For my use case, I needed to implement a function that would take as argument a string and return back every language whose name matches (i.e, includes) that string.
No big deal, I thought, so I wrote the code:
If you’re reading this code and already found a problem, you’re a smart ruby programmer. For the ones who haven’t figured out what the problem is, we need to take a look at the keep_if method. keep_if will delete every element of the original array that doesn’t make the block evaluate to true, i.e, it mutates the array. The problem is I didn’t know this when I was writing this code. I did know that the method would reject any element that didn’t evaluate the block to true, but I didn’t know it would mutate the array (I was used to associate only bangmethods as methods that mutate the receiver).
This revealed a problem in the gem. Every time I called this method, the constant LanguageList::ALL_LANGUAGES would get smaller in size, because the array was being mutated. Needless to say, I spent a good amount of time trying to understand why that was happening.
As soon as I understood the problem, I immediately opened a Pull Request (following the same steps as above) to fix the problem. It was as simple as adding a freeze call to the exported arrays. With that change, my original code would throw a proper error when calling the keep_if method (or any other array method that mutates the original array, like map!) on that array:
RuntimeError: can't modify frozen ArrayConclusions
Your open source contributions do not need to change the open source landscape. They can be as simple as fixing an error message in a library that you or your team regularly use. They can be adding tests, or fixing documentation. In my case, my first two contributions were very small, but they fixed problems big enough to cause me pain and introduce delays in my development process, so any small fix that alleviates this is going to be a huge plus for me. And it was.
Don’t be afraid to contribute. Even if your contribution is rejected, there’s always a good reason for it, and, most importantly, you’re going to learn something in the process regardless, which is always more important than a pull request merged. I believe every open source maintainer welcomes and appreciates every pull request opened, and they will gladly discuss the pros and cons of adding your feature to the code base.
Nowadays I work at Runtime Revolution. Working here has been, and continues to be, a great learning experience. I’ve matured professionally as a developer, focusing on building and maintaining large scale Ruby on Rails applications.