How to list updateable dependencies with Bundler and Yarn

Bundler

bundle outdated [--filter-major|--filter-minor|--filter-patch]

Example output for bundle outdated --filter-major

Image

Other examples

A useful flag is --strict as it will only list versions that are allowed by your Gemfile requirements (e.g. does not show rails update to 6 if your Gemfile has the line gem 'rails', '~>5.2').

I also experienced that doing upgrades per group (test, development) are easier to do. Thus --groups might also be helpful.

$ bundle...

Using ngrok for exposing your development server to the internet

Sometimes you need to access a dev server running on localhost from another machine that is not part of the same network. Maybe you want to use your phone to test a web page, but are only in a guest WiFi. In the past, we often used some port forwarding or other techniques to expose the service to the internet.

Enter ngrok, a command line tool that gives you an on-the-fly internet...

Automated "git bisect" will make your day

So you're hunting down a regression (or just a bug) and want to use git bisect to find out when it was introduced? Smart kid.
If you have a shell command ready to reveal if your current state is good or bad, you can have git do most of the work for you.

Using git bisect run <your command> you can tell git that your command will reveal the issue; git on the other hand will use the return value of that call to decide if the state is good or bad.
...

How to: Use git bisect to find bugs and regressions

Git allows you to do a binary search across commits to hunt down the commit that introduced a bug.

Given you are currently on your branch's HEAD that is not working as expected, an example workflow could be:

git bisect start # Start bisecting
git bisect bad # Tag the revision you are currently on (HEAD) as bad. You could also pass a commit's SHA1 like below:
git bisect good abcdef12345678 # Give the SHA1 of any commit that was working as it should
# shorthand:
git bisect start <bad ref> <good ref>

Git will fetch a comm...

Heads up: network requests `Kernel#open` are not mocked with VCR

We usually rely on VCR and WebMock to prevent any real network connection when running our unit tests.

This is not entirely true: They are both limited to a set of HTTP libraries listed below (as of 2022). Direct calls to Kernel#open or OpenURI#open_uri are not mocked and will trigger real network requests even in tests. This might bite you e.g. in [older versions of CarrierWave](https://github.com/carrierwaveuploader/carrierwave/blob/0.11-stable/lib/carrierwave/upl...

Carrierwave: Built-in RSpec matchers

CarrierWave comes with some RSpec matchers which will make testing more comfortable. Let's say you have an Uploader like this:

class MyUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  # Create different versions of your uploaded files:
  version :small do
    process resize_to_fill: [100, 100]
  end
  
  version :medium do
    process resize_to_fit: [200, nil]
  end
  
  version :large do
    process resize_to_limit: [400, 400]
  end

end

Imagine you have a class Movie with an attribute poster. In ...

RSpec: How to aggregate failures

RSpec >= 3.3 added aggregate_failures, which allows multiple failures in an example and list them all, rather than aborting on the first failure.

This can be used:

  • In the global configuration
  • With the tag :aggregate_failures (our preferred option in case every expectations should be aggregated)
  • With the method aggregate_failures

[Here](https://web.archive.org/web/20210110131654/https://relishapp.com/rspec/rspec-core/docs/expec...

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

Bash functions to provide repository context for LLM chats

I use the Gemini web chat interface quite extensively. One thing that is tedious is giving it all the context it needs to do a proper job. Context engineering is not an easy task, but on the other hand we now have context limits of ~1 million token, which allows us to just dump in everything we have in many cases. And when we do that in the web interface, we can avoid extra costs that would be charged when using the API!

The functions below pack your current work (diffs, full repos, or specific commits) into XML/Diff files, which are then ...

Issue Checklist Template

This is a checklist I use to work on issues. For this purpose I extracted several cards related to the makandra process and ported them into a check list and refined that over time a little bit.

This task list is divided by the Gate keeping process in the following steps:

1. Starting a new feature
2. Working on the issue
3. Finishing a feature
4. After Review

Here are some ti...

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

Don't assert exceptions in feature specs

As we are slowly switching from Cucumber scenarios to RSpec feature specs, you might be tempted to write assertions like this one:

feature 'authorization for cards management' do
  let(:guest_user) { create(:user, :guest) }

  scenario "rejects guest users from adding new cards", js: true do
    sign_in guest_user

    expect { visit new_cards_path }.to raise_error(Consul::Powerless)
  end
end

While this might work under certain circumstances¹, there is a good chance you'll see two exceptions when running this single spec:

  • ...

RSpec: Ensuring a method is called on an object that will be created in the future

rspec >= 3.1 brings a method and_wrap_original. It seems a bit complicated at first, but there are use cases where it helps to write precise tests. For example it allows to add expectations on objects that will only be created when your code is called.

If you have older rspec, you could use expect_any_instance_of, but with the drawback, that you can't be sure if it really was the correct instance which got the message.

Example

The example model uses different validators based on a flag:

class MyModel < ApplicationRecord

 ...

RSpec: How to write isolated specs with cookies

Background

Rails offers several methods to manage three types of different cookies along with a session storage for cookies. These are normal, signed and encrypted cookies.

By following the happy path of testing a web application, that is only the main use-case is tested as a integration test and the rest as isolated (more unit ...

How to add esbuild to the rails asset pipeline

This are the steps I needed to do to add esbuild to an application that used the vanilla rails asset pipeline with sprockets before.

Preparations

  1. update Sprockets to version 4
  2. add a .nvmrc with your preferred node version (and install it)
  3. add gems jsbundling-rails and foreman to your Gemfile:
    gem 'jsbundling-rails'
    group :development, :test do
      gem 'foreman'
      # ...
    end
    
  4. bundle install
  5. run bin/rails javascript:install:esbuild in a console to prepare esbuild.
  6. run `yarn instal...

Heads up: expect(object).to receive(:method_name) does not execute the original implementation of the method

Let's assume that we have a model Movie that registers a callback function when a new instance of Movie is created (Note: For the purpose of this card it is not important what that callback does or which type of callback it is).

This is how we test whether the callback function (here it is named :my_method) is called when a new movie is created:

expect_any_instance_of(Movie).to receive(:my_method)
create(:movie)  # <-- this is where the method :my_method should be called

You might expect that when calling `create(:mo...

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

RSpec: Inferring spec type from file location

RSpec Rails can automatically mix in different behaviors to your tests based on their type tag, for example enabling you to call get and
post in specs with the tag type: :request.

Alternatively you can skip these tags by setting the config config.infer_spec_type_from_file_location! in the spec_helper.rb. This will automatically choose the right type context based on the file location of the test.

For instan...

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. Further evidence supporting this is the fact that Aider already writes ~70% of its own code (as of 02/2025). However, when starting out, your results may fall short of efficiently generating large portions of your code with the...

Rails: Using require and permit for attributes

Raising errors for required and permitted attributes makes it easier to find errors in your application during development and in tests. Consider this approach if you want to strengthen the params handling in your application.

Example

# config/application.rb

config.action_controller.action_on_unpermitted_parameters = :raise
def user_params
  params.require(:user).permit(:full_name)
end

Effects

  • This raises an error `Ac...

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

Rails: Use fixture helpers like `users(:alice)` in the Rails console

In tests you can write users(:alice) to look up a fixture record. The same helper is not available in the Rails console, so debugging a fixture by name means looking it up by primary key (or by some unique attribute that you have to remember). A small initializer brings the helpers into the console.

Prerequisite: the fixtures must be loaded

This initializer does not load fixture data. It only looks records up by their fixture-derived ID. You have to seed the database first with

bin/rails db:fixtures:load

In the test envir...

Regular Expressions - Cheat Sheet

You can write regular expressions some different ways, e.g. /regex/ and %r{regex}. For examples, look here.

Remember that it is always a good idea to match a regex visually first.

Characters

Literal Characters

[ ] \ ^ $ . | ? * + ( )

Character Classes

[ae]            matches a and e, e.g. gr[ae]y => grey or gray => but NOT graay or graey
[0-9]  ...