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:
-
git log -- path/to/filelists all commits that touch a file -
git log -S some_stringlists all commits where "some_string" was added or removed
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:
- For new columns: https://guides.rubyonrails.org/active_record_migrations.html#comments
- Changing the comment for existin...
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
- Go to fontsource.org and search for the font you want to add (or a font that suits your application).
- 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:

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
Expiresattribute or an HTTP response includes caching headers likeExpiresorCache-Control, their validity depends on the server'sDateheader 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:
- 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:
- The
'medium'issue - The
'low'issue - 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...