Rails: When to use :inverse_of in has_many, has_one or belongs_to associations

When you have two models in a has_many, has_one or belongs_to association, the :inverse_of option in Rails tells ActiveRecord that they're two sides of the same association.

Example with a has_many / belongs_to association:

class Forum < ActiveRecord::Base
  has_many :posts, inverse_of: :forum
end

class Post < ActiveRecord::Base
  belongs_to :forum, inverse_of: :posts
end

Knowing the other side of the same association Rails can optimize object loading so forum and forum.posts[0].forum will reference the same o...

How to update a single gem conservatively

The problem

Calling bundle update GEMNAME will update a lot more gems than you think. E.g. when you do this:

bundle update cucumber-rails

... you might think this will only update cucumber-rails. But it actually updates cucumber-rails and all of its dependencies. This will explode in your face when one of these dependencies release a new version with breaking API changes. Which is all the time.

In the example above updating cucumber-rails will give you Capybara 2.0 (because capybara is a dependency of `cucumber-rail...

Defining class methods with Modularity traits

There are two ways to define a class method from a Modularity trait. Note that the usual caveats regarding class method visibility apply.

Using define_method

The recommended way is to define a method on your module's singleton class:

module SomeTrait
  as_trait do
    define_singleton_method :foo do
      # ...
    end
  end
end

Using def (has...

Sentry Local Logging in Ruby

Enable local logging for Sentry when:

  • Debugging Sentry event capture locally
  • Testing error handling without polluting production metrics
  • Developing background jobs and want to see what Sentry captures

How to enable

To capture and log Sentry events locally during development without sending to the server, add this to config/initializers/sentry.rb inside the Sentry.init block:

if Rails.env.development?
  # Use dummy transport to prevent actual transmission to Sentry
  config.transport.transport_class = Sentry::DummyTran...

Using a virtual column for trigram indexes in PostgreSQL

Full-text search can reach its limits in terms of flexibility and performance. In such cases, trigram indexes (pg_trgm) offer a lightweight alternative.

You can base the index on a virtual column that combines multiple text attributes. A stored virtual column stores the result of an expression as if it were a real column. It is automatically updated when the source columns change and can be indexed like normal data. This keeps your query logic consistent and avoids repeating string concatenation in every search.

def searc...

Simple form examples with bootstrap

Good reference how to build bootstrap forms with simple_form.

Ruby: A small summary of what return, break and next means for blocks

Summary

  • Use return to return from a method. return accepts a value that will be the return value of the method call.
  • Use break to quit from a block and from the method that yielded to the block. break accepts a value that supplies the result of the expression it is “breaking” out of.
  • Use next to skip the rest of the current iteration. next accepts an argument that will be the result of that block iteration.

The following method will serve as an example in the details below:

def example
  puts yield
  puts ...

Using ActiveRecord with threads might use more database connections than you think

Database connections are not thread-safe. That's why ActiveRecord uses a separate database connection for each thread.

For instance, the following code uses 3 database connections:

3.times do
  Thread.new do
    User.first # first database access makes a new connection
  end
end

These three connections will remain connected to the database server after the threads terminate. This only affects threads that use ActiveRecord.

You can rely on Rails' various clean-up mechanisms to release connections, as outlined below. This may...

Unpoly: Passing Data to Compilers

Quick reference for passing data from Rails to JavaScript via Unpoly compilers.

Haml Attribute Syntax

# Ising hash rockets and string symbols (method calls)
= form.text_field :name, 'date-picker': true

# Curly braces or brackets (elements) 
%div.container{ id: 'main', 'data-value': '123' }

Simple Values: data-* Attributes

Use for: Scalar values (IDs, strings, booleans)

%span.user{ 'data-age': '18', 'data-first-name': 'Bob' }
up.compiler('.user', (element, data) => {
  console.log(...

Unpoly: Compiler Selector Patterns

Quick guide for frequently used compiler selector patterns of Unpoly.

1. BEM Component Pattern

When: Reusable UI components with multiple child elements

Examples: toggleable.js, collapsible.js, searchable_select.js

up.compiler('.toggleable', (toggleable) => {
  const checkbox = toggleable.querySelector('.toggleable--checkbox')
  const content = toggleable.querySelector('.toggleable--content')
  // ...
})
%td.toggleable.-inverted.-ignore-when-not-empty
  .toggleable--content
    = form.text_fie...

Project management best practices: Budget control

When starting a project we always make a good estimate of all known requirements, and plan budgets and available developers accordingly.

Requirements change. Budgets usually don't.

To make sure a project stays on track, we update our estimates periodically and compare them to the remaining budget. If this doesn't match any more, we have to act.

To update an estimate, do the following:

  • Start with the most recent estimate for the project.
  • Which stories have been completed? Set their estimate to zero.
  • Have any requirements cha...

Careful: `fresh_when last_modified: ...` without an object does not generate an E-Tag

To allow HTTP 304 responses, Rails offers the fresh_when method for controllers.

The most common way is to pass an ActiveRecord instance or scope, and fresh_when will set fitting E-Tag and Last-Modified headers for you. For scopes, an extra query is sent to the database.

fresh_when @users

If you do not want that magic to happen, e.g. because your scope is expens...

Firefox cancels any JavaScript events at a fieldset[disabled]

If you try to listen to events on elements that are nested inside a <fieldset disabled>, Firefox will stop event propagation once the event reaches the fieldset. Chrome and IE/Edge will propagate events.

Since we often bind event listeners to document this can be annoying.

You could solve it by...

SQL: Fast threshold counts with LIMIT

Performing COUNT(*) on large tables is slow. Sometimes you don’t need the exact number once results exceed a certain threshold.

For example, you may only need to display 100+ in the UI. Using a plain COUNT(*) would scan all matching rows.

The following query would be pretty slow when counting many rows because it has to scan all rows.

SELECT COUNT(*) FROM movies;

Limiting within a subquery

Use a subquery with LIMIT to cap the scan early. ...

How to tweak RSpec's truncation behavior

When RSpec sets out to print any given object to the console, it will never print more than 200 characters from it. Only the first and last 100 chars from overly long strings are displayed, which sometimes means that the root cause for the failing test is buried in truncation.

For example, I could not easily make out the reason for this failure:

Failure/Error: expect { crawler.pull_new_commits }.not_to raise_error

expected no Exception...

Matching Unicode characters in a Ruby regexp

On Ruby 1.9+, standard ruby character classes like \w, \d will only match 7-Bit ASCII characters:

"foo" =~ /\w+/   # matches "foo"
"füü" =~ /\w+/   # matches "f", ü is not 7-Bit ASCII

There is a collection of character classes that will match unicode characters. From the documentation:

  • /[[:alnum:]]/ Alphabetic and numeric character
  • /[[:alpha:]]/ Alphabetic character
  • /[[:blank:]]/ Space or tab
  • /[[:cntrl:]]/ Control character
  • /[[:digit:]]/ Digit
  • /[[:graph:]]/ Non-blank character (excludes spaces...

JavaScript: Stopping expensive work in inactive tabs

Is your application doing something expensive every few seconds? Maybe an animated slider that rotates images? Maybe you are updating data over the network every five minutes? It's a good idea to pause this if the your document tab is not even visible to the user. This saves your user's battery and data plan.

You can ask document.visibilityState or document.hidden whether this tab is visibl...

zizmor - Static analysis for GitHub Actions

The linked tool can be used to scan your CI/CD workflows for potential security issues and suboptimal defaults if they are based on GitHub Actions.

For example, it warns you about

  • string interpolations that may expand into attacker-controllable code
  • suboptimal defaults like e.g. persist-credentials: true for the checkout action
  • actions that are not pinned to a tag instead of a git SHA

Some of the warnings can be auto-fixed. The tool comes wi...

Rails 8: The db:migrate task might not run all migrations in db/migrate/ anymore

In Rails 8 the behavior of the rails db:migrate command has changed for fresh databases (see PR #52830).

  • Before Rails 8: The command runs all migrations in the folder db/migrate/*
  • After Rails 8: The command loads the schema file (db/schema.rb or db/structure.sql) if existing and runs all pending migrations in the folder db/migrate/* afterwards

This speeds up the command. But e.g. migrations with data manipulations are missing.

The only way to run all pending mig...

How to reliably center (block) icons vertically with text

vertical-align is hard. Have you ever wanted to vertically center an icon with text? This usually means "vertically align with capital letters", as visually, a text line goes from baseline up to the capital top. (That's because descenders are far less frequent than ascenders.)

In this card we'll vertically center an icon (or any "blockish" inline element, really) with the capital letters of surrounding text. This works well with our [modern approach to SVG icons](/mak...

Ruby tempfiles

With the the Ruby Tempfile class you can create temporary files. Those files only stick around as long as you have a reference to those. If no more variable points to them, the GC may finalize the object at some point and the file will be removed from the file system. In other words: tempfiles are removed automatically. If you would then try to access the tempfile using its path (which you stored previously), you would get an error because the file no longer exists.

You can proactively unlink your tempfiles to delete them earlier...

How to use pessimistic row locks with ActiveRecord

When requests arrive at the application servers simultaneously, weird things can happen. Sometimes, this can also happen if a user double-clicks on a button, for example.

This often leads to problems, as two object instances are modified in parallel maybe by different code and one of the requests writes the results to the database.

In case you want to make sure that only one of the requests "wins", i.e. one of the requests is fully executed and completed while the other one at least has to wait for the first request to be completed, you ha...

Unpoly 3.12.0 released

This release adds asynchronous compilers and many other features requested by the community.
We also fixed a number of performance regressions introduced by Unpoly 3.11.

Breaking changes are marked with a ⚠️ emoji and polyfilled by unpoly-migrate.js.

Asynchronous compilers

Compiler functions can now be [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...

Testing HTTPS with badssl.com

Website that offers lots of different kinds of HTTPS configurations, bad or good or complicated.

They also offer a dashboard to check if your browser's HTTPS handling works as expected (which might be compromised e.g. due to security products or enterprise proxy servers).