How to find out what is running on a port on a remote machine

By convention, common protocols use a defined port, like 80 for HTTP or 443 for HTTPS.

You can use nmap to find out what service is running behind a given port, and most often see some details about it. This can be helpful if servers don't offer the services you expect for some ports. If you'd like to see what ports are listing on your local machine, you might want to use netstat instead of nmap.

Note that nmap's service discovery may trigger several requests.

Example

When using nmap, adding the -A switch ...

RSpec: Expecting non-primitive objects as method invocation arguments

Expecting a primitive value as an argument to a method invocation is easy:

expect(object).to receive(:foo).with('arg1', 'arg2')

This expectation would be met with this call:

object.foo('arg1', 'arg2')

But what if the argument is expected to be an object with a given set of methods? E.g. this class with #first_name and #last_name methods:

class Person

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end
  
  attr_reader :first_name, :last_name
  
end
``...

Updated: How to allow testing beforeunload confirmation dialogs with modern ChromeDrivers

ChromeDriver 135 started following the W3C spec more closely, which broke testing beforeunload confirmations again. To get working confirmations in a testing browser again, unhandled_prompt_behavior needs to be set to the hash { default: :ignore }.

Selenium doesn't currently support setting this option to a hash, so a monkey patch is needed.

Updated: Testing Accessibility using Orca

As it's quite hard to use a screen reader when you have never done so before, I added a guide on how to visually review the spoken text instead.


Debugging Orca's Output

We can visually review everything the screen reader says by hacking together a real-time transcript of Orca's speech.

To do so, run orca in a CLI window telling it to write a temporary debug log (without Braille to reduce noise)

orca --disable braille --debug-file=/tmp/orca-log.txt

Tip: The screen reader will still be audible. You can reduce its volume ...

Managing chrome versions for selenium

Currently we often use geordi to run cucumber and rspec tests. Geordi takes care of installing a matching chromedriver for the installed google-chrome binary. The google-chrome binary is managed by apt.

Another approach is to use the Selenium Manager for installing and using the correct browser versions for you. Here is the setup you need for your integration tests:

Capybara.register_driver :chrome do |app|
  options = Sele...

Webpack(er): Analyze the size of your JavaScript components

We're always striving towards keeping our website's JavaScript as small as possible.

If you're using webpack(er), you can use the webpack-bundle-analyzer plugin to get a good overview, which of your JavaScript modules take up how much space, and where you can optimize.

To use it, add it via npm or yarn

yarn add webpack-bundle-analyzer

Then add this to your environment.js:

// Uncomment this code to show statistics of bundle sizes. Generated file will automatically...

Custom error pages in Rails

Basic error pages

To add a few basic styles to the default error pages in Rails, just edit the default templates in public, e.g. public/404.html.

A limitation to these default templates is that they're just static files. You cannot use Haml, Rails helpers or your application layout here. If you need Rails to render your error pages, you need the approach below.

Advanced error pages

  1. Register your own app as the applicatio...

Don't forget: Automatically remove join records on has_many :through associations

Bad

# Given the following models

class Image < ActiveRecord::Base
  has_many :album_images
  has_many :albums, through: :album_images
end

class Album < ActiveRecord::Base
  has_many :album_images
  has_many :images, through: :album_images
end

# Join model
class AlbumImage < ActiveRecord::Base
  belongs_to :album
  belongs_to :image
end

Destroying a record in this setup will only remove the record itself, and leave orphaned join records behind.

image = Image.last
image.destroy # removes only the `image` record,
   ...

Rails: Handling actions that need to happen after all transactions

In Rails 7.2. the feature ActiveRecord.after_all_transactions_commit was added, for code that may run either inside or outside a transaction (we have a special card for nested transactions in general) and needs to perform work after the state changes have been properly persisted. e.g. sending an email.

Example

def publish_article(article)
  article.update(published: true)

  ActiveRecord.after_all_transactions_commit do
    PublishNotification...

Rails: Testing exceptions with the rescue_responses setting

In Rails 7.2 the new default for config.action_dispatch.show_exceptions is rescuable.

  • :rescuable: It will show a Rails error page in the response only for rescuable exceptions as
    defined by ActionDispatch::ExceptionWrapper.rescue_responses. In the
    event of an unexpected internal server error, the exception that caused
    the error will still be raised within the test so as to provide a useful
    stack trace and a good debugging experience.
  • :all: It wi...

RSpec: Defining negated matchers

You can use RSpec::Matchers.define_negated_matcher to define a negated version of an existing matcher. This is particularly useful in composed matcher expressions or to create more expressive and meaningful matchers.

You should only negate "atomic" matchers with an unambiguous inversion. For example, have_radio_button(label) can be negated, whereas have_active_radio_button(label) should not be. Its inversion could either mean "there is a radio button with that label, but it is not active", or "there is no radio button with that la...

A modern approach to SVG icons

You have some SVG files you want to use as icons on your website. How would you embed them?

Common options are:

  1. Use them with an image: <img src='path-to-icon.svg'>
  2. Embed them inline with <svg>$ICON</svg>
  3. Embed them using CSS and background-image: url(path-to-icon.svg) or even background-image: url(data:$ICON).
  4. Build your own icon font.

All of these have drawbacks:

  • Image and background-image do not allow to recolor the image using CSS.
  • Inline-<svg> are unnecessary work for the server and are...

Regex: Be careful when trying to match the start and/or end of a text

Ruby has two different ways to match the start and the end of a text:

  • ^ (Start of line) and $ (End of line)
  • \A (Start of string) and \z (End of string)

Most often you want to use \A and \z.

Here is a short example in which we want to validate the content type of a file attachment. Normally we would not expect content_type_1 to be a valid content type with the used regular expression image\/(jpeg|png). But as ^ and $ will match lines, it matches both content_type_1 and content_type_2. Using \A and \z will wo...

Statistics and Reports on Web Performance Optimization

Case studies and experiments demonstrating the impact of web performance optimization (WPO) on user experience and business metrics.

How to use Parallel to speed up building the same html partial multiple times (for different data)

The parallel-gem is quite easy to use and can speed up rendering time if you want to render the same partial multiple times (e.g. for rendering long lists of things).

Parallel supports execution using forked processes (the default), threads (mind the GVL) and Ractors (some limitations for data sharing).

If your parallelized code talks to the database, you should [ensure not to leak database connections](https://makandracards.com/makandra/45360-using-activerecord-with-threads-will-leak-database-connect...

Choosing the right gems for your project

Adding a gem means you take over the liability towards the external code.

Checklist

Based on "To gem, or not to gem":

  • Gem is really needed (prefer writing your own code for simple requirements without many edge cases)
  • Gem is tested well (coverage and quality)
  • Gem has a good code quality
  • Gem's licence fits to the project requirement
  • Try to avoid gems that do much more than your requireme...

How to iterate over an Enumerable, returning the first truthy result of a block ("map-find")

Ruby has Enumerable.find(&block), which returns the first item in the collection for which the block evaluates to true.

first_post_with_image = posts.find do |post|
  post.image
end

However, sometimes it's not the item you're interested in, but some value depening on it – e.g. the value the block evaluated to. You could first map the collection and then take the first truthy value, but this way you need to process the whole collection twice:

first_image_url = posts.map(&:image).find(&:present?).url

If the mapp...

Heads up: Capybara 3's text matchers no longer squish whitespace by default

Until Capybara 2, node finders that accept a text option were able to find nodes based on rendered text, even if it spans over multiple elements in the HTML. Imagine a page that includes this HTML:

<div class='haystack'>
  Hi!
  <br>
  Try to match me.
</div>

Even though the text is separated by a <br> tag in the HTML, it is matched until Capybara 2 which used to "squish" text prior to the comparison.

# Capyabara 1 or 2
page.find(...

RubyMine: Efficiently filtering results in the "Finder" overlay

RubyMine comes with a nice way to grep through your project's files: The finder (ctrl + shift + f). Don't be discouraged about the notice 100+ matches in n+ files if your searched keyword is too general or widely used in your project.

Image

RubyMine comes with a few ways to narrow down the resulting list, don't hesitate to apply those filters to speed up your search. Your keybinding might vary based on your personal settings.

File mask (alt + k)

If you already know the file extension of your ...

Testing for Performance: How to Ensure Your Web Vitals Stay Green

Frontend performance and user experience are orthogonal to feature development. If care is not taken, adding features usually degrades frontend performance over time.

Many years, frontend user experience has been hard to quantify. However, Google has developed some metrics to capture user experience on the web: the Web Vitals. The Core Web Vitals are about "perceived loading speed" (Largest Contentful Paint), reactivity (Interaction to Next Paint) and visual stability (Content Layout Shift).

I have recent...

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)....

You don't always need a custom matcher to write clean RSpec tests

When you repeat complex assertions in your tests multiple times, it might be a good idea to extract a custom RSpec matcher. This not only tidies up your own code, but also makes it easier to write future specs.

However, not all situations are well-suited for that. Sometimes the effort isn't worth it, e.g. when your matcher would need too many parameters to be reusable. In those cases, you can also simply extract a private method:

describe `/search` do
  it "doesn't lose the infinite scroll's filter state when navig...

Different ways to set attributes in ActiveRecord

Rails 5 / 6 / 7

Method Uses Default Accessor Saves to Database Runs Validations Runs Callbacks Updates updated_at/updated_on Respects Readonly
attribute= Yes No n/a n/a n/a n/a
attributes= Yes No ...

Error handling in DOM event listeners

When an event listener on a DOM element throws an error, that error will be silenced and not interrupt your program.

In particular, other event listeners will still be called even after a previous listener threw an error. Also the function that emitted the event (like element.dispatchEvent() or up.emit()) will not throw either.

In the following example two handlers are listening to the foo event. The first handler crashes, th...