How to get information about a gem (via CLI or at runtime from Ruby)

When you need information about a gem (like version(s) or install path(s)), you can use the gem binary from the command line, or the Gem API inside a ruby process at runtime.

gem binary (in a terminal)

You can get some information about a gem by running gem info <gem name> in your terminal.

Example:

$ gem info irb

*** LOCAL GEMS ***

irb (1.4.1, 1.3.5)
    Author: Keiju ISHITSUKA
    Homepage: https://github.com/ruby/irb
    Licenses: Ruby, BSD-2-Clause
    Installed at (1.4.1): /home/arne/.rbenv/versions/3.0.3/lib/ruby/g...

JavaScript: Working with Query Parameters

tl;dr: Use the URLSearchParams API to make your live easier if you want to get or manipulate query parameters (URL parameters).

URLSearchParams API

The URLSearchParams API is supported in all major browsers except IE 11.

It offers you a bunch of useful methods:

  • URLSearchParams.append() - appends a query parameter
  • URLSearchParams.delete() - deletes the specified query parameter
  • URLSearchParams.get() - returns the value of the specified query parameter
  • `URLSearchP...

Version 5 of the Ruby Redis gem removes Redis.current

Redis.current will be removed without replacement in redis-rb 5.0.
Version 4.6.0 adds deprecation warnings for Redis.current and Redis.current=:

`Redis.current=` is deprecated and will be removed in 5.0.

If your application still uses Redis.current, you can only fix it by no longer using it. Here is how.

Redis.new when you need it

You can easily instantiate a Redis client when you need it.

There is probably already a constant like REDIS_URL that you use to configure Sidekiq or similar. So just use that one.

``...

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

esbuild: Make your Rails application show build errors

Building application assets with esbuild is the new way to do it, and it's great, especially in combination with Sprockets (or Propshaft on Rails 7).
You might be missing some convenience features, though.

Here we cover one specific issue:
Once you have started your development Rails server and esbuild with the --watch option (if you used jsbundling-rails to set up, you probably use bin/dev), esbuild will recompile your assets upon change, but build errors will only be printed to the terminal. Your application won't complain about them ...

Carrierwave: How to attach files in tests

Attaching files to a field that is handled by Carrierwave uploaders (or maybe any other attachment solution for Rails) in tests allows different approaches. Here is a short summary of the most common methods.

You might also be interested in this card if you see the following error in your test environment:

CarrierWave::FormNotMultipart:
You tried to assign a String or a Pathname to an uploader, for security reasons, this is not allowed.
If this is a file upload, please check that your upload form is multipart encoded.

Factor...

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

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

Caching in Rails < 6.1 may down parts of your application when using public cache control

Proxy caching is a good feature to serve your publicly visible application content faster and reduce load on your servers. It is e.g. available in nginx, but also affects proxies delivered by ISPs.

Unfortunately, there is a little problem in Rails < 6.1 when delivering responses for different MIME-types. Say you have an arbitrary route in your Rails application that is able to respond with regular HTML and JSON. By sending the specific MIME type in the Accept header, you tell the application to either return HTML (text/html) or JSON (`t...

Elasticsearch: recover from readonly mode

Elasticsearch defaults to go into readonly mode when you run low on disk space (< 95%). You might then see an error like this when you try to write to elastic:

Elasticsearch::Transport::Transport::Errors::Forbidden:
       [403] {"error":{"root_cause":[{"type":"cluster_block_exception","reason":"blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];"}],"type":"cluster_block_exception","reason":"blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];"},"status":403}

Even after freeing up space and restarting elas...

Ad blockers: How to debug blocked elements

Some users might use Adblock Plus or similar browser plugins to reduce the number of ads displayed. If you run into an issue that your application or part of an application is blocked, this card will give you some guidance on how to debug it.


In general ad blocking is not an issue for most of our web apps. But if your application uses iframes or is embedded in another site it's more prone to it.

Blocked elements most of the time appear to the user as empty frames in the page. The indicator icon of the ad blocker also gives ...

Using feature flags to stabilize flaky E2E tests

A flaky test is a test that is often green, but sometimes red. It may only fail on some PCs, or only when the entire test suite is run.

There are many causes for flaky tests. This card focuses on a specific class of feature with heavy side effects, mostly on on the UI. Features like the following can amplify your flakiness issues by unexpectedly changing elements, causing excessive requests or other timing issues:

  • Lazy loading images
  • Autocomplete in search f...

Setup Sidekiq and Redis

If you want Sidekiq to be able to talk to Redis on staging and production servers, you need to add the following to your configuration:

# config/initializers/sidekiq.rb
require 'sidekiq'

Sidekiq.configure_client do |config|
  config.redis = { url: REDIS_URL }
end

Sidekiq.configure_server do |config|
  config.redis = { url: REDIS_URL }
end

The following step may be skipped for new Sidekiq 6+, since it isn't recommended anymore to use a global redis client.

# config/initializers/redis.rb
require 'redis'
require_relativ...

RSpec: how to prevent the Rails debug page if you want to actually test for 404s

Within development and test environments, Rails is usually configured to show a detailed debug page instead of 404s. However, there might be some cases where you expect a 404 and want to test for it.

An example would be request-specs that check authorization rules. (If you use a gem like consul for managing authorization rules, you should always check these rules via power-specs. However, request-specs can be used as a light-weight version of integration tests here.)

In this case, Rails will replace the 404 page that you want to test ...

RSpec: automatic creation of VCR cassettes

This RailsCast demonstrated a very convenient method to activate VCR for a spec by simply tagging it with :vcr.

For RSpec3 the code looks almost the same with a few minor changes. If you have the vcr and webmock gems installed, simply include:

# spec/support/vcr.rb
VCR.configure do |c|
  c.cassette_library_dir = Rails.root.join("spec", "vcr")
  c.hook_into :webmock
end

RSpec.configure do |c|
  c.around(:each, :vcr) do |example|
    name = example.metadata[:full_descripti...

Working on the Linux command line: How to use bookmarks for directories

Bookmarks for directories will be most helpful if you are forced to work in deeply nested projects. Then it's really helpful!

This makes use of the CDPATH variable. Similar to the PATH variable, which holds the list of directories which are searched for executables, CDPATH contains the list of directories that are available for cd. Besides the current directory (.), you can add others to that.

The trick is to add a directory for bookmarks to CDPATH.

First, create the directory with: mkdir ~/.bookmarks.

Then add the followin...

Working on the Linux command line: How to efficiently navigate up

With cd .. you can navigate one directory up from the one you are at now. If you use that a lot, consider some handy aliases.

Add the following lines to your ~/.bashrc:

alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
alias .....="cd ../../../.."
alias ......="cd ../../../../.."

you can add even more aliases, but I usually loose track after too many levels and just jump to the directly directly, e.g. using its absolute path or its bookmark (see [this card](https://makandracards.com/makandra/504947-working-on-the-li...

Unpoly 2: Don't try to download files through AJAX requests

Rails has the handy controller method send_file which lets us download files easily. We can decide whether the file should be downloaded (disposition: 'attachment') or shown in the browser (disposition: 'inline'). The default is disposition: 'attachment'.

Downloading files will not work when you are calling the controller action from an AJAX request. The browser will try to render the file and insert it in the DOM, which is never what you want.

Unpoly 2

Unpoly (sin...

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

Bookmarklet to facilitate generating new git branches for PivotalTracker Stories

This bookmarklet grabs a PivotalTracker story title, transforms it into a valid git branch name and automatically prepends your initials and an optional abbreviation (for better tab completion). It will output the following formats:

If you cancel the first dialog or confirm it without entering text:

git checkout -b kw/178298638-card-320-state-machines

If you enter an abbreviation (e.g. stm in this case):

git checkout -b kw/stm/178298638-card-320-state-machines

How to set it up:

  • in the attached file replace `YOUR_INITI...

Headless Chrome: Changing the Accept-Language header is not possible

It seems like changing the HTTP_ACCEPT_LANGUAGE is not possible for a headless chrome.

  • On Ubuntu the headless Chrome derives the Accept-Language from the operation system
  • Adding the option options.add_argument('--lang=de') to the Capybara::Selenium::Driver has no effect
  • Adding the preference options.add_preference('intl.accept_languages', 'de') to the Capybara::Selenium::Driver has only effects if the --headless option is skipped (see bug ticket #775911)
  • Cha...

How to avoid raising RestClient exceptions for 4xx or 5xx results

When using RestClient to make an HTTP request, it will raise an exception when receiving a non-successful response.
HTTP status codes like 422 or 403 might be totally expected when talking to APIs, so plastering your code with rescue RestClient::Exception or similar can feel annoying.

It may not be intuitive, but the readme says you can also pass a block to methods like RestClient.get or RestClient::Request.execute. In that case, RestClient will not raise ...