Debugging flickering VCR tests

We often use VCR to stub external APIs. Unfortunately VCR can have problems matching requests to recorded cassettes, and these issues are often hard to debug.

VCR's error messages mostly look like this and are not very helpful:

An HTTP request has been made that VCR does not know how to handle:
         POST http://another-site.de:9605/json/index

VCR fails if the request does not exactly look like the request it has recorded. If the request is d...

VCR fails if the same request is triggered multiple times

Same requests are recorded only once in vcr. Replaying a test fails, if you trigger the same request multiple times. The error message is somehow confusing, as your cassette contains the request:

An HTTP request has been made that VCR does not know how to handle

If you want to allow to match a request multiple times, you need to configure this explicit with allow_playback_repeats: true. Some exa...

Javascript: Read params from url

There is no build in functionally in jQuery and Prototype to extract params from a url.

  1. You can use this library (not tested): jquery-deparam

  2. Use Unpoly and the following code snippet

ClockPicker: Android-style time picker for Bootstrap

ClockPicker is a JavaScript and Bootstrap implementation of an Android-style time picker which looks and feels great.

Unfortunately, it is no longer maintained.

ClockPicker.png

An intro to Javascript promises

Promises are the new way™ to express "Do this, and once you're done, do that". In contrast to callbacks, promises are easily chainable. From the readme of Q, an early implementer of the pattern:

The callback approach is called an “inversion of control”. A function that accepts a callback instead of a return value is saying, “Don’t call me, I’ll call you.”. Promises un-invert the inversion, cleanly separating the input arguments from control flow arguments. This simplifies the use and creation of APIs, p...

How to human-join an array in JavaScript

To simulate Rails' to_sentence in your JavaScript application, you can use these few lines of CoffeeScript code:

joinSentence = (array) ->
  if array.length > 1
    array[0..-2].join(', ') + ', and ' + array[-1..]
  else
    array.join ', '

Examples:

> joinSentence(['cats', 'dogs', 'pandas'])
# => 'cats, dogs, and pandas'

^
> joinSentence(['llamas'])
# => 'llamas'

Here is some plain JavaScript, should you prefer that:

function joinSentence(array) {
  if (array.length > 1) {
    return ar...

Middleman does not fingerprint asset paths by default

We're using Middleman for some static sites like our blog.

Despite being very similar to Rails, Middleman does not add a fingerprint hash to its asset paths by default. This means that when you write this:

<%= javascript_include_tag 'all.js' %>

... you always get the same path, regardless of the contents of all.js:

<script src='/javascripts/all.js'>

Because browsers tend to cache assets for a while, this means that users might not get your changes until their cac...

Represent astral Unicode characters in Javascript, HTML or Ruby

Here is a symbol of an eight note: ♪

Its two-byte hex representation is 0x266A.

This card describes how to create a string with this symbol in various languages.

All languages

Since our tool chain (editors, languages, databases, browsers) is UTF-8 aware (or at least doesn't mangle bytes), you can usually get away with just pasting the symbol verbatim:

note = '♪'

This is great for shapes that are easily recognized by your fellow programmers.
It's not...

Using Google Analytics with Unpoly

The default Google Analytics might not work as expected with your Unpoly app. This is because your app only has a single page load when the user begins her session. After that only fragments are updated and the <script> tag that sends the page view to Google Analytics is probably never evaluated again.

Luckily you can fix this.

Simple mode: You just want to track all the page views

Embed your Google Analytics code as always.

Now add the following code snippet:...

object-fit polyfill by lazysizes

All new browsers support the new object-fit CSS property. It allows to specify how an element behaves within its parent element and is intended for images and videos. The most useful values are contain (fit-in) and cover (crop).

Unfortunately, IE does not support this yet. However, if you're already using lazysizes, you can use its object-fit polyfill!

Usage

In your Javascript manifest, require them like this:

#= require plugins/object-fit/ls.obj...

Tasks, microtasks, queues and schedules - JakeArchibald.com

The way that Javascript schedules timeouts and promise callbacks is more complicated than you think. This can be the reason why callbacks are not executed in the order that they are queued.

Please read this article!


This is an extract of the example in the article which demonstrates the execution order of tasks and microtasks.

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
})...

Making jQuery throw an error when it returns an empty collection

When you are working with jQuery selectors and collections, many times you want to know if the collection actually contains the elements you wanted to select. Here's a tiny jQuery plugin that does just that.

$.fn.ensure = ->
  if (@length == 0) then throw 'Empty jQuery collection'
  this

Use it like this:

$('input[id$=_cache]').ensure()
> Console: "Uncaught Empty jQuery collection"

Dynamically uploading files to Rails with jQuery File Upload

Say we want …

  • to create a Gallery that has a name and has_many :images, which in turn have a caption
  • to offer the user a single form to create a gallery with any number of images
  • immediate uploads with a progress bar per image
  • a snappy UI

Enter jQuery File Upload. It's a mature library that can do the job frontend-wise. On the server, we'll use Carrierwave, because it's capable of caching images.

(FYI, [here's how to do the u...

Javascript: Wait until an image has finished loading

The attached ImageLoader helper will start fetching an image and return an image that is resolved once the image is loaded:

ImageLoader.load('/my/image.png').then(function(image) {
  ...
});

The image argument that is yielded to the promise callback is an HTMLImageElement. This is the kind of object you get when you call new Image().

jQuery: Find a selector in both descendants and the element itself

jQuery's find looks in the element's descendants. It will never return the current element itself, even if the element matches the given selector.

Require the attached file and you can now say:

$('.container').findWithSelf('.selector')

This is sort of like closest, but it looks in descendants instead of ancestors.

Preloading images with CSS

Sometimes you want to preload images that you will be using later. E.g. if hovering over a an area changes its background image, the new image should be preloaded. If you only load it once the user starts hovering, there will be a delay until the background image flips.

The attached article explains how to preload images with only CSS. No Javascript required.

The gist is:

.element:after {
  content: url(img01.jpg) url(img02.jpg) url(img03.jpg);
  display: none;
}

Delay your Jasmine tests until the document is ready

To delay your entire Jasmine test suite until the DOM is ready, add the following:

beforeAll(function(done) {
  $(done);
});

jQuery Core 3.0 Upgrade Guide | jQuery

Since jQuery 3 saw it's first release candidate today, the links has a list of (breaking) changes.

How to: Client-side language detection

When you have a localized website, you may want to redirect users to their preferred language when they visit the root path.
Here is how to do it without a server-side component (like a Rails application).

  • Use JavaScript's navigator.language (real browsers and IE11+) and navigator.userLanguage (old IEs).
  • Use a <meta> refresh as fallback
  • Provide buttons for paranoid users that disabled JavaScript and meta refreshs.

JavaScript

The following JavaScript will try to auto-detect a user's preferred language.

It understands string...

thoughtbot/fake_stripe: A Stripe fake so that you can avoid hitting Stripe servers in tests.

fake_stripe spins up a local server that acts like Stripe’s and also serves a fake version of Stripe.js, Stripe’s JavaScript library that allows you to collect your customers’ payment information without ever having it touch your servers. It spins up when you run your feature specs, so that you can test your purchase flow without hitting Stripe’s servers or making any external HTTP requests.

We've also had tests actually hitting the testing sandbox of Stripe, which worked OK most of the time (can be flakey).

How to preview an image before uploading it

When building a form with a file select field, you may want to offer your users a live preview before they upload the file to the server.

HTML5 via jQuery

Luckily, HTML5 has simple support for this. Just create an object URL and set it on an <img> tag's src attribute:

$('img').attr('src', URL.createObjectURL(this.files[0]))

Unpoly Compiler

As an Unpoly compiler, it looks like this:

up.compiler '[image_p...

Reading and writing cookies in JavaScript

You can use JavaScript to get or set cookie values on the client.

Using the vanilla JavaScript API

In JavaScript, document.cookie is an accessor to all cookies on the current site. It looks like a String, but its setter is actually more powerful.

When setting cookies this way, remember to set the path=/ option.

Reading cookies

A result may look like this:

hello=universe; foo=bar

This means that there are 2 cookies: "hello" with value "universe", and "foo" with value "bar...

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

How to quickly inspect an Angular scope in your webkit browser

Current webkit browsers like Chrome and Safari have a special variable in their consoles that refers to the selected DOM node in the elements panel. This lets us easily inspect Angular scopes.

  1. Right click in the page and click "Inspect" to open the Dev Tools

  2. Select the element you're interested in from the elements panel

  3. Focus the console (in Chrome, hit ESC)

  4. Get the scope object and store it

    s=$($0).scope()
    
    // That is:
    element = $0 // Store element
    $element = $(element) // Wrap with j...