I’ve been a Ruby Software Developer since 2012. It’s more than seven years of experience in developing web applications using Ruby and Ruby on Rails framework.
When I joined SourceLevel, the main application already existed. Before becoming a Startup, SourceLevel was called Ebert. Folks from Plataformatec did an excellent job building the foundations of what now is our product.
It’s been Ruby on Rails application since the beginning. Currently, we run under Ruby on Rails 5.1.7 version, even though we intend to upgrade to 5.2.3 soon.
We are a small team. Our efforts need to be well measured, and developers must work precisely on what matters. We need to find the “nirvana” among developing new features, fixing bugs, dealing with technical debts – as Martin Fowler explained -, and chore demands, which is something important to our culture.
Importing to the project a well tested and working gem for a specific job save us time. Although it also adds complexity and external dependency, its impact on productivity and velocity is significantly higher.
Developing and internally maintaining tools is an unnecessary effort for now. It is crucial to keep in mind that adding too many dependencies is terrible, and finding the balance between using a gem or developing our solution is hard.
That said, I’d like to share a list of those gems we are currently using in our product. Below I give some context on which problem each gem solves and how they save us time!
I organized this section in categories that describe a bit of what and why we use each gem.
The fact we chose a specific gem, does not imply I recommend your project to use it. My idea here is to share a bit more about SourceLevel development.
We are heavy Markdown users! We produce internal documentation in Markdown. The docs page is a static site entirely written in it (and built with
In the main app, we use
markerb to parse markdown content and convert it to HTML. Comments to Github, issue explanations and repository badges are examples of markdown usage. Although its repository is archived and doesn’t accept contributions anymore, it does a pretty good job. It works with both
redcarpet. We chose
redcapet as our processor.
Another useful gem is
charlock_holmes. As accurate as Sir Arthur’s character Sherlock Holmes, this gem detects character encoding for given files or chunks of text. Under the hood,
charlock_holmes benefits from the set of libraries from ICU.
We love PostgreSQL! It is reliable, open-source and has lots of functionalities that make it attractive. The ability to create materialized views is one of them.
Working with views in
Rails is kind of messy. That’s why we added
scenic to the SourceLevel main app. This gem adds methods to
ActiveRecord::Migration that allow managing views in migrations.
We use materialized views to scope content. If you don’t know what it is, here it goes: it’s a SQL query whose results work as stored in a regular table. Long-running queries or segmented results can be fetched from appropriate views reducing both time and code complexity.
pghero gem, besides the ability to kill them if you need, also ships with a UI for you to monitor other performance indicators.
Another essential dependency is
dalli. It does an incredibly good job of storing and retrieving memcached records. It’s thread-safe and allows us to run
Rails.cache smoothly throughout the codebase.
SourceLevel integrates with Github in many ways. Our tool can comment in Pull Requests, update build status, listen to interaction events via webhooks, and much more. Instead of creating a lib, we picked
octokit to do the job of creating a layer of abstraction. It is a very complete and well-maintained gem.
Besides Github, our main app integrates with other applications, such as Metabase. They required us to develop a simple API Client for each. To do that, we have chosen
Faraday because it is straightforward, robust, flexible, testable, widely used, and easy to use.
Our team is adept at TDD. We love the red, green, and refactor cycle. As it has a significant impact on our culture, I point three essential gems that help us daily:
minitest , and
My general workflow is 1) write a test for a non-covered scenario, 2) watch it fail, 3) write the minimum amount of code to make it pass, and 4) refactor. It would be so time-consuming to run all the test suits every time I change a piece of code that probably I give up.
That’s why I like
guard that much. This gem can detect and automatically run only the proper test scenarios that a given change affects. With fast feedback, I can move forward in development.
There always be, though, those scenarios we need to investigate what’s going on under the hood. When I need to answer questions like “what’s the value of a variable?”, “does an if statement satisfies its condition?” and “is a method called?” I turn to
pry-byebug. There are a lot of articles about this gem out there. I won’t stick to this subject in this blog post.
Finally, another topic I want to address is that we use
RSpec is much more accessible, I like the way
minitest induces you to keep all test scenarios contained within themselves.
RSpec makes code reuse simple. The bad part is that reusing too much code turns your development more expensive. You tend to spend too much time digging throughout the codebase. Questions like “where this data comes from” and “where did this record change its state?” are often raised while writing tests.
I know, it depends heavily on the developer. It’s not an exclusively tooling problem. But, in my experience, using
minitest makes contained tests more natural, even though there is more duplicated code.
I could write an entire book chapter about
rspec vs. minitest. For now, I hope I summarized well enough for you to get the overall idea.
I presented some gems we use at SourceLevel. Then I explained what they do and why we chose them. With this blog post, I intended to show a little bit more about the backstage of our product.
I hope you like it!