Rails Authentication Checklist

Authentication is a special part of web applications. On the one hand, it usually is a crucial security mechanism restrict access to certain people and roles. On the other hand, most users authenticate only once, so it is very unlikely to spot issues by accident.

So, here comes a quick checklist to help you verifying your authentication solution is all set.

  • This should be default: use HTTPS with HSTS. The HSTS part is important.
  • Use a reliable authentication solution, e.g. Clearance or [Devise…

Devise: How to allow only HTTP Basic Auth and disable the HTML sign-in form

By default, Devise redirects to a sign-in form when accessing a route that requires authentication. If for some reason you do not want this, but use Basic Authentication (and the corresponding browser username/password dialog) instead, this is a simple change.

Note that Devise's default configuration actually only redirects requests for HTML content (as requested by the HTTP Accept header).
For all other formats (like JSON) it would use Basic Auth if the http_authenticatable setting was enabled. So you can simply enable that flag and cl…

Letting a DOM element fade into transparency

You can use the CSS property mask-image to define an "alpha channel" for an element.

E.g. to let an element start at full opacity at the top and gradually fade into transparency at the bottom:

.box {
  -webkit-mask-image: linear-gradient(to bottom, black 0%, transparent 100%)
  mask-image: linear-gradient(to bottom, black 0%, transparent 100%)
  • A fully opaque black pixel will render the masked pixel fully opaque
  • A fully transparent black pixel will render the ma…
Linked contentRepeats

Rails: Overriding view templates under certain conditions only

Rails offers a way to prepend (or append) view paths for the current request. This way, you can make the application use different view templates for just that request.


A use case of this is a different set of view templates that should be used under certain circumstances:

class UsersController < ApplicationController

before_action :prepare_views

def index



def prepare_views
if prepend_view_path Rails.root.join('app', 'views', 'special') end end

end …

Linked contentAuto-destruct in 30 days

Updated: SameSite cookies

  • Added section on how to actually configure cookies with SameSite attribute
  • Restructured a little
  • Added resources

Escape a string for transportation in a URL

To safely transport an arbitrary string within a URL, you need to percent-encode characters that have a particular meaning in URLs, like & or =.

If you are using Rails URL helpers like movies_path(:query => ARBITRARY_STRING_HERE), Rails will take care of the encoding for you. If you are building URLs manually, you need to follow this guide.


In Ruby, use CGI.escape:

=> "foo%3Dfoo%26bar%3Dbar"

Do not ever use URI.encode or …

Rails: Rest API post-mortem analysis

This is a personal post-mortem analysis of a project that was mainly build to provide a REST API to mobile clients.

For the API backend we used the following components:

  • Active Model Serializer (AMS) to serializer our Active Record models to JSON.
  • JSON Schema to test the responses of our server.
  • SwaggerUI to document the API.

It worked

The concept worked really good. Here are two points that were extraordinary compared to normal Rails project with many UI components:

  • Having a Rails application, that has no UI components (only…

How to: Validate dynamic attributes / JSON in ActiveRecord

PostgreSQL and ActiveRecord have a good support for storing dynamic attributes (hashes) in columns of type JSONB. But sometimes you are missing some kind of validation or lookup possibility (with plain attributes you can use Active Record's built-in validations and have your schema.rb).

One approach about being more strict with dynamic attributes is to use JSON Schema validations. Here is an example, where a project has the dynamic attributes analytic_stats, that we can use to store analytics from an external measurement tool.

  • A g…
Linked contentRepeats

Taking screenshots in Capybara

Capybara-screenshot can automatically save screenshots and the HTML for failed Capybara tests in Cucumber, RSpec or Minitest.

Requires Capybara-Webkit, Selenium or poltergeist for making screenshots. They're saved into $APPLICATION_ROOT/tmp/capybara

The attached files contain config for cucumber integration and a Then show me a screenshot step.

Including assets for prettier presentation

Make sure to add this to config/environments/test.rb

# Do not generate digests fo…

Checklist: Using Carrierwave in a Rails project

This checklist should help you to check edge cases that are not part of the default Carrierwave configuration.

Linked contentRepeats

Showing a custom maintenance page while deploying

Add a custom maintenance page for each vhost (require capistrano 3.x):


Add this line to your application's Gemfile:

gem 'capistrano', '~> 3.0'
gem 'capistrano-maintenance', '~> 1.0'

Add this line to you application's Capfile:

require 'capistrano/maintenance'

Enable task

Present a maintenance page to visitors. Disables your application's web interface by writing a #{maintenance_basename}.html file to each web server. The servers must be configured to detect the presence of this file, and if it i…

Linked content

A Migration Path to Bundler 2+

Bundler 2 introduced various incompatibilites und confusing behavior. To add to the confusion, Bundler's behavior changed after the release of their version 2.

The linked article explains what happened.


Common mistakes when storing file uploads with Rails

1. Saving files to a directory that is not shared between deploys or servers

If you save your uploads to a made up directory like "RAILS_ROOT/uploads", this directory goes away after every deploy (since every release gets a new). Also this directory is not shared between multiple application servers, so your uploads are randomly saved to one local filesystem or another. Fixing this afterwards is a lot of fun.

Only two folders are, by default, shared between our application servers and deployments: "RAILS_ROOT/storage" and `"RAILS…


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

puts User.order(:last_name, :created_at).to_sql
# => 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]

3. Test the…


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…

Understanding grid sizes of (SVG) icons

A primer on vector graphics

For rastered image formats like JPG or PNG, each pixel is basically drawn on a fixed size canvas. To display such an image in a different size (say: 1.5 times larger than original), the renderer (your Browser / GPU / Monitor) needs to interpolate the color values of missing pixels. The image will appear slightly blurred.

This is different for vector graphics like the SVG (Scalable Vector Graphics) format. You can imagine SVG files as XML file contai…

Automated wordbreaks for long words

The problem:

So I had the issue that User input (coming from many different sources and users) often contains the same long word. Maybe that's a super german thing to have lots of long words I have to deal with. This long word needs to be fully visible on small screens but none of the automated word-break solutions offered by css ( is clever or supported enough to be a good solution. So I…

This website uses cookies to improve usability and analyze traffic.
Accept or learn more