View
Linked contentAuto-destruct in 54 days

Updated: Ruby constant lookup: The good, the bad and the ugly

I updated the ugly part to include the reason for a wrong constant lookup in production.

Linked contentRepeats

Writing a README for a project

Rails applications and ruby gems should have a README that gives the reader a quick overview of the project. Its size will vary as projects differ in complexity, but there should always be some introductory prose for a developer to read when starting on it.

Purpose

That's already the main purpose of a project README: Give a new developer a quick overview of the project. In sketching this outline, the README should notify the reader of any peculiarity he needs to know of.

Remember that in a few months, you'll be a kind of "new …

Repeats

Redirecting responses for PATCH or DELETE will not redirect with GET

Redirect responses to PATCH and DELETE requests will be followed with PATCH or DELETE. Redirect responses to GET and POST will be followed with a GET.
The Rails form_for helper will use a workaround to send POST requests with a _method param to avoid this issue for PATCH/DELETE.

If you make requests yourself, watch out for the following behavior.

When you make an AJAX request PATCH /foo and the /foo action redirects to /bar, browsers will request PATCH /bar. You probably expected the second request to be…

How to avoid ActiveRecord::EnvironmentMismatchError on "rails db:drop"

After loading a staging dump into development, you might get an ActiveRecord::EnvironmentMismatchError when trying to replace the database (like rails db:drop, rails db:schema:load).

$ rails db:drop
rails aborted!
ActiveRecord::EnvironmentMismatchError: You are attempting to modify a database that was last run in `staging` environment.
You are running in `development` environment. If you are sure you want to continue, first set the environment using:

        bin/rails db:environment:set RAILS_ENV=development

Starting with R…

Sass partial names must always start with an underscore

Be careful to name any file @imported by SASS with a leading underscore.

SASS files not beginning with an underscore will be rendered on their own, which will fail if they are using variables or mixins defined elsewhere. (For me it broke only in production, which may be due to some settings in SASS-GEM/lib/sass/plugin/rails.rb.)

From the SASS docs:

The underscore lets Sass know that the file is only a partial file and that it should not be generated into a CSS file.

Linked contentAuto-destruct in 18 days

Updated: How to enable SSL in development with Passenger standalone

Rewrote card with instruction to create a Passenger config file. This way, Passenger will always start with SSL enabled.

Linked content

How to use the Capistrano 2 shell to execute commands on servers

Capistrano 2 brings the shell command which allows you to run commands on your deployment targets.
There is also invoke to run a command directly from your terminal.

Both commands allow running Capistrano tasks or shell commands, and scope to individual machines or machine roles.

Unfortunately Capistrano 3 does not include these commands any more.

cap shell

Basics

First of all, spawn a Capistrano shell (we're using the multistage extension here):

$ cap staging shell

In your "cap" shell you can now run Capistrano ta…

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…
Linked contentRepeats

Showing a custom maintenance page while deploying

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

Installation

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…

Understanding SQL compatibility modes in MySQL and MariaDB

MySQL and MariaDB have an SQL mode setting which changes how MySQL behaves.

The SQL mode value is comprised of multiple flags like "STRICT_TRANS_TABLES, NO_ZERO_IN_DATE". Each flag activates or disables a particular behavior.

The default SQL mode varies widly between versions of MySQL and MariaDB. In general, more recent versions of MySQL and MariaDB have stricter settings than older versions, and MySQL has stricter settings than the more liberal MariaDB.

If your app explodes …

jQuery promises: done() and then() are not the same

jQuery's deferred objects behave somewhat like standard promises, but not really.

One of many subtle differences is that there are two ways to chain callbacks to an async functions.

The first one is done, which only exists in jQuery:

$.ajax('/foo').done(function(html) {
  console.debug("The server responded with %s", html);
});

There is also then, which all promise libraries have:

```
$.ajax('/foo').then(function(html) {
console.debug("The server resp…

Repeats

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…

How to run a small web server (one-liner)

Sometimes you just want to have a small web server that serves files to test something.

Serve the current directory

On Ruby 1.9.2+ you can do the following ("." for current directory).

ruby -run -ehttpd . -p8000

Python 2.x offers a similar way.

python -m SimpleHTTPServer 8000 .

This is the same way with Python 3.x

python -m http.server

In both cases your web server is single-threaded and will block when large files are being downloaded from you.

WEBrick also offers [a simple way](https://stackoverflow.com/quest…

Repeats

Fixing flaky integration tests

This card shows basic techniques for fixing a flaky integration test suite that sometimes passes and sometimes fails. "Integration test" is a test script that remote-controls a web browser with tools like Selenium WebDriver.

Although the examples in this card use Cucumber and Selenium, the techniques are applicable to all languages and testing tools.

Why tests are flaky

Your tests probably look like this:

When I click on A
When I click on B
When I click on C
Then I should see effects of C

A test like this works fine most of t…

Repeats

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…

Repeats

XHR is not JSON

When a Rails controller action should handle both HTML and JSON responses, do not use request.xhr? to decide that. Use respond_to.

I've too often seen code like this:

def show
  # ...
  if request.xhr?
    render json: @user.as_json
  else
     # renders default HTML view
  end
end

This is just plain wrong. Web browsers often fetch JSON via XHR, but they (should) also send the correct Accept HTTP header to tell the server the data they expect to receive.

If you say request.xhr? as a means for "…

Linked content

Linux Performance Analysis in 60,000 Milliseconds

You login to a Linux server with a performance issue: what do you check in the first minute?

uptime
dmesg | tail
vmstat 1
mpstat -P ALL 1
pidstat 1
iostat -xz 1
free -m
sar -n DEV 1
sar -n TCP,ETCP 1
top
Linked content

Defining "partials" in pure HTML without additional rendering helpers

A while ago I tweeted a thread about how a small JavaScript snippet, one that can fit in a single tweet in fact, can be used to allow defining custom elements purely in HTML. This post will expand on the idea, show how the snippet works, and argue for why you might want to actually use this.

A nice trick that lets you define "partials" in HTML without any additional rendering technology on the server or client.

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