Use the Attributes API to make your Rails models more communicative
ActiveRecord is the powerful object-relational mapper at the heart of Ruby on Rails. By default, it gives you tools to quickly and easily create new database tables and map them to domain models. It follows the ethos of “convention over configuration” that David Heinemeier Hansson coined with the release of Rails. As such, with little application code, you get a powerful, database-backed model that Just Works™.
However, few lines of code do not, necessarily, mean that the lines that are there are easy to understand. Does this model have a
description? How is that
expiryfield encoded, as a Date or a Time? What fields exist on this table, again? These are examples of common questions when working in a Ruby on Rails application.
To alleviate some of these issues, you can use the Attributes API when defining your models to make them more explicit. You can also use richer data types for your fields to ease working with subsets of your models. This article will share the history of the Attributes API, then show some concrete examples of using it.
Solving the right problem
Using ox-hugo without duplicating content in the repository
My new blogging setup mashes up Org mode with Hugo using the ox-hugo library. This is part of my attempt to bring more of my work product into the single format of Org mode. Hugo has rudimentary support for Org mode through go-org, but it admittedly only tries to cover the 80/20 use case of Org mode. Since I intend to use Org mode for everything, the chances are high that I will end up with something incompatible, thus requiring me to work around the problem. I didn’t want to do that, so I stuck with the Hugo export library.
Every example that I saw of a site that uses
ox-hugoends up duplicating the Org mode documents are Markdown in the repository. This felt noisy and redundant to me so I wanted to find a way to have Netlify render the Org document to its constituent Hugo pages as part of the deploy process. This article documents the process that I now use and shares the rendering script that I wrote to process the file as part of a deployment.
Provisioning a Valheim server with Terraform
My friends and I decided we were going to give Valheim, an early-access survival game, a try. Since many of us are parents now and we’re in a socially distancing world, colocating for an evening of fun was out of the question. I decided to use the event as an excuse to practice my DevOps skills.
I use Terraform at work for a variety of things, but I don’t write enough of it to be completely comfortable. As such, I decided to use Terraform to provision a dedicated server for us. This article documents how I went about it using DigitalOcean and Terraform.
Duplicate cookies in Ruby on Rails
Ruby on Rails has an easy-to-use cookie store for managing state between requests. It has affordances for storing clear-text values, tamper-proof signed values, and encrypted values. I previously showed how you can make good use of encrypted values for handling ActionCable authentication. However, there is a case where you might end up with duplicate cookies in Ruby on Rails applications.
This article discusses cookies, shared cookies, and how the use of the Ruby on Rails cookie store may lead to apparently duplicate cookies. From that, we’ll end with three rules of thumb for using cookies and avoiding the issue.
3 Ways to Make Arel a Joy
Arel, the SQL syntax tree constructor library backing ActiveRecord, allows you to express your SQL queries without the use of fragments. ActiveRecord uses it internally to represent a variety of queries. It does this transparently using the traditional
where(key: value)syntax that we’ve seen since the early days of Rails.
In cases where you only need to write simple query predicates, the traditional syntax is what you should reach for, full stop. However, when you need to write a more complex query like grouped pagination or null-based ordering, I recommend reaching for Arel.
However, because Arel considers itself a “framework framework,” it’s not a truly enjoyable to use out-of-the-box. This article shares three ways to make Arel a joy to use.
Null-based ordering in ActiveRecord
When designing your domain model for an application, the natural solution might end up using a
nilto model the absence of a value. In these cases, you might need to reach for null-based ordering within your database. When you’re writing a Ruby on Rails application, you’re most likely going to use ActiveRecord as the interface to your database. While ActiveRecord supports most queries out-of-the-box, sometimes you have to go off the beaten path.
Null-based ordering is one of those situations. Since ActiveRecord’s ordering works based on simple
key: :directionpairs, it is hard to perform null-based ordering outside of using the built-in behavior of your database. This article outlines two ways you can structure this type of null-based ordering, along with the caveats of using them.
Memoization in Ruby using three different patterns
Memoization is the process of performing an expensive calculation — a lookup from a database, a long-running function, etc. — and then caching its value to prevent the expensive action from running again. In computer science jargon, it trades space complexity for time complexity; that is, instead of releasing the calculated value for the garbage collector, it stores the value, thus increasing the space requirements of the object, to save on the time it takes to calculate the value more than once.
There are myriad ways to perform memoization in Ruby. The most common means is to use the
||=operator to conditionally set an instance variable upon first running the method. In most cases, this works well. However, there are certain cases where it does not do what you expect it to. This article discusses the semantics and gotchas of memoization in Ruby and shares different patterns you can use to ensure the correct behavior happens every time you choose to memoize a method.
Implementing account impersonation in ActionCable
Account impersonation is when you allow accounts (usually privileged accounts, e.g. support staff or developers) to operate your Rails application as if they are the owner of another account entirely. It’s a helpful feature to have when diagnosing issues that your customers write in about. There are plenty of gems that implement impersonation for your Rails controllers, but I wasn’t able to turn up any suggestions for implementing this for ActionCable.
This post outlines a simple method for adding impersonation to your Rails application in both your controllers and your ActionCable channels. I discuss some ActionCable features that are not well-documented and that I found a little confusing, then show examples of how to use the same pattern for identifying both your active account and your impersonating account — called a “shadower” in this article — in your channels.
Off-site backups using Duplicacy and Wasabi
I recently had my first ever hard drive failure and have since been looking into off-site backups. There are many choices to look through for off-site backups: what software should I use? What storage provider? This post describes how I set up Duplicacy and Wasabi as my off-site backups solution. Duplicacy is a backup tool written in Go. It supports many back ends including Wasabi, a fast, S3-compatible cloud storage provider. Wasabi offers great pricing that allows you to easily calculate how much it will cost to back up your data. However, combining the two isn’t very clear due to lacking documentation. You’ll leave this post with an understanding of how to set up an off-site backups repository using these two tools.