Don't forget: Automatically remove join records on has_many :through associations

Bad

# Given the following models

class Image < ActiveRecord::Base
  has_many :album_images
  has_many :albums, through: :album_images
end

class Album < ActiveRecord::Base
  has_many :album_images
  has_many :images, through: :album_images
end

# Join model
class AlbumImage < ActiveRecord::Base
  belongs_to :album
  belongs_to :image
end

Destroying a record in this setup will only remove the record itself, and leave orphaned join records behind.

image = Image.last
image.destroy # removes only the `image` record,
   ...

Using form models (aka decorators) with Devise

To use a form model with devise, you can simply override #resource_class in a controller. A typical use case would be the registrations controller, as users will need some fields only on sign-up. Example:

class Frontend::Authentication::RegistrationsController < Devise::RegistrationsController

  private

  def resource_class
    FrontendUser::AsSignUp # my decorator class, extending from FrontendUser
  end

end

Fontawesome 4+ icon naming conventions

Fontawesome 4 has introduced new naming conventions that make it easy to retrieve variants of a given icon.

The format is:

fa-[name]-[alt]-[shape]-[o]-[direction]

Note that this is a naming convention which doesn't imply there's an icon for any combination of tags.

name

The name of the icon, e.g. comment, print, bookmark etc. See the full list.

alt

An alternative icon.

shape

The icon inside a circle or square.

o

An outlined ...

Rails 4 introduced collection_check_boxes

Starting from Rails 4.0, you can use a special form options helper called #collection_check_boxes. It behaves similar to #collection_select, but instead of a single select field it renders a checkbox and a label for each item in the collection.

= form_for @post do |form|
  = form.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial

How generated form params look like
---------------------------------...

Capybara: Waiting for pending AJAX requests after a test

When ending a Selenium test Capybara resets the browser state by closing the tab, clearing cookies, localStorage, etc.

It may be a good idea to wait for all in-flight AJAX requests to finish before ending a scenario:

  • You may have client-side JavaScript that freaks out when the tab closure kills their pending requests. If that JavaScript opens an error alert or spams errors to the console, your test may fail after the last step.
  • With unlucky timing the server may receive an AJAX request as the browser tab closes, causing a connection ...

rspec_candy 0.4.0 released

  • Now supports RSpec 3 and Rails 4
  • Drops support for state_machine, which has some issues with Rails 4 and isn't actively maintained

Differences between transactions and locking

Web applications can be used by multiple users at the same time. A typical application server like Passenger has multiple worker processes for a single app. In a distributed deployment setup like we use at makandra you will even have multiple application servers, each with their own worker pool.

This means that your code needs to deal with concurrent data access. The two main tools we use to cope with concurrency are database transactions and distributed locks. These two are not interchangeable. You ca...

Verifying doubles in RSpec 3

RSpec 3 has verifying doubles. This breed of mock objects check that any methods being stubbed are present on an instance of a given class. They also check methods aren't called with the wrong number of arguments.

This dual approach allows you to move very quickly and test components in isolation, while
giving you confidence that your doubles are not a complete fiction.

You should always prefer using a verifying double to using an old-school mock...

Communication between collaborating directives in Angular

What if a complicated component comes along that is naturally modeled by multiple directives? This group of directives, as a whole, form a single self contained component. None of directives in the group can stand alone because they only make sense when used together; they collaborate; they are aware of each other and need to communicate with each other.

This post will discuss best practices for managing communication among collaborating directives and illustrate these practices with an example.

Versatile Cucumber step regarding hovering above elements

Here's a pretty useful steps that hasn't made it into Spreewald yet.

It is best used with the auto-mapper for BEM classes in features/support/selectors.rb

When I hover above [selector] element

When /^I hover above (.*) element$/ do |selector|
  page.find(selector_for(selector)).hover
end

Example:

When I hover above the album's image element

→ triggers a hover event on .album--image

Slack integration for deployments via Capistrano

You can hook into Slack when using Capistrano for deployment. The slackistrano gem does most of the heavy lifting for you. Its default messages are unobtrusive and can be adjusted easily.

When deploying, it posts to a Slack channel like this:

Example

How to integrate

Integrating Slackistrano with Capistrano 3 is fairly simple.

  1. In your Slack, open menu → A...

Use CSS sibling selectors instead :last-child (or :first-child)

Often times you want to give a bunch of elements the same style, except for the last. For example borders or margins.

You probably commonly used the :last-child CSS meta selector like so:

.foo {
  border-bottom: 1px dashed #000;
}
.foo:last-child {
  border-bottom-width: 0;
}

However, this only works when an element is the last child of its parent. Any other siblings which are unrelated to your case will break it.

Instead, prefer using the + sibling selector. It applies to the element following the other.

.foo + .foo {
 ...

Ruby: Removing leading whitespace from HEREDOCs

If you're on Ruby 2.3+ there's a <<~ operator to automatically unindent HEREDOCs:

str = <<~MESSAGE
  Hello Universe!
  This is me.
             Bye!
MESSAGE

If you have an older Ruby, you can use the String#strip_heredoc method from ActiveSupport. See Summarizing heredoc in ruby and rails for an example.

Technically...

Detecting when fonts are loaded via JavaScript

Webfonts are not always available when your JavaScript runs on first page load. Since fonts may affect element sizes, you may want to know when fonts have been loaded to trigger some kind of recalculation.

Vanilla JavaScript / Modern DOM API

In modern browsers (all but IE and legacy Edge) you can use document.fonts. Use load to request a font and receive a Promise that will be resolved once the font is available. Example:

document.fonts.load('1rem "Open S...

Sharing cookies across subdomains with Rails 3

To achieve this goal you have to setup the session store like the following example:

  MyApp::Application.config.session_store(
    :cookie_store,
    {
      :key => '_myapp_session',
      :domain => :all, # :all defaults to da tld length of 1, '.web' has length of 1
      :tld_length => 2 # Top Level Domain (tld) length -> '*.myapp.web' has a length of 2
    }
  )

The invconvenient side effect for local development

… or: Why do I get "Can't verify CSRF token authenticity" even if csrf token is present?

As `:domain => :all...

How to create giant memory leaks in AngularJS (and other client-side JavaScript)

This guide shows how to create an AngularJS application that consumes more and more memory until, eventually, the browser process crashes on your users.

Although this guide has been written for Angular 1 originally, most of the advice is relevant for all client-side JavaScript code.

How to observe memory consumption

To inspect the amount of memory consumed by your Javascripts in Chrome:

  • Open an incognito window
  • Open the page you want to inspect
  • Press Shift + ESC to see a list of Chrome processes...

An auto-mapper for BEM classes in Cucumber selectors

When you are using the #selector_for helper in Cucumber steps, as e.g. Spreewald does, the following snippet will save you typing. It recognizes a prose BEM-style selector and maps it to the corresponding BEM class.

For a variation on this idea, see An auto-mapper for ARIA labels and BEM classes in Cucumber selectors.

Examples

"the main menu" -> '.main-menu'
"the item box's header" -> '.item-box--header'

Here are some examples of steps (using Spreewald, too):

T...

grosser/rspec-instafail

Gem to show failing specs instantly.
Unlike the --fail-fast option it doesn't abort abort on the first failure, but keeps running other examples after print out the failure.

I haven't tried it with parallel_tests.

Block formatting contexts

TL;DR Block formatting contexts establish an isolating container. float
and clear only apply to elements within such a container.

About

Block formatting contexts (BFCs) are important for the positioning and clearing
of floats. The rules for positioning and clearing of floats apply only to
things within the same block formatting context.

Floats do not affect the layout of things in other block formatting contexts,
and clear only clears past floats in the same block formatting context.

How to create a new block form...

Understanding z-index: it's about stacking contexts

The CSS property z-index is not as global as you might think. Actually, it is scoped to a so-called "stacking context". z-indexes only have meaning within their stacking context, while stacking contexts are treated as a single unit in their parent stacking context. This means indices like 99999 should never actually be needed.

Creating a new stacking context

In order to create a stacking context with the least possible side effects, use the isolation property on an...

Git: How to get a useful diff when renaming files

tldr; Use git diff -M or git diff --find-renames when you've moved a few files around.

Usage

$ git diff --help
  Options:
    -M[<n>], --find-renames[=<n>]
      Detect renames. If n is specified, it is a threshold on the similarity index
       (i.e. amount of addition/deletions compared to the file’s size). For example,
       -M90% means Git should consider a delete/add pair to be a rename if more than
       90% of the file hasn’t changed. Without a % sign, the number is to be read as
       a fraction, with a decimal point...

How to load an SQL dump from a migration

If you want to load an SQL dump from an ActiveRecord migration, you might find this to be harder than you thought. While you can call ActiveRecord::Base.connection.execute(sql) to execute arbitrary SQL commands, the MySQL connection is configured to only accept a single statement per query. If you try to feed it multiple statements, it will die with You have an error in your SQL syntax.

You can work around this by opening a second MySQL connection that does accept multiple statements per call.

Below is an example for a migration that l...

RSpec: Only stub a method when a particular argument is passed

To only stub a method call if a given argument is used, but use the default implementation for other arguments:

object.should_receive(:some_method).and_call_original
object.should_receive(:some_method).with('my argument').and_return('other value')

Requires rspec-mocks 2.13+.