I recently shared a couple of my favorite gems on Twitter. And people asked for more! These are my top 5 must have gems for any Rails app + my reasoning and some tips on how to best use them.
Pry - development console
If you're a person who uses
puts for debugging your code, try this now! This gem is the secret to writing Ruby quickly and confidently.
gem 'pry-rails', group: [:development, :test]
Pry is a powerful developer console. You can put breakpoints into any of your code by typing
binding.pry. Then when you run your code, the application will stop at that point and you can use pry to explore the state of your code.
Some tricks: run
ls to see available variables. Run
show-source method_name to see the source of a method. And so many more.
binding.pry in the test code, run the test and then use the console to figure out the rest of my test.
I rely on Pry so much that I often write most of my code in a console, and then I'll copy it into a file.
Flipper - feature flags
You know how people often say you shouldn't copy what big companies do? This one is the exception. Big companies ship code using feature flags, and you absolutely should as well.
I've used this gem at Product Hunt, GitHub and now PlanetScale. You couldn't pry it from my cold dead hands.
Learning to use feature flags in your application & development flow is life changing. This allows you to break the dreaded deploy & release (where releasing feature requires a deployment). Instead you can deploy code, and enable it just for your own user, a group of users, or percentage of users.
Having feature flags allows you to ship small changes quickly & confidently. Implementing this on flow for your team is one of the highest leverage actions you can take.
# code path A
# code path B
Personally, I prefer the ActiveRecord adapter with memcached for caching. Everywhere I've worked we've ended up customizing the included UI as well. It's incredibly flexible and easy to work with. Take a look at FlipperCloud for more UI options.
Make sure you read about the memoization and preloading features, which will help you out when you get so addicted to using feature flags that you have hundreds of them.
Sidekiq - background jobs
All Rails apps eventually need a background worker queue. Sidekiq is the greatest of them all. It uses Redis, is super fast/efficient and has every feature you could need. It's also a well supported and profitable open source project.
I prefer using Sidekiq directly instead of with ActiveJob. In my experience you get better performance out it. Sidekiq has more features built into it which are easier to make use of when using it directly. In the past I've liked using ActiveJob in case "we need to switch". But in my years of doing this, it has never been an issue.
I wrote a post a while back on how PlanetScale uses Sidekiq: How we made PlanetScale’s background jobs self-healing. The decision continues to pay off for us.
Rack::Attack - rate limiting
Eventually, every application needs some basic form of rate limiting. Even if it's for something simple like protecting your login form from password stuffing.
This is where you should use rack-attack. It allows you to add basic rate limiting to your application. I generally suggest setting one high limit for the entire application, this will protect you from general abuse. And then adding specific lower rate limits for important endpoints. Things like your login/signup and password reset forms.
Rack::Attack.throttle("limit registration attempts per IP", limit: 6, period: 60) do |request|
if request.path == "/register" && request.post?
This tiny code snippet will limit a user to signing up with the same IP address 6 times per minute.
Prometheus client - metrics & alerting
Once your application is in production and supporting a business, it's critical to have alerting that informs you when something is going wrong.
For this, I love using Prometheus (prom for short!). Prometheus is a time series database for storing metric data. It's incredibly powerful and a critical tool in many companies alerting infrastructure.
The mistake people make: I find that most teams will alert on things like "high error rate" or "slow page loads". These are useful alerts to have, but they often don't cover what is most important to your application.
Do this instead: I recommend adding metrics that measure the success of your mission critical user flows. For example: for a payments application it is important that every payment is processed within 5 seconds. If you have a
Payment model in your application that stores the timestamps of each payment, you can easily setup a metric to monitor this.
payment_metric = Prometheus::Client::Gauge.new(:slow_payments)
slow_count = Payments.slow_payments_in_last(15.minutes).count
This will record the number of payments that were slow in the past 15 minutes. Based on this metric you can setup an alert whenever it goes over a certain threshold. This indicates a problem with your application that is impacting users!
Once you get good at this, you've find tons of ways to measure your application and setup alerts on it. I find it's helpful to add new alerts for every critical feature. Soon you'll be getting notified of problems sooner than a customer can email into support!