#544 — March 18, 2021

Read on the Web

Ruby Weekly

Bringing Encrypted Attributes to Active Record Models — The folks at Basecamp are extracting how they encrypt attributes for their ‘HEY’ email app in this pull request to Rails core. There’s also support for deterministic encryption and queryable encrypted values. Lockbox is a pre-existing approach, too, if you need something right now.

Ruby on Rails

Awesome Print 1.9: Pretty Print Your Ruby Objects with Style — Awesome Print has long provided a fantastic way to ‘pretty print’ Ruby objects in a way that goes far beyond what the standard library's pp offers. The project went stale for long enough that a fork called Amazing Print was formed (and continues to get releases) but now the original is back with its first release in over 3 years supporting Rails 5 and up, Ruby 2.7 and up, and more.

Awesome Print Team

The Easiest Way to Monitor Ruby: Automatic Instrumentation — Monitoring your Ruby apps can be hard. You need to understand what you need to monitor, instrument code, and then make sense of all the data. Automatic instrumentation makes that whole process easier and streamlined. Find out how you can do it.

AppSignal sponsor

Spree 4.2.0 Released with Rails 6.1 and Ruby 3.0 Support — Spree, a modular open source e-commerce system, is one of the longest standing Rails projects out there and it’s had a slew of updates including a new, responsive admin UI, expanded and improved i18n support, and better multi-store support.

Spree Commerce

▶  Discussing Ruby Garbage Collection and WNB.rb with Jemma Issroff — Jemma is not only the author of our Tip of the Week but she’s currently writing a book about managed garbage collection, with a focus on Ruby, and spoke with Brittany Martin here.

Ruby on Rails Podcast podcast

Quick Bits

💻 Jobs

Senior Ruby Engineer — Join a small team and help build out our automated direct mail platform, used by high growth startups to help optimize their marketing campaigns.


TravelJoy | Engineer #4 | Full-Stack | Remote in USA | Full-Time — TravelJoy is the market network for leisure travel. Thousands of travel agents love and depend on our product every day.

TravelJoy - Bring the joy back into travel planning

Find Your Next Job Through Hired — Create a profile on Hired to connect with hiring managers at growing startups and Fortune 500 companies. It's free for job-seekers.


📘 Articles & Tutorials

Boring Breadcrumbs for Rails — Rather than use a library to implement this common Web UI pattern (although there are links to several, if you prefer) you can roll your own breadcrumbs system pretty easily, says Matt.

Matt Swanson

Rails: How to Reduce Friction at the Authorization Layer — While gems like Pundit are nice, they are full of non-DRY policies and authorization often needs more for a given situation. can_dig? => true

John Nunemaker

Logging in Ruby with Logger and Lograge — Various options and approaches to logging including customizing format (a la JSON) along with what actually gets written to the logs.

Diogo Souza (Honeybadger)

Complete Peace of Mind Rails Hosting — If you need 100% peace of mind Rails hosting, OpsCare is for you. We keep your application online and performing, 24 hours a day, 7 days a week.

OpsCare by reinteractive sponsor

Nested Forms in Rails — If you ever have to use nested forms, this kind of reference can save you hours of frustration.


SOLID Design Principles in Ruby — Can we ever have enough examples of SOLID principles? (Hint: No.)

Milap Neupane

Sharing Common Code Between Rails Controllers with the Scoped Concern Pattern — Tired of repeating common controller actions?

Matt Swanson

▶  Keeping Rails Apps Organized with Tom Rossi

Rails with Jason Podcast podcast

The Two Ways to Dockerize a Rails Application

Jason Swett

🛠 Code and Tools

Ltree Hierarchy: Organize ActiveRecord Models Into a Tree using Postgres's Ltree Type — Pat Shaughnessy (a true blast from the past, eh?) covered the topic of using LTREE with Postgres back in 2017 if you want to understand more about the technique.

Cédric Fabianski

PgHero 2.8: A Performance Dashboard for Postgres — A dashboard built in Ruby (and used at Instacart) that lets you look at basic performance stats including live queries, maintenance status, and connections.

Andrew Kane

Seamlessly Integrate Video into Your Ruby App

Mux sponsor

Maildown: Write ActionMailer Email Templates in Markdown — They then get sent in HTML and plain text, as you’d expect.

Richard Schneeman et al.

sr_mini: A Minimal Rails App That Showcases How to Use StimulusReflex

Nate Hopkins

yr_weather: Downloads and Parses YR.no Weather Forecasts — A reader sent this in as an example of scripting a weather forecast system fueled by data from Norway’s state broadcasting weather authority (but it covers the whole world and seems to be quite permissive as a public API).


💡 Tip of the Week

Triple Equals (===)

Have you ever wondered what is happening behind the scenes of a case statement in Ruby? We can write cases that look like this:

case input
when "exact match"
  "Found an exact match"
when /regex match/
  "Found a regex match"
when String
  "Input is a string"
when (1...10)
  "Input falls within this range"

Although this example doesn't actually do anything useful, it does illustrate something interesting: Ruby's case statements allow for a whole host of different types in their when clauses. In this example alone, we have a String, Regexp, Class and a Range. This is all because case statements in Ruby compare using ===.

Well, this begs the question, what exactly is a === comparison? === is most straightforward when thought of as a membership comparison. It is checking if the argument on the right of the === is a member of the argument on the left.

Here are some concrete examples based on the above:

# "exact match" is a member of "exact match"
"exact match" === "exact match"
=> true

# "string which regex matches" is a member of the
# set of matches described by /regex match/
/regex match/ === "string which regex matches"
=> true

# "another string" is a member of the String class
String === "another string"
=> true

# 1 is a member of the range (1...10)
(1...10) === 1
=> true

Now we more deeply understand what case statements are using. To read more details on the === in any specific class, take a look at the docs for that class. For instance, the === docs for String are here.

This week’s tip was written by Jemma Issroff.