Working with lists of DOM elements in JavaScript

When you query the browser for DOM elements, there are some footguns you should know about.

Some lists are synchronized with the DOM

Some DOM APIs return live lists that automagically update their contents as the underlying DOM is manipulated.

Example

Let's assume we have two <div> elements:

<div id="one"></div>
<div id="two"></div>

We have multiple ways to retrieve a list of these elements. At first glance, they all look the same:

let liveList = element.getElementsByTagName('div')
let nonLiveList = docum...

Git: Finding changes in ALL commits

Finding changes

When you're looking for a specific change in Git, there are multiple axes you can choose:

Note that you can do most of these things with Git tools as well, e.g. tig path/to/file.

Considering ALL commits

By default, only the current branch (HEAD) is searched. To search across the entire local repository, add these options:

  • --all: Search al...

Making minimal updates to DOM trees using morphdom / idiomorph

When you replace parts of the DOM with new HTML, using .innerHTML = newHtml is usually the simplest and fastest option. It comes at the price of your DOM elements losing state, like input values, scroll position, progress in a video player, or even more complex state for custom elements.

One option to avoid this are libraries like morphdom (as used by Phoenix Liveviews) or idiomorph (as used by Rails' Turbo).

It lets you write

morphdo...

GoodJob: Ensure you get notified about background exceptions

GoodJob and ActiveJob rescue exceptions internally, preventing exception_notification from triggering. This can cause silent job failures.To get notified, subscribe to ActiveJob events and configure GoodJob's on_thread_error hook. This lets you manually call your exception notifier for every retry, discard, or internal GoodJob error.

# config/initializers/good_job.rb

# Manually notify on job failures, as they are handled internally by ActiveJob/GoodJob.
ActiveSupport::Noti...

Improve accessibility with [aria-required] in SimpleForm

SimpleForm comes with an option browser_validations which could be used to give fields that have a presence validation the HTML required attribute. We usually turn it off due to difficulties controlling its behavior and appearance. Instead we only mark required fields with an asterisk (*) next to its label. Blind users probably only discover the validation issue after submitting the form due to the now displayed error messages.

A compromise with better acce...

How to auto-resize a textarea (or other inputs) in pure CSS

Modern CSS offers the field-sizing property to allow elements to automatically adjust size (width and/or height) to fit their contents.
The most common use case are textareas which start fairly small (e.g. 2 or 3 rows tall) but grow when users enter longer text.

Usage

textarea {
  field-sizing: content;
}

That's it! At least in modern Chromium-based browsers.

Limited browser support

Support is still lacking in Firefox and Safari (as of mid 2025)....

Adding comments to ambiguous database columns

The DB schema is the most important source of truth for your application and should be very self-explanatory. If determining the true meaning of a DB column requires historical research in your issue tracker or reverse engineering of your source code you might consider adding a comment.

Both PostgreSQL and MySQL support comments in the DB schema:

How to: Self-hosted fonts via NPM packages

We usually ship applications that self-host webfonts to comply with GDPR.

Many popular web fonts are available as NPM packages provided by Fontsource.
We recommend using those instead of downloading and bundling font files yourself. (See below for a list of benefits.)

Usage

  1. Go to fontsource.org and search for the font you want to add (or a font that suits your application).
  2. Click the font card to vie...

Better performance insights with gem `rails_performance`

Even if you don't make any beginner mistakes like N+1 queries or missing DB indices, some requests can have bad performance. Without good performance metrics, you probably won't notice this until it's too late.

We investigated multiple gems and found that rails_performance (https://github.com/igorkasyanchuk/rails_performance) provides a lot of valuable information with very little setup cost. It only needs Redis which we use in the majority of our applications anyw...

Controlling smooth scrolling in browsers

It can be hard to understand what causes a browser scroll smoothly or instantly. CSS, JavaScript and the browser settings all have options to influence the scroll behavior. They all interact with each other and sometimes use the same words for different behavior.

CSS

Scrolling elements can use the scroll-behavior CSS property to express a preference between smooth and instant scrolling.

Preferring instant scrolling

CSS can prefer instant scrolling behavior:

html {
  scroll-behavior: auto; /* the default */
}

An `aut...

Testing Accessibility using Orca

Orca is a Linux screen reader. Since it is part of the GNOME project it should come preinstalled with Ubuntu installations.

Getting started

To turn on the screen reader you can either go to Settings > Accessibility and then activate Screen Reader in the "Seeing" section or you can simply type orca in your terminal. Alternatively you can use the default keyboard shortcut super + alt + s to toggle the screen reader.

Note

It may feel quite strange in the beginning to use a screen reader. It is constantly commenting on everyth...

Rails: Configuring the default sorting behaviour

In Rails, the implicit_order_column (added in Rails 6) is a configuration option that helps you define the default sorting behavior of ActiveRecord queries when no explicit ORDER BY clause is provided. This option allows you to specify a column that Rails will use to automatically sort records in a particular order when no specific ordering is given.

Since the id is typically the primary key and automatically indexed, Rails will default t...

Implementing upload progress and remove button with ActiveStorage DirectUpload

DirectUpload allows you to upload files to your file storage without having to wait for the form to submit. It creates AJAX requests to persist the file within your form and wraps them in a little API. This card will show you how to use it in order to create in-place file uploads with progress and a remove button.

This is basic functionality, you may add additional elements, styles and logic to make this look fancy, but the core functionality is the same. I created a file upload that looks like this:

![Image](/makandra/625023/attachments/3...

Implementing authentication and authorization for ActiveStorage blobs/files

ActiveStorage does not provide any built-in way of implementing authentication for the available DirectUpload endpoint in Rails. When using DirectUpload as JS wrapper in the frontend, be aware that its Rails endpoint is public by default, effectively allowing anyone to upload an unlimited amount of files to your storage.

The DirectUploadController from @rails/activestorage bypasses your form controller because it uploads the file using an AJAX request that runs directly, before any form roundtrip happens. This is a comfortable solutio...

How to automatically optimize SVG files with esbuild

SVG files often contain redundant information, like editor metadata or hidden elements. When esbuild handles your static assets, you can easily optimize SVG files using svgo as a plugin. Here is how to do it.

Adding svgo as an esbuild plugin

  1. Add the svgo package to your project's package.json
  2. Adjust your esbuild.config.js like so:
const esbuild = require('esbuild')
const svgo = require('svgo')

const options = {
  // ...
  loader: {
    // ...
    '.svg': 'copy', // this may be different...

Overview of method delegation in Rails

Method delegation in Rails can help you to keep your code organized and avoid deep call chains (law of demeter) by forwarding calls from one object to another. Rails provides several ways to accomplish this. Below is a concise overview of the most common approaches:

Single-Method delegation with delegate

Use the built-in delegate method from ActiveSupport to forward specific methods:

class User < ApplicationRecord
  has_one :profile

  delegate :full_name, :age, to: :profile, prefix: true
end
  • `delegate: full_name, :age...

Debug your Postgres SQL query plan

When debugging slow SQL queries, it’s helpful to understand the database engine's query plan. Whenever you execute a declarative SQL query, the database generates a "query plan" that outlines the exact steps the engine will take to execute the query. Most of the time, we don’t need to worry about this plan because SQL engines are highly optimized and can generate efficient execution strategies automatically. However, if a query is slow, inspecting the generated plan can help identify bottlenecks and optimization opportunities.

If you're usi...

How the Date Header Affects Cookie Expiration and Caching

tl;dr

When a cookie includes an Expires attribute or an HTTP response includes caching headers like Expires or Cache-Control, their validity depends on the server's Date header if present. Otherwise, the browser uses its local time. This can lead to issues in tests with mocked time or inconsistent cache behavior.

Cookie Expires depends on the Date header or browser time

When a cookie includes an Expires attribute, the browser evaluates the expiration date relative to a reference time:

  1. If the HTTP response ...

How to enable pretty IRB inspection for your Ruby class

When Ruby objects are inspected in any modern IRB, some objects (like ActiveRecord instances) are rendered with neat colors and line breaks.
You will not get that for custom classes by default -- which can be annoying if your inspection contains lots of meaningful information.

Here is what you need to do if you want your objects to be inspected nicely.

Implement a pretty_print method

As an example, consider the following class.

class MyClass

  # ...

  def inspect
    "#<#{self.class} attr1: #{attr1.inspect}, attr2: #{attr2...

DB enums are ordered

A lesser known fact about PG enums is that they are ordered. This can be really handy when values have an implicit ordering.

Let's imagine a record Issue(criticality: string). criticality should have the following three possible values: critical, medium, low.

Sorting with Issue.all.order(criticality: :desc) will return the following order:

  1. The 'medium' issue
  2. The 'low' issue
  3. The 'critical' issue

This happens because the database column backing the criticality attribute is a string and PG will use a [collation](...

Capistrano task to edit staging / production credentials

When using Rails credentials, you will edit the encrypted credentials for staging or production environments from time to time. To do that you need the secret key which should only live on the servers.

Do not download these key files to your local dev environment. They are sensitive and must not be stored on your machine.

Instead, put the attached capistrano task into lib/capistrano/tasks/ of your application. It expects environment specific keys to live in :shared_path/config/credentials/:stage.key. If you have a single master.key...

Timeouts for long-running SQL queries

While the main goal always is to prevent long-running queries in the first place, automatic timeouts can serve as a safety net to terminate problematic queries automatically if a set time limit is exceeded. This prevents single queries from taking up all of your database’s resources and reduces the need for manual intervention that might destabilize or even crash the application.

As Rails does not set a timeout on database statements by default, the following query will run for an entire day:

ActiveRecord::Base.connection.execute("S...

A simple example with a GIN index in Rails for optimizing a ILIKE query

You can improve your LIKE / ILIKE search queries in PostgreSQL by adding a GIN index with an operate class ("opclass") to split the words into trigrams to the required columns.

Example

class AddSearchTextIndexToUsers < ActiveRecord::Migration[7.1]
  def change
    enable_extension 'pg_trgm'

    add_index :users, :search_tex...

Rails credentials: Always use the bang version

Rails credentials are a way to store secrets in an encrypted YAML file. Usage is simple: each key in the credentials file becomes a method on Rails.application.credentials, returning the corresponding secret.

# Credentials file
file_storage_secret: superstrongsecret
# Somewhere in the application
FileStorage.secret = Rails.application.credentials.file_storage_secret

Since credentials usually are different between environments, you can easily forget to define them for another environment. If it is an API token, you'll...