Finding ancestors with Capybara

Modern versions of Capybara include a finder method #ancestor which allows you to find a parental element using CSS or XPath.

If you previously did something like this:

field.find(:xpath, './ancestor::div[contains(@class, "form-group")]')

..and prefer CSS, you may rewrite it:

field.ancestor('div.form-group')

Both versions will return the outermost matching element. Use the #order option find the closest parent:

field.ancestor('div.form-group', order: :reverse)

Hints for debugging MySQL InnoDB deadlocks

Deadlocks only occur if two transactions in separate threads compete for the same rows in the database. They usually (but not necessarily) only happen when trying to update or otherwise lock several rows in different order.

Solving deadlocks is potentially complicated, so here are a few pointers:

  • MySQL should always detect the deadlock right when it happens, and will throw an error to one of the offending threads. This error states the SQL statement that this thread was currently waiting for, and that tried to acquire one of the competin...

You can use graphs in gitlab comments!

Since GitLab 10.3. you can use Mermaid in GitLab comments: Gitlab Doc.
With Mermaid you can create diagrams based on text / code.

Sometimes a picture says more than thousand words and can help you express your thoughts more clearly.

Image

Image

Some Examples from the Mermaid documentation:

Flowcharts

graph TD;
    A-->B;
    A-->C...

Strict Loading Associations can prevent n+1 queries

Rails 6.1 has a "strict loading" mode that forces the developer to preload any association they plan to use. Associations no longer load lazily. An error is raised when reading an association that was not preloaded.

Enabling strict loading is a tool to prevent n+1 queries.

Strict loading can be enabled for individual records, for a single association,...

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

RSpec: ". not_to include" behaves like ".to exclude"

RSpec is smart when using the include-matcher in combination with .not_to. One could assume that

.not_to include(3, 4, 5)

evaluates to:

NOT( .to include(3, 4, 5) )

However, it behaves like:

.to (NOT include(3) && NOT include(4) && NOT include(5) )

Warning

Using .not_to in combination with the include-matcher doesn't logically negate the final truth value. It instead negates the individual include-expectations for each argument.

Proof

describe 'RSpec' do
  it "doesn't use logical nega...

A Guide To CSS Debugging

Debugging in CSS means figuring out what might be the problem when you have unexpected layout results. We’ll look at a few categories bugs often fit into, see how we can evaluate the situation, and explore techniques that help prevent these bugs.

Fix REPL of better_errors page

The gem better_errors offers a detailed error page with an interactive REPL for better debugging.
I had the issue that on a few projects with Ruby 2.5.8, the REPL was not shown.

Solution

To make the REPL work properly with this Ruby version I had to update the gem binding_of_caller to at least version 0.8.0.

From the [better_errors](https://github.com/BetterE...

Git shortcut to rebase onto another branch

Inspired by recent "git shortcut" cards I figured it would be nice to have one of these for rebasing a few commits onto another branch. The usual notation is prone to of-by-one errors as you have to either specify the commit before the ones you want to move or count the number of commits.

You may add this rebase-onto function to your ~/.bashrc:

function rebase-onto {
  commit=$(git log --oneline | fzf --prompt 'Select the first commit y...

Cancelling the ActiveRecord callback chain

What Rails version Within before_* Within after_*
Cancel later callbacks Rails 1-4 return false return false
Cancel later callbacks Rails 5+ throw :abort throw :abort
Rollback the transaction Rails 1-4 return false raise ActiveRecord::Rollback
Rollback the transaction Rails 5+ `thr...

Capybara can find links and fields by their [aria-label]

Sometimes a link or input field has no visible label. E.g. a text field with a magnifying glass icon 🔎 and a "Search" button does not really need a visible label "Query".

For accessibility reasons it is good practice to give such a field an [aria-label] attribute:

<input type="search" aria-label="Search contacts">

This way, when a visually impaired user focuses the field, the screen reader will speak the label text ("Search contacts").

Info

Without an `[aria-...

Disable built-in dragging of text and images

Most browsers have built-in drag and drop support for different page elements like text and images. While this may be useful in most situations, it may become annoying in others. If you e.g. want to allow the user to scroll/move horizontally within a container by grabbing an item and moving the mouse, you will notice that nothing will move and you'll instead start dragging that element.

To disable this, add the following CSS to your content:

-webkit-user-drag: none
user-drag: none

-webkit-user-drag is only fully supported in ...

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

Building web applications: Beyond the happy path

When building a web application, one is tempted to claim it "done" too early. Make sure you check this list.

Different screen sizes and browsers

Desktops, tablets and mobile devices have all different screen resolutions. Does your design work on each of them?

  • Choose which browsers to support. Make sure the page looks OK, is usable and working in these browsers.
  • Use @media queries to build a responsive design
    • If you do not suppo...

Webpack(er): A primer

webpack is a very powerful asset bundler written in node.js to bundle (ES6) JavaScript modules, stylesheets, images, and other assets for consumption in browsers.

Webpacker is a wrapper around webpack that handles integration with Rails.

This is a short introduction.

Installation

If you haven't already, you need to install node.js and Yarn.

Then, put

gem 'webpacker', '~> 4.x' # check if 4.x is still cu...

Git shortcut to checkout recent branches

If you have fzf installed, you may add an alias such as this to your ~/.bashrc:

alias recent-branch="git for-each-ref --sort=-committerdate --format='%(refname:short)' refs/heads/ |  fzf | sed 's/\* //g' | xargs -I '{}' git checkout {}"

Now whenever you want to switch back and forth between your most recent branches, type recent-branch, select one and press enter.

Large CSS box shadows can bring browsers to a crawl

Browser rendering engines are very slow at rendering large box shadows. I had a situation where a complex layout with fixed elements and large shadows slowed Firefox down to 2 frames/second for scrolling and DOM manipulation.

Some advice:

  • Be aware that by introducing fixed elements (e.g. sticky navigation bars) and large animations, you might force the browser to redraw large portions of the site when scrolling. When your fixed elements have shadows, this increases the screen area that needs to be redrawn, which might again require other...

Rails: Removing the cucumber-rails warning when setting cache_classes to false without Spring enabled

We are using Spring in our tests for sequential test execution but not for parallel test execution. And Rails requires you to set the config.cache_classes = false if you are using Spring in tests.

With our setup, this would raise the following error in cucumber-rails for parallel test executions due to some legacy database cleaner issue.

WARNING: You have set Rails' config.cache_classes to false
    (Spring needs cache_classes set to false). This is known to cause probl...

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

The many gotchas of Ruby class variables

TLDR: Ruby class variables (@@foo) are dangerous in many ways. You should avoid them at all cost. See bottom of this card for alternatives.

Class variables are shared between a class hierarchy

When you declare a class variable, it is shared between this and all descending (inheriting) classes. This is rarely what you want.

Class variables are bound at compile-time

Like unqualified constants, class variables are bound to your current scope *whe...