Variable fonts for web developers

This card is mainly an explanation how variable fonts work in CSS, not necessarily a recommendation to actually use them.

What is a variable font?

Designing and rendering fonts are two highly complex topics. For an arbitrary text to appear properly on your screen, its font must be created multiple times for different "settings" like stroke width (boldness) and style (e.g. italic).

Now as web developers, we usually ship these variants of the same font via multiple @font-faces of the same font-family:

@font-face
  font-family...

How to configure file watchers in RubyMine

Installation

You need to install the official plugin, it is not bundled with RubyMine by default.

Example: Setup a watcher to verify rubocop integrity

First, open Settings -> Tools -> File Watchers. Then, configure rubocop to check every change to the VCS:

Image

Note that the "program" argument must be part of your $PATH. I worked around this constraint by using b as a shim for bundle exec.

Resources

  • [File watchers documen...

Convert curl commands to ruby code

curl-to-ruby is a handy tool that converts your curl command to ruby code that uses the Net::HTTP library.

Example

curl -X POST -d
  "grant_type=password&email=email&password=password"
  localhost:3000/oauth/token

will output to:

require 'net/http'
require 'uri'

uri = URI.parse("http://localhost:3000/oauth/token")
request = Net::HTTP::Post.new(uri)
request.set_form_data(
  "email" => "email",
  "grant_type" => "password",
  "password" => "password",
)

req_options =...

VCR and the webdrivers gem

If you're using the webdrivers gem and VCR together, depending on your configuration, VCR will yell at you regulary.
The webdrivers gem tries to update your webdrivers on your local machine. To do so, it checks the internet for newer versions, firing an HTTP-request to e.g. https://chromedriver.storage.googleapis.com

You can "fix" this in multiple ways:

  1. Update your drivers on your machine with
    RAILS_ENV=test rake webdrivers:chromedriver:update

  2. Ignore the driver update-URL in your ...

How to include Sidekiq job IDs in Rails logs

When logging in Rails, you can use the log_tags configuration option to add extra information to each line, like :request_id or :subdomain. However, those are only valid inside a request context and have no effect when your application is logging from inside a Sidekiq process.
This includes custom as well as any framework logs, like query logging from ActiveRecord.

Since Sidekiq Workers run inside threads of a single process, running multiple jobs in...

Ruby: How to determine the absolute path relative to a file

If you want to get the path of a file relative to another, you can use the expand_path method with either the constant __FILE__ or the method __dir__. Read this card for more information about __FILE__ and __dir__.

Example

Structure:

.
├── bin
│   ├── format_changelog
├── CHANGELOG.md

bin/format_changelog:

#!/usr/bin/env ruby

changelog_path = ? # How to get the path to ../CHANGELOG.md independent of the working dir of the caller
changelog = File.read(changelog_path)

# ... further actions h...

CSS variables aka CSS Custom Properties

CSS variables are very different from preprocessor variables. While preprocessors use variables to compile a static piece of CSS, CSS custom properties are a reactive (i.e. live) part of the styles. Think of them like usual CSS properties that cascade, but have:

  • a special syntax: CSS variables always start with a double-dash (--color)
  • no inherent meaning: Defining a CSS variable will not change any styles in itself
  • a special functionality: CSS variables can be used within the values of other properties, including CSS variables...

How does Sentry group exceptions?

When you use Sentry to monitor exceptions, an important feature is Sentry's error grouping mechanism. This will aggregate similar error "events" into one issue, so you can track and monitor it more easily. Grouping is especially important when you try to silence certain errors.

It is worth understanding how Sentry's grouping mechanism works.

The default grouping mechanism

The exact algorithm has changed over time, and Sentry will keep using the algorithm t...

Rails: How to get the ordered list of used middlewares

Rails middlewares are small code pieces that wrap requests to the application. The first middleware gets passed the request, invokes the next, and so on. Finally, the application is invoked, builds a response and passes it back to the last middleware. Each middleware now returns the response until the request is answered. Think of it like Russian Dolls, where each middleware is a doll and the application is the innermost item.

You can run rake middleware to get the ordered list of used middlewares in a Rails application:

$> rake midd...

How to check if a file is a human readable text file

Ruby's File class has a handy method binary? which checks whether a file is a binary file. This method might be telling the truth most of the time. But sometimes it doesn't, and that's what causes pain. The method is defined as follows:

# Returns whether or not +file+ is a binary file.  Note that this is
# not guaranteed to be 100% accurate.  It performs a "best guess" based
# on a simple test of the first +File.blksize+ characters.
#
# Example:
#
#   File.binary?('somefile.exe') # => true
#   File.binary?('somefile.txt') # => fal...

How to migrate CoffeeScript files from Sprockets to Webpack(er)

If you migrate a Rails application from Sprockets to Webpack(er), you can either transpile your CoffeeScript files to JavaScript or integrate a CoffeeScript compiler to your new process. This checklist can be used to achieve the latter.

  1. If you need to continue exposing your CoffeeScript classes to the global namespace, define them on window directly:
-class @User
+class window.User
  1. Replace Sprocket's require statement with Webpacker's...

Vortrag: Content Security Policy: Eine Einführung

Grundidee

CSP hat zum Ziel einen Browser-seitigen Mechanismus zu schaffen um einige Angriffe auf Webseiten zu verhindern, hauptsächlich XSS-Angriffe.

Einschub: Was ist XSS?

XSS = Cross Site Scripting. Passiert wenn ein User ungefiltertes HTML in die Webseite einfügen kann.

<div class="comment">
  Danke für den interessanten Beitrag! <script>alert('you have been hacked')</script>
</div>

Rails löst das Problem weitgehend, aber

  • Programmierfehler weiter möglich
  • manchmal Sicherheitslücken in Gems oder Rails

Lösungsid...

Automatically validating dependency licenses with LicenseFinder

"Open-source software (OSS) is great. Anyone can use virtually any open-source code in their projects."

Well, it depends. Licenses can make things difficult, especially when you are developing closed-source software. Since some OSS licenses even require the employing application to be open-sourced as well (looking at you, GPL), you cannot use such software in a closed-source project.

To be sure on this, we have developed a project-level integration of Pivotal's excellent [license_finder](https:/...

The HTML5 video element

# Basic HTML example
<video poster="preview_image.png" controls>
  <source src="or_here.webm" type="video/webm" />
  <source src="alternative_if_browser_cant_pay_first_source.mp4" type="video/mp4" />
  <track src="optional_subtitles.vtt" kind="subtitles" srclang="de" label="Deutsch" default>
</video>

# Javascript API (notable methods and properties)
video = document.querySelector('video')
video.play()
video.pause()
video.load() // Reset to the beginning and select the best available source
video.currentSrc // The selected source
video.c...

HTTP Client in RubyMine

RubyMine has a HTTP Client that can be useful to test web APIs.
Just create a .http scratch file an write your request in it.
The request can then be executed with the "Run all requests in File" button above the file.

Some alternatives:

The format for request is like this:

Method Request-URI HTTP-Version
Header-field: Heade...

How to use Active Job to decouple your background processing from a gem

In a web application you sometimes have tasks that can not be processed during a request but need to go to the background.
There are several gems that help to you do that, like Sidekiq or Resque.

With newer Rails you can also use ActiveJob as interface for a background processing library. See here for a list of supported queueing adapters.
For ...

Legacy CarrierWave: How to generate versions with different file extensions

We use CarrierWave in many of our projects to store and serve files of various formats - mostly images. A common use case of CarrierWave's DSL is to "process" the original file in order to create multiple "versions", for example different resolutions of the same image.

Now we could go one step further: What if we want to create versions that have a different file extension than the original file? For example, let's assume we'd like to create a ve...

Rails: Concurrent requests in development and tests

With puma you can have concurrent requests. There are two concepts on how Puma can handle two incoming requests: Workers and Threads.

Workers

Puma can have multiple workers. Each worker is a process fork from puma and therefore a very heavy instance and can have multiple threads, that handle the incoming requests.

Example: A Puma server with 2 workers and 1 thread each can handle 2 request in parallel. A third request has to wait until the thread of one of the workers is free.

Threads

Rails is thread-safe since version 4 (n...

Test-Driven Development with integration and unit tests: a pragmatic approach

Test-Driven Development (TDD) in its most dogmatic form (red-green-refactor in micro-iterations) can be tedious. It does not have to be this way! This guide shows a pragmatic approach with integration and unit tests, that works in practice and improves on productivity.

Hierarchical approach

TDD with integration and unit tests is a process with three abstraction levels:

  • Integration level
  • Code
  • Unit level

During development you are frequently changing levels. It may look something like this:

Integration _                    _...

Bundler in deploy mode shares gems between patch-level Ruby versions

A recent patch level Ruby update caused troubles to some of us as applications started to complain about incompatible gem versions. I'll try to explain how the faulty state most likely is achieved and how to fix it.

Theory

When you deploy a new Ruby version with capistrano-opscomplete, it will take care of a few things:

  • The new Ruby version is installed
  • The Bundler version stated in the Gemfil...