RSSAmplifier

Blog

Boring Rails: Skip the bullshit and ship fast |

Learn about the boring tools and practices used by Basecamp, GitHub, and Shopify to keep you as happy and productive as the day you typed rails new

boringrails.comRSS feed ↗49 posts

Latest posts

Beautiful Rails confirmation dialogs (with zero JavaScript)

Upgrading the default data-turbo-confirm with a beautiful, native HTML dialog with animations

Hotwire components that refresh themselves

Using ViewComponents that know how to refresh themselves via turbo_streams is a powerful pattern to build complex flows with Hotwire

Event sourcing for smooth brains: building a basic event-driven system in Rails

Event sourcing is a jargon filled mess, but we can build a lean version with just ActiveRecord, callbacks, and a bit of boring code. Learn how to create simple, yet powerful event-driven systems in Rails.

Writing better Action Mailers: Revisiting a core Rails concept

Mailers are used in literally every Rails application, but often an after thought where we throw out the rules of software design. Revisiting the tools provided by Action Mailer can help us improve how we write mailers.

Sorting ActiveRecord results by enum values (in SQL)

Rails enums are a great way to model things like a status on an ActiveRecord model. They provide a set of human-readable methods while storing the result as an integer in the database. class JobSubmission < ApplicationRecord enum status: { draft: 0 , submitted: 1 , hold: 2 , rejected: 3 , accepted: 4 , canceled: 5 } end It is highly recommended to use a Hash to explicitly define the enum values –…

Thinking in Hotwire: Progressive Enhancement

Your mental model for Hotwire should be progressive enhancement: start with the basics and layer on Turbo Frames, Streams, and Stimulus as you build more.

Galaxy brain CSS tricks with Hotwire and Rails

Techniques for working with CSS in Hotwire and Rails that will make you say "wait..you did that with only CSS?!"

Adding keyboard shortcuts and hotkeys to StimulusJS

A review of the ecosystem for adding hotkeys to your Stimulus controllers: stimulus-hotkeys, stimulus-use/useHotkeys, HotKey.js, and github/hotkey

The most underrated Rails helper: dom_id

One of the oldest helpers in Rails is also the most underrated. `dom_id` shines for building apps with Hotwire, allowing you to easily target parts of the page without a bunch of nasty string interpolation.

Self-destructing StimulusJS controllers

Add sprinkles of Javascript behavior with Stimulus controllers that run a few lines of code and then remove themselves from the page. Like inlined jQuery snippets but for the modern times!

Tailwind style CSS transitions with StimulusJS

Build polished UI components with StimulusJS and Enter/leave CSS Transitions using patterns from Vue, Alpine, and Tailwind.

Dynamic user content in Rails with Liquid tags

When building features that accept user-generated content, you may need to display dynamic content based on what the user specifies. Imagine you want to users to be able to customize a welcome message sent from your application when they invite someone to their account. Rails programmers are deeply familiar with writing content with pieces of dynamic text: we do this all the time when writing view…

Accessing Rails environment variables from a StimulusJS Controller

Environment variables are a great way to configure your Rails apps. You can use the Rails.env variable to conditionally change behavior when you are in development/test or production. And you can add your own application specific variables for things like API tokens or global settings. While Stimulus has a values API to read from HTML data attributes, sometimes you need data that you don’t want to…

Rails validations: database level check constraints

One of the most common Rails tips is to back up your ActiveRecord model validations with database level constraints. Because there are times when validations are skipped, it’s best to let your database be the last line of defense to maintain your data integrity. You can add a validates :name, presence: true line to your model, but if null values sneak into your database, your app will still throw…

Debugging slow Heroku builds

It’s always best to follow a systematic approach when trying to speed up slow code. First, measure the current performance. Next, make the change that you think will help. Lastly, measure again to see if the change worked. It’s no different when it comes to debugging slow test suites or deploys. I recently noticed that my Heroku deploys were taking nearly 10 minutes to build. Thanks to a tip from…

Quickly explore your data with `uniq` and `tally`

A common question you may want to answer on user-input data is: what values have been entered and how many times is each one used? Maybe you have a list of dropdown options and you want to investigate removing a rare-used option. Ruby has two handy methods that I reach for often: uniq and tally . Usage The uniq method operates on an enumerable and compresses your data down to unique values.…

Improving your Rails mailers with `email_address_with_name`

In almost all email programs, you can add a display name before your email address like so: To: Matt Swanson <matt@example.com> It’s a small touch, but it is a more human-readable way of addressing an email. Rails provides a helper utility to format email addresses in this style without resorting to manual string manipulation. Usage Use email_address_with_name to add a name in-front on an email…

Building lightweight components with Rails Helpers and Stimulus

Custom Rails helpers modules are often overlooked, but they can be a great option for building lightweight components and reducing boilerplate in your Stimulus controllers. One nice thing about Stimulus is that you can quickly infer the functionality just from reading the markup attributes, but for components that have a couple of values and actions, you can benefit from hiding some of the…

Combine `redirect_to` and the `anchor` option

Often you’ll have an application screen like this: After editing information about an employee, you’ll redirect back to the Company Directory page. For a bit of extra polish, you can redirect with an anchor to automatically scroll the browser to the recently updated item and maintain your position in the list. You can combine this with the most underrated Rails helper – dom_id – for a really clean…

Lazy-loading content with Turbo Frames and skeleton loader

Hotwire is a new suite of frontend tools from Basecamp for building “reactive Rails” apps while writing a minimal amount of JavaScript. While the most exciting feature to some is the real-time streaming of server rendered HTML, my favorite addition is the Turbo Frame . The Turbo Frame is a super-charged iFrame that doesn’t make you cringe when you use it. Frames represent a slice of your page and…

Building a Rails CI pipeline with GitHub Actions

GitHub Actions is an automation platform that you run directly from inside a repository. We can use it as a testing CI/CD pipeline and keep everything close to the code.

Use `to_sql` to see what query ActiveRecord will generate

If you’re trying to write a tricky ActiveRecord query that includes joins , complex where clauses, or selecting specific values across tables, it can be hard to remember every part of the ActiveRecord DSL. Is it joins(:orders) or joins(:order) ? Should you use where(role: { name: 'Manager' }) or where(roles: { name: 'Manager' }) . It’s a good idea to test these queries in the Rails console so you…

Prefer returning chainable ActiveRecord objects

One of the best parts about ActiveRecord is the chainable query interface: Post . includes ( :comments ) . where ( published: true ) . where ( author: Current . user ) . order ( :name ) To take advantage of this strength and give you flexibility in your code, always try to return chainable objects when querying data. Usage It’s common to extract complex queries as your application grows. class…

Rails validations: unique within a certain scope

It’s a great idea to make your database and application validations match. If you have validates :name, presence: true in your model, you should pair it with a not null database constraint. Unique validations should be paired with a UNIQUE database index. In real-world applications, you often have more complicated validations, but you should continue this practice whenever you can. Something I…

Boring breadcrumbs for Rails

Breadcrumbs are a common UI pattern in most software applications. Rails has no built-in tools specifically for breadcrumbs, and while there are a handful of existing gems , I think this is something you can easily implement in your own app with just a few lines of code. Ultimately, you’ll want control of how you display the breadcrumbs in your app so you might as well just own all the code for…

Sharing common code between Rails controllers with `Scoped` pattern

If you follow a strict REST / nested resources approach to building your Rails app, you might get sick of repeating common controller actions. Try the Scoped concern pattern: a place to put shared code (setting variables, authorization) and slim down your controllers. Usage This particular pattern comes from DHH and Basecamp – a codebase that p rides itself of using lots of tiny concerns to share…

Run different ActiveRecord validations based on context

Sometimes want to skip certain validations on your database models. Maybe you have a multi-step wizard or want admins to have more freedom in changing data. You might be tempted to have certain forms skip validations, but there is a better way. Rails allows you to pass in a context when saving or validating a record. You can combine context with the on: option to run only certain ActiveRecord…

Find records missing an association with `where.missing`

You can’t prove a negative, but what about querying a database for a negative? While the majority of the time you are writing queries to find data, there are some cases when you want the opposite: writing a query that looks for the absence of data. When it comes to raw SQL, you can use a LEFT OUTER JOIN combined with a NULL check to find records without certain associations. Usage In Rails, you…

Testing multiple sessions in the same test with Capybara

Sometimes a feature in your application will involve a back-and-forth between multiple users. When it comes time to write an automated system test, you can easily simulate switching between users using Capybara’s using_session helper. Instead of logging in and out or faking out another user making changes to the app, you can use multiple sessions within the same Capybara test. This can be very…

Pluck single values out of ActiveRecord models or Enumerables

Rails has a great, expressive term called pluck that allows you to grab a subset of data from a record. You can use this on ActiveRecord models to return one (or a few) columns. But you can also use the same method on regular old Enumerables to pull out all values that respond to a given key. Usage In Rails, use pluck to query a subset of columns. Shoe . all . map ( & :name ) # SELECT "shoes.*"…

Never mix up greater/less than when comparing dates again

When it comes to compare dates, for some reason my brain really struggles. I mix up < and >= all the time and end up flipping them. Is start_date greater than end_date ? Or vice-versa? I get confused because I think about dates in terms of before and after not greater_than or less_than . Usage Luckily, Rails is here to save the day and make sure I never make this mistake again by adding before?…

Super readable String operations with `delete_prefix` and `delete_suffix`

One reason I love writing Ruby is that it’s optimized for programmer happiness. The Ruby community values code that is super readable. Programmers coming from other ecosystems are often shocked at much Ruby looks like pseudo-code. Between the standard library and extensions like ActiveSupport , working with Ruby means you can write code in a natural way. A great example of this are the String…

Setting CSS classes in Markdown with Jekyll / Bridgetown

Writing blog posts in Markdown is just great. This blog is written in Markdown! But sometimes you might be tempted to drop down to raw HTML to add some extra styling. For example maybe you want to write this content in markdown but have it apply a “pro-tip” CSS class so that it looks like…well, this! Usage Popular Ruby static site generators like Jekyll and Bridgetown use Kramdown under-the-hood…

Use Heroku Dataclips to share query and do ad-hoc data exports

Heroku Dataclips enable you to create SQL queries for your Heroku Postgres databases and share the results with colleagues, third-party tools, and the public. Recipients of a dataclip can view the data in their browser and also download it in JSON and CSV formats. Usage If you are hosting your app on Heroku, you might need to run some ad-hoc queries or share a report. Instead of generating an…

Ensure required environment variables are set when booting up Rails

It’s common to use environment variables to configure external services or other options in a Rails app. These ENV_VARS usually are not checked into source control, but rather configured per environment. Rails has the concept of initializers , which is code run during the boot phase of a Rails app. You can add a custom initializer to check that required environment variables are set to avoid…

Search and debug gems with `bundle open`

Ever get frustrated trying to search through code on GitHub? Or wish you could put a breakpoint in a gem so you could figure out what it was doing? Don’t mess around with cloning the gem repo or monkey patching code in your own app. Use bundle open instead. Usage In your shell, run the command: bundle open GEM_NAME bundler will open the source code for the exact version of the gem you’ve got…

Automatically cast params with the Rails Attributes API

A common practice in Rails apps is to extract logic into plain-old Ruby objects (POROs). But often you are passing data to these objects directly from controller params and the data comes in as strings. class SalesReport attr_accessor :start_date , :end_date , :min_items def initialize ( params = {}) @start_date = params [ :start_date ] @end_date = params [ :end_date ] @min_items = params […

Show relevant chunks of text with Rails `excerpt` helper

The Rails helper excerpt can extract a chunk of text that matches a certain phrase, no matter where in the string it is. Imagine you wanted to display a list of emails matching a certain search term: Simply filter down your records and then use excerpt on the email body. Usage Here’s what your view might look like to build this feature. <%= link_to email do %> <div class= "flex justify-between…

Use Rails `link_to_unless_current` for navigation links

We’re all familiar with the classic Rails link_to helper. But did you know there is a link_to_unless_current variant? It works just link link_to except that it doesn’t create a link if the browsers current URL is the same as the link target. Usage Simply replace link_to with link_to_unless_current . If you are not already on the page, a normal <a> tag will be rendered. If you are on the page…

Use Rails `cycle` to avoid `i % 2 == 0` in your view loops

Sometimes you need to keep track of how many times you’ve looped when rendering some views, for instance to alternate background colors to create a “striped” table. <!-- @foods = ["apple", "orange", "banana"] --> <% @foods . each do | food | %> <tr class= "???" > <td> <%= food %> </td> </tr> <% end %> You might try using :odd or :even CSS child selectors or switching to each_with_index . <% @foods…

Use the Rails helper `highlight` when showing search results

Use the Rails highlight helper to wrap search result matches in <mark> tags. Highlight the search term “comment” in a list of notifcations Usage Pass the search term to your controller via params (e.g. params[:search] ) and use that to filter down your results. # app/controllers/inbox_controller.rb class InboxController < ApplicationController def index @notifications = Current . user .…

Magic Responsive Tables with Stimulus and IntersectionObserver

Responsive HTML data tables are a tricky problem that usually requires scrolling on small screens. With a sprinkle of Stimulus and the IntersectionObserver API, we can build a small enhancement to make the user experience more pleasant.

Hacktoberfest Recap: Open source Ruby/Rails work in 2020

A recap of my Rails-related contributions for the 2020 Hacktoberfest event: ViewComponent, Bullet, LRUG, and Circulate

Building GitHub-style Hovercards with StimulusJS and HTML-over-the-wire

Turbolinks, Stimulus, and Server Rendered HTML is a compelling alternative to modern JavaScript single page apps. Let's build a hovercard to see how you can kick it old school with a more boring approach.

Writing better StimulusJS controllers

Stimulus sprinkles interactive behavior on top of your boring HTML pages. By keeping your controllers small, generic, and composable you can build a front-end without the typical JavaScript mess.

Feature Flags: The stupid simple way to de-stress production releases

Feature flags bridge the gap between the abstract concept of continuous delivery and tactical release of features. Start small with a glorified if-statement before adding more complicated tooling to get the most bang for your buck.

Spring Cleaning: Tidying up your codebase

A practical checklist for tidying up your gems, pruning old git branches, removing unused views and routes, and cleaning up your database. A little bit goes a long way when it comes to cleaning!

Wrangling slow reports, large file exports, and long-running tasks in Rails with Active Job

Sometimes we need to generate really large file exports or run reports that are just slow. It's not enough to optimize a few queries, we need to move the work to a background job and notify the user when it's all done.

Managing Rails schema and data migrations without losing your mind

Rails database migrations are extremely powerful, but can be a mess if we don't avoid the traps. This article outlines a boring way to handle schema and data migrations effectively.

Boring Rails: Skip the bullshit and ship fast | · RSS Amplifier