3707 cards
Linked contentRepeats

Beware: Many browsers define window.event

Some browsers define window.event, which will return a copy of the "current" event. However, this is not defined by the W3C. Most importantly, Firefox does not support it, neither do recent versions of IE.

You should completely avoid accessing the global event and instead pass the event object around that the event handler receives. The easiest protection against accidentally accessing window.event is just never naming the event event, but e or evnt or so.

function brokenInFirefox() {
event.preventDefault(); // Break…


Operators "in" and "of" are very inconsistent between CoffeeScript and JavaScript

CoffeeScript and JavaScript (ECMAScript) both have operators in and of. Each language use them for more than one purpose. There is not a single case where the same operator can be used for the same purpose in both languages.

Check if an object (or its prototype) has a property


var hasFoo = 'foo' of object


var hasFoo = 'foo' in object;

Iterate through all properties of an object


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…
Linked contentAuto-destruct in 58 days

Unpoly 0.61.1 released

This is a maintenance release while we're getting ready for the next major version of Unpoly:

  • Fix a bug where up.destroy() wouldn't clean up the global jQuery cache. This is only relevant when using Unpoly together with jQuery.
  • Fields outside a <form> are now recognized when they have a matching [form] attribute (fixes #85)
  • up.form.fields() now accepts a jQuery collection as a first argument, as was already documented.
Linked contentAuto-destruct in 58 days

Updated: Obtain pessimistic row locks on ActiveRecord objects

Added link to optimistic row locking in ActiveRecord. This does not require you to start a transaction, but raises an exception when trying to save a record that has been changed in the database since it was looked up.

Linked contentAuto-destruct in 55 days

Updated: Reading and writing cookies in JavaScript

  • Clarified how reading cookies works
  • Added section about using libraries, including link to Cookies.js

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…

Writing Code Comments

Code comments allow for adding human readable text right next to the code: notes for other developers, and for your future self.

As always, with great power comes great responsibility. Code comments can go wrong in many ways: they may become outdated, silently move away from the code they're referring to, restate the obvious, or just clutter files.

Good Comments

Here are some simple rules to keep your comments helpful:

Avoid stating what some code does – prefer the Why
Some say, perfect code would not need a single comment. That'…
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.


Popular mistakes when using nested forms

Here are some popular mistakes when using nested forms:

  • You are using fields_for instead of form.fields_for.
  • You forgot to use accepts_nested_attributes in the containing model. Rails won't complain, but nothing will work. In particular, nested_form.object will be nil.
  • The :reject_if option lambda in your accepts_nested_attributes call is defined incorrectly. Raise the attributes hash given to your :reject_if lambda to see if it looks like you expect.
  • If you are nesting forms into nested forms, each model involved ne…

Carrierwave: Deleting files outside of forms

TL;DR Use the #remove_<mounted_attribute>! method to delete attachments. Also, save the record after removing the file!

As you know, Carrierwave file attachments work by mounting an Uploader class to an attribute of the model. Though the database field holds the file name as string, calling the attribute will always return the uploader, no matter if a file is attached or not. (Side note: use #present? on the uploader to check if the file exists.)

class User < ApplicationRecord
  mount :avatar, AvatarUploader

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.


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 …

Linked content

Heads up: Ruby's Net::HTTP silently retries a failing request

Ruby's Net::HTTP library repeats a failing request once, as long as it deems it idempotent (GET, HEAD etc). Both requests will use the configured timeout. Hence, if both requests time out, Net::HTTP will only return after twice the configured timeout.

This can become an issue if you rely on the timeout to strike precisely.

Linked contentRepeats

HTML/CSS: "transparent" is not a color

Heads up: transparent is not a real color, but black with 0% opacity.

In Safari, this makes e.g. gradients between transparent and white have some gray tones in the middle.

/* Unexpected in Safari */
linear-gradient(to right, white 0%, transparent 100%)

/* Correct */
linear-gradient(to right, white 0%, rgba(255,255,255,0) 100%)

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…


Whitelist Carrierwave attributes correctly

Say you have a User with a Carrierwave attribute #avatar:

class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader

When whitelisting the avatar field in the controller, you might do this:


But you probably want this:

  params[:user].permit(:avatar, :avatar_cache, :remove_avatar)

In this example:

  • :avatar_cache allows a newly upload image to persist through form roundtrips in the case of validation errors (something that isn't possible with Paper…

Obtain pessimistic row locks on ActiveRecord objects

When requests arrive at the application servers simultaneously, weird things can happen. Sometimes, this can also happen if a user double-clicks on a button, for example.

This often leads to problems, as two object instances are modified in parallel maybe by different code and one of the requests writes the results to the database.

In case you want to make sure that only one of the requests "wins", i.e. one of the requests is fully executed and completed while the other one at least has to wait for the first request to be completed, you ha…

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