Beautiful Rails confirmation dialogs (with zero JavaScript)
Upgrading the default data-turbo-confirm with a beautiful, native HTML dialog with animations
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
Upgrading the default data-turbo-confirm with a beautiful, native HTML dialog with animations
Using ViewComponents that know how to refresh themselves via turbo_streams is a powerful pattern to build complex flows with Hotwire
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.
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.
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 –…
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.
Techniques for working with CSS in Hotwire and Rails that will make you say "wait..you did that with only CSS?!"
A review of the ecosystem for adding hotkeys to your Stimulus controllers: stimulus-hotkeys, stimulus-use/useHotkeys, HotKey.js, and github/hotkey
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.
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!
Build polished UI components with StimulusJS and Enter/leave CSS Transitions using patterns from Vue, Alpine, and Tailwind.
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…
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…
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…
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…
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.…
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…
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…
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…
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…
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.
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…
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…
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…
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…
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…
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…
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…
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…
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.*"…
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?…
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…
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…
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…
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…
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…
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 […
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…
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…
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 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 .…
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.
A recap of my Rails-related contributions for the 2020 Hacktoberfest event: ViewComponent, Bullet, LRUG, and Circulate
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.
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 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.
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!
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.
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.