Bash: How to grep logs for a pattern and expand it to the full request

Example

I, [2024-01-21T06:22:17.484221 #2698200]  INFO -- : [4cdad7a4-8617-4bc9-84e9-c40364eea2e4] test
I, [2024-01-21T06:22:17.484221 #2698200]  INFO -- : [4cdad7a4-8617-4bc9-84e9-c40364eea2e4] more
I, [2024-01-21T06:22:17.484221 #2698200]  INFO -- : [6e047fb3-05df-4df7-808e-efa9fcd05f87] test
I, [2024-01-21T06:22:17.484221 #2698200]  INFO -- : [6e047fb3-05df-4df7-808e-efa9fcd05f87] more
I, [2024-01-21T06:22:17.484221 #2698200]  INFO -- : [53a240c1-489e-4936-bbeb-d6f77284cf38] nope
I, [2024-01-21T06:22:17.484221 #2698200]  INFO -- ...

Rails: Testing the number of database queries

There are a few tools to combat the dreaded n+1 queries. The bullet gem notifies you of missing eager-loading, and also if there is too much eager-loading. strict_loading in Rails 6.1+ forces developers to explicitly load associations on individual records, for a single association, for an entire model, or globally for all models.

But you can also actually **write spe...

Opening a zipped coverage report with one click

Image

Tested on Ubunut 22.04

1. Opener script

  • Create a file ~/.local/bin/coverage_zip_opener with:
#!/bin/bash

tmp_folder="/tmp/coverage-report-opener"

if [ -z "$1" ]
then
 echo "Usage: coverage_zip_opener [filename]"
 exit -1
fi

if ! [[ "$1" =~ ^.*Pipeline.*Coverage.*\.zip$ || "$1" =~ ^.*merged_coverage_report.*\.zip$ ]]; then
 file-roller "$1"
 exit 0
fi

rm -Rf $tmp_folder

unzip -qq "$1" -d $tmp_folder
index_filename=$(find /tmp/coverage-report-opener -name "index.html" | ...

Element.animate() to animate single elements with given keyframes

Today I learned that you can animate HTML elements using the Web Animation API's method .animate(keyframes, options) (which seems to be Baseline for all browsers since 2022).

const fadeIn = [{ opacity: 0 }, { opacity: 1 }] // this is a keyframe example

const container = document.querySelector('.animate-me')

const animation = container.animate(fadeIn, 2000) // I am just using the animation duration as option here but it can also be given an object

// the animation object can be used for things like querying timings or stat...

SASS: Adding, removing and converting units

Adding a unit

Multiply by 1x the unit:

$number = 13
$length = $number * 1px // => 13px

Removing a unit

Divide by 1x the unit:

$length = 13px
$number = $length / 1px // => 13

Converting a unit

the result of an addition or subtraction between two numbers of different units is expressed in the first member’s unit

Thus, to convert a number, add it to 0 of the desired unit:

$duration: .21s
$duration-in-milliseconds: 0ms + $duration // => 210ms

An example is storing a transition duration as CS...

When loading Yaml contents in Ruby, use the :freeze argument to deep-freeze everything

Ruby methods which load from a Yaml file, like YAML.safe_load or YAML.safe_load_file, support passing freeze: true to deep-freeze the entire contents from the Yaml file.
This is available by default on Ruby 3.0 and newer. On older Rubies, you can install psych 3.2.0 or newer for :freeze support.

As an example, consider the following Yaml file:

---
message:
  - hello
  - universe
foo:
  bar:
    baz: "example"

We can now load it as usual, but pass freeze: true.

>> test = YAML.safe_load_file('example.yml', fre...

Creating a self-signed certificate for local HTTPS development

Your development server is usually running on an insecure HTTP connection which is perfectly fine for development.

If you need your local dev server to be accessible via HTTPS for some reason, you need both a certificate and its key. For a local hostname, you need to create those yourself.
This card explains how to do that and how to make your browser trust the certificate so it does not show warnings for your own certificate.

Easy: self-signed certificate

To just create a certificate for localhost, you can use the following command....

How to search through logs on staging or production environments

We generally use multiple application servers (at least two) and you have to search on all of them if you don't know which one handled the request you are looking for.

Rails application logs usually live in /var/www/<project-environment-name>/shared/log.
Web server logs usually live in /var/www/<project-environment-name>/log.

Searching through single logs with grep / zgrep

You can use grep in this directory to only search the latest logs or zgrep to also search older (already zipped) logs. zgrep is used just like grep ...

How to make your application assets cachable in Rails

Note: Modern Rails has two build pipelines, the asset pipeline (or "Sprockets") and Webpacker. The principles below apply for both, but the examples shown are for Sprockets.


Every page in your application uses many assets, such as images, javascripts and stylesheets. Without your intervention, the browser will request these assets again and again on every request. There is no magic in Rails that gives you automatic caching for assets. In fact, if you haven't been paying attention to this, your application is probabl...

How to let passenger restart after deployment with capistrano

Phusion Passenger changed the way how it gets restarted several times. Through the project's history, these all were valid:

  • touch tmp/restart.txt
  • sudo passenger-config restart-app /path/to/app
  • passenger-config restart-app /path/to/app

You should not need to know which one to use. Instead, the capistrano-passenger gem will choose the appropriate restart mechanism automatically based on your installed the passenger version.

Installation

  1. Add to your Gemfile:

    gem 'capistr...
    

Maintaining custom application tasks in Rails

Here are some hints on best practices to maintain your tasks in larger projects.

Rake Tasks vs. Scripts

  • The Rails default is using rake tasks for your application tasks. These live in lib/tasks/*.
  • In case you want to avoid rake for your tasks and just use plain ruby scripts, consider lib/scripts/* as folder.

Keeping tasks slim

For readability and testing it's easier to keep your tasks slim. We suggest to use folders inside the tasks or scripts folder.

Example for a task:

The slim task lib/tasks/gitlab.rb:

Unpoly 3.7.1, 3.7.2 and 3.7.3 released

Version 3.7.0 broke some things in complex forms. Sorry for that. Concurrent user input is hard.

3.7.1

This change fixes two regressions for form field watchers, introduced by 3.7.0:

  • When a change is detected while waiting for an async callback, prevent the new callback from crashing with Cannot destructure property { disable } of null.
  • When a change is detected while waiting for an async callback, the full debounce delay of that new change is honored.

...

CSS: Letting text flow around a round element

If you have an element with significant border-radius (e.g. 50% for a circle) and you want inline content (i.e. text) to flow around it, do it like this:

  • Place the element right before the text and float: right or float: left
  • Tell the browser to take the content-box for the element's shape, i.e. without margin, padding and border. shape-outside: content-box
  • Set the margin where you want it, e.g. 10px left and bottom
  • Set the shape-margin to the same size ...

Cucumber step to match table rows with Capybara

These steps are now part of Spreewald.

This note describes a Cucumber step that lets you write this:

Then I should see a table with the following rows:
  | Bruce Wayne       | Employee    | 1972 |
  | Harleen Quinzel   | HR          | 1982 |
  | Alfred Pennyworth | Engineering | 1943 |

If there are additional columns or rows in the table that are not explicitely expected, the step won't complain. It does however expect the rows to be ordered as stat...

Pitfall: ActiveRecord callbacks: Method call with multiple conditions

In the following example the method update_offices_people_count won't be called when office_id changes, because it gets overwritten by the second line:

after_save :update_offices_people_count, :if => :office_id_changed? # is overwritten …
after_save :update_offices_people_count, :if => :trashed_changed? # … by this line

Instead write:

after_save :update_offices_people_count, :if => :office_people_count_needs_update?

private

def office_people_count_needs_update?
  office_id_changed? || trashed_changed?
end

Or...

Copying validation errors from one attribute to another

When using virtual attributes, the attached trait can be useful to automatically copy errors from one attribute to another.

Here is a typical use case where Paperclip creates a virtual attribute :attachment, but there are validations on both :attachment and :attachment_file_name. If the form has a file picker on :attachment, you would like to highlight it with errors from any attribute:

class Note < ActiveRecord::Base
  has_attached_file :attachment
  validates_attachment_presence :a...

Rails: Using custom config files with the config_for method

You can use the config.x configuration in combination with config_for to configure global settings for your Rails 4.2+ application.

Example

In your config/application.rb assign the settings from e.g. config/settings.yml as follows:

module FooApplication
  class Application < Rails::Application
    config.x.settings = config_for(:settings)
  end
end

The config/settings.yml might look as follows:

shared: &shared
  email: info@example.com
...

Dockerfile and Heredocs

I recently did a quick research on how to better write down multiline statements like this:

# Dockerfile
RUN export DEBIAN_FRONTEND=noninteractive \
  && apt-get update \
  && apt-get dist-upgrade -y \
  && apt-get install --no-install-recommends --no-install-suggests -y \
    ca-certificates \
    curl \
    unzip

It turns out, there is! Buildkit, the tool behind docker build added support for heredoc strings in May 2021.
Now we could refactor the code above like this:

Browser debugging tricks

A list of clever debugging tricks. TOC:

  • Advanced Conditional Breakpoints
  • monitor() class Calls
  • Call and Debug a Function
  • Pause Execution on URL Change
  • Debugging Property Reads
    • Use copy()
  • Debugging HTML/CSS

RubyMine: Real-time Collaborating in the IDE

RubyMine has a collaboration feature called "Code With Me". Using it, you can invite someone into your local editor to work together. This is nicer to the eyes and much more powerful than sharing code through some video chat.

How to

Getting started is really simple:

  1. Click the "add person" icon in the top-right editor corner (or hit Ctrl + Shift + Y) and select "Start Session".
  2. Choose permissions:
    • "Read-only" lets others only watch you.
    • "Edit files" is needed for pairing. Note that this allows remote partners to, well, ...

Ignore commits when git blaming

You can ignore certain commits when using git blame with the --ignore-revs-file option. This is handy to ignore large rubocop commits or big renamings in your project. You can add and commit a .git-blame-ignore-revs file in your project to track a list of commits that should be ignored.

# a list of commit shas
123...
456...

Use git blame with the --ignore-revs-file option and ignore the SHAs specified in .git-blame-ignore-revs.

git blame --ignore-revs-file .git-blame-ignore-revs

If you want to use this flag by def...

You should probably load your JavaScript with <script defer>

It is generally discouraged to load your JavaScript by a <script src> tag in the <head>:

<head>
  <script src="app.js"></script>
</head>

The reason is that a <script src> tag will pause the DOM parser until the script has loaded and executed. This will delay the browser's first contentful paint.

A much better default is to load your scripts with a <script src defer> tag:

<head>
  <script src="app.js" defer></script>
</head>

A deferred script has many useful properties:

  • I...

How to: Context-dependent word expansion in RubyMine

One of the many useful features of TextMate is autocompletion of words. If I were in TextMate right now, I could write "au[tab]", and it would complete it to "autocompletion". RubyMine can do this, too. When you write a word (e.g. a variable name), just hit ALT + / repeatedly and it will offer all completions for the letters you typed. This action is called Cyclic Expand Word in RubyMine / IntelliJ IDEA.

This feature keeps you from mistyping variable names, saves you keystrokes and speeds up development. ~10 keystrokes to the price ...

Disable PostgreSQL's Write-Ahead Log to speed up tests

The linked article suggests an interesting way to speed up tests of Rails + Postgres apps:

PostgreSQL allows the creation of “unlogged” tables, which do not record data in the PostgreSQL Write-Ahead Log. This can make the tables faster, but significantly increases the risk of data loss if the database crashes. As a result, this should not be used in production environments. If you would like all created tables to be unlogged in the test environment you can add the following to your...