Using Low-Level Prompts for High-Accuracy AI Coding

The key to unlocking the full potential of LLMs in coding lies in crafting precise prompts. The main challenge is learning how to structure prompts effectively to guide the model toward accurate results.

In this card, I explore a prompting technique I’ve found useful for making edits across multiple files.

Prompt Structure

The following structure provides a clear and repetitive pattern that helps the LLM understand and accurately describe code m...

Git commands to discard local changes

Use case

You have uncommited changes (you can always check by using git status), which you want to discard.

Context

Now there are several options to discard these depending on your exact situation.
The headlines will differentiate the cases whether the files are staged or unstaged.

  1. Staged and unstaged changes
  2. [Staged changes](https://makandracards.com/makandra/516559-git-commands-to-discard-local-changes#s...

RSpec: Tagging examples and example groups

In RSpec you can tag examples or example groups with any tags you like simply by saying

describe ReportCreator, slow: true do
  # ..
end

describe ReportCreator do
  it 'generates reports', slow: true do
    # ...
  end
end

You can then only run examples with these tags.

rspec --tag slow
rspec -t slow

# Using the parallel_tests gem
rake "parallel:spec[,,--tag slow]"

Or you can run all examples except the ones with a certain tag:

rspec --tag ~slow # note the ~
rspec -t ~slow

# Using the parallel_tests gem
r...

PSA: "index: true" in Rails migrations does not work as you'd expect

Several Rails migration methods accept index: true as an option to create an index. In some cases (like #add_column), this option is silently discarded. Know what you are doing, or use #add_index instead.

Example

Consider the following migration.

class CreateExamples < ActiveRecord::Migration
  def change
    create_table :examples do |t|
      t.references :category, index: true
      t.boolean :positive, index: true
      t.integer :number_of_participants, index: true
    end

    add_reference :examples, :user, index: tr...

Writing a README for a project

Rails applications and ruby gems should have a README that gives the reader a quick overview of the project. Its size will vary as projects differ in complexity, but there should always be some introductory prose for a developer to read when starting on it.

Purpose

That's already the main purpose of a project README: Give a new developer a quick overview of the project. In sketching this outline, the README should notify the reader of any peculiarity he needs to know of.

Remember that in a few months, you'll be a kind of "new ...

Google Analytics: Change the tracked URL path

By default, Google Analytics tracks the current URL for every request. Sometimes you will want to track another URL instead, for example:

  • When an application URL contains a secret (e.g. an access token)
  • When you want to track multiple URLs under the same bucket
  • When you want to track interactions that don't have a corresponding URL + request (e.g. a Javascript button or a PDF download)

Luckily the Analytics code snippet allows you to freely choose what path is being tracked. Simple change this:

ga('send', 'pageview');

......

The Ruby Object Model

In Ruby (almost) everything is an Object. While this enables a lot of powerful features, this concept might be confusing for developers who have been programming in more static languages, such as Java or C#. This card should help understanding the basic concepts of Ruby's object model and how things behave.


Usage of objects in Ruby

When working with objects in Ruby, you might think of a "container" that holds metadata, variables and methods. Metadata describes stuff like the object's class or its object_id whi...

Installing Python packages using pip on Ubuntu 24.04

Ubuntu 24 added some guarding for Python packages which no longer allows installing applications through pip on system level. Instead, you are presented with this error message:

error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.
    
    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use...

Shell script to magically configure display setup

Here is a bash script that I use to auto-configure displays on Ubuntu 24.04 with Xorg.

Background

  • Ubuntu always sets the primary display to the 1st (i.e. internal) display whenever I connect to a new Dock/Hub.
    • I want my primary display to be the large display.
    • My notebook is always placed left of external displays, so the 2nd display will be the center (or only) external display and should be primary.
  • I also want all my displays to be placed horizontally, but bottom-aligned (the default would be aligned at their top edges)....

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

Rails and Postgres: How to test if your index is used as expected

This is a small example on how you can check if your Postgres index can be used by a specific query in you Rails application. For more complex execution plans it might still be a good idea to use the same path of proof.

1. Identify the query your application produces

query = User.order(:last_name, :created_at).to_sql
puts query
# => SELECT "users".* FROM "users" ORDER BY "users"."last_name" ASC, "users"."created_at" ASC

2. Add an index in your migration and migrate

add_index :users, [:last_name, :created_at]...

HTML: Making browsers wrap long words

By default, browsers will not wrap text at syllable boundaries. Text is wrapped at word boundaries only.

This card explains some options to make browsers wrap inside a long word like "Donaudampfschifffahrt".

Option 1: hyphens CSS property

Modern browsers are able to hyphenate natively with the CSS property hyphens:

hyphens: auto

There is also hyphens: none (disable hyphenations even at &shy; entities) and hyphens: manual (hyphenation at &shy; only).

For the hyphens property to wor...

How to reduce a video's file size with ffmpeg

Using ffmpeg, you can easily re-encode a video to reduce its file size.

Command

Do it like this:

ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset slow -c:a copy -movflags +faststart output.mp4

Arguments

  • -i input.mp4 specifies your input file
  • -c:v libx264 specifies H.264 encoding.
    • Use -c:v libx265 for H.265/HEVC. It's an excellent modern encoding standard that is fairly widely supported, but not on older devices.
  • -crf 23 specifies the Constant Rate Factor, i.e. video quality.
    • Lower values mean higher...

How to disable telemetry for various open source tools and libraries

If you're lucky DO_NOT_TRACK=1 opts you out of CLI telemetry - it's not widely adopted. When you're using any of the libraries below, I'd rather opt out explicitly:

Yarn

https://yarnpkg.com/advanced/telemetry (Since: Version 2.2)

Disable for a project:

# .yarnrc.yml
---
enableTelemetry: false # Relevant from yarn v2.2

Disable on your machine:

yarn config set --home enableTelemetry 0

Next.js

https://nextjs.org/telemetry

...

How to use your favorite font in Slack

In Slack, the settings dialog only offers a fixed selection of fonts. You can use any font you like using the /slackfont command.

Fonts need to be installed on your machine. Webfonts beyond those provided by Slack won't magically work unless you install them locally.
Only the chat font can be changed. The monospaced font used for code blocks isn't easily customizable.

Example usage

  • /slackfont Comic Neue to use "Comic Neue" (if installed)
  • /slackfont system-ui to use your desktop's system font in Slack.
  • /slackfont (withou...

BEM naming conventions

We structure our CSS using the BEM pattern.

Our naming convention for blocks, elements and modifiers has evolved over the years. This card shows our current style and various alternative styles that you might encounter in older projects.

The difference between the various styles are mostly a matter of taste and optics. I do recommend to not mix styles and be consistent within a given project.

Current convention

Our current BEM naming convention looks...

How to send HTTP requests using cURL

  • Reading a URL via GET:

    curl http://example.com/
    
  • Defining any HTTP method (like POST or PUT):

    curl http://example.com/users/1 -XPUT
    
  • Sending data with a request:

    curl http://example.com/users -d"first_name=Bruce&last_name=Wayne"
    

    If you use -d and do not set an HTTP request method it automatically defaults to POST.

  • Performing basic authentication:

    curl http://user:password@example.com/users/1
    
  • All together now:

    curl http://user:password@example.com/users/1 -XPUT -d"screen_name=batman"
    

...

ActiveRecord: Passing an empty array into NOT IN will return no records

Caution when using .where to exclude records from a scope like this:

# Fragile - avoid
User.where("id NOT IN (?)", excluded_ids)

When the exclusion list is empty, you would expect this to return all records. However, this is not what happens:

# Broken example
User.where("id NOT IN (?)", []).to_sql
=>  SELECT `users`.* FROM `users` WHERE (id NOT IN (NULL))

Passing an empty exclusion list returns no records at all! See below for better implementations.

Rails 4+

Use the .not method to let Rails do the logic

`...

Rails: Accessing strong parameters

Rails wraps your parameters into an interface called StrongParameters. In most cases, your form submits your data in a nested structure which goes hand in hand with the strong parameters interface.

Example:

curl -X POST -d "user[name]=bob" https://example.com/users
class UsersController
  def create
    User.create!(params.expect(user: [:name])) # Or User.create!(params.require(:user).permit(:name))
  end
end

This works well most of the time...

How to write a good image alt text

This decision tree describes how to use the alt attribute of the element in various situations. For some types of images, there are alternative approaches, such as using CSS background images for decorative images or web fonts instead of images of text.

Questions asked:

  • Does the image contain text?
  • Is the image used in a link or a button, and would it be hard or impossible to understand what the link or the button does, if the image wasn’t there?
  • Does the image contribu...

CSS & a11y: When hiding with opacity, also set visibility:hidden (transitions supported)

Elements can be hidden and shown by toggling the display property. However, this is not animatable, so we often turn to opacity. At opacity: 0, the element is hidden, and with a nice transition on that property, it can be faded in and out smoothly.

Yet, opacity only hides visually, not technically: the element is still focusable and visible to screen readers. So, how can we fade an element while maintaining accessibility?

Enter visibility. It also hides elements, bu...

Enumerators in Ruby

Starting with Ruby 1.9, most #each methods can be called without a block, and will return an enumerator. This is what allows you to do things like

['foo', 'bar', 'baz'].each.with_index.collect { |name, index| name * index }
# -> ["", "bar", "bazbaz"]

If you write your own each method, it is useful to follow the same practice, i.e. write a method that

  • calls a given block for all entries
  • returns an enumerator, if no block is given

How to write a canonical each method

To write a m...

ActiveSupport includes Timecop-like helpers

ActiveSupport (since 4.1) includes test helpers to manipulate time, just like the Timecop gem:

  • To freeze the current time, use freeze_time (ActiveSupport 5.2+):

    freeze_time
    
  • To travel to a specific moment in time, use travel_to:

    travel_to 1.hour.from_now
    

    Important

    When freezing time with #travel_to, time will be frozen (like with freeze_time). This means that your application can't detect passage of time by using Time.now.

  • To travel a re...