Yarn: Use yarn-deduplicate to cleanup your yarn.lock

Note

Use yarn dedupe in Yarn v2+: https://yarnpkg.com/cli/dedupe

This package only works with Yarn v1. Yarn v2 supports package deduplication natively!

A duplicate package is when two dependencies are resolved to a different version, even when a single version matches the range specified in the dependencies. See the Deduplication strategies section for a few examples.

Yarn is stupid, so it can happen that there are several version of the same package in your bundle, although one would fulf...

CSS: :is() pseudo selector

tl;dr

The :is() pseudo selector - specificity of its most specific argument - matches against a comma-separated list of selectors.

Example

Compound selectors like ...

.datepicker .prev, .datepicker .next, .datepicker .switch
  padding-bottom: 1rem

ul li, ol li
  list-style-type: none

can be simplified by using the :is() pseudo selector ...

.datepicker :is(.prev, .next, .switch)
  padding-bottom: 1rem

:is(ul, ol) li
  list-style-type: none

Hint

The specificity of :is() is equals t...

CSS: :where() pseudo selector

tl;dr

The :where() pseudo selector - zero specificity - matches against a comma-separated list of selectors.

Example

Compound selectors like ...

.datepicker .prev, .datepicker .next, .datepicker .switch
  padding-bottom: 1rem

ul li, ol li
  list-style-type: none

can be simplified by using the :where() pseudo selector ...

.datepicker :where(.prev, .next, .switch)
  padding-bottom: 1rem

:where(ul, ol) li
  list-style-type: none

Hint

The specificity of :where() is always zero!

I...

Generating and streaming ZIP archives on the fly

When your Rails application offers downloading a bunch of files as ZIP archive, you basically have two options:

  1. Write a ZIP file to disk and send it as a download to the user.
  2. Generate a ZIP archive on the fly while streaming it in chunks to the user.

This card is about option 2, and it is actually fairly easy to set up.

We are using this to generate ZIP archives with lots of files (500k+) on the fly, and it works like a charm.

Why stream downloads?

Offering downloads of large archives can be cumbersome:

  • It takes time to b...

A short overview of common design patterns implemented within Rails

The linked content includes a few design patterns implemented with Ruby on Rails.

What is the card indented to achieve?

  • You can use the pattern names for code reviews, so all parties know with only a few words which change is requested. Example: "Please use a form object here"
  • You can learn about new code patterns
  • You should read the sections "Advantages of using design patterns" and "Disadvantages of using design patterns in a wrong way", since design patterns do not replace good code

Included Design Patterns: Service, Value objec...

makandra tech survey - results

These are the results of the "personal tech stack survey". I've included only the most popular mentions, maybe it can help you find one or two useful tools for your own usage.

Desktop environment

pie title Desktop environment
    "Gnome" : 16
    "i3": 2
    "sway": 2
    "awesome": 1
    "bspwm": 1
    "mate": 1
    "xfce": 1

Gnome dominates (unsuprising, it's the Ubuntu default), but quite a few people use tiling window managers, most popular i3 and the mostly i3-compatible [sway](https://swaywm....

CSS: The inset CSS shorthand

The inset CSS property is a shorthand that corresponds to the top, right, bottom, and/or left properties. It has the same multi-value syntax of the margin shorthand.

Example

<div class="outer">
  <div class="inner">
    Some text
  </div>
</div>
.outer {
  background-color: cyan;
  position: relative;
  width: 500px;
  height: 500px;
}

Top, right, bottom and left

https://jsfiddle.net/jqx68wem/

.inner {
  background-color: darkCyan;
  position: absolute;
  top: 10px;
  right: 10px;
  bottom: 10p...

PostgreSQL: How to show database size

SELECT pg_size_pretty(pg_database_size('some-database'));

Example

SELECT pg_size_pretty(pg_database_size('cards_p'));
----------------
 13 GB
(1 row)
SELECT pg_database_size('cards_p');
 pg_database_size 
------------------
      13524832927
(1 row)

Related

Double loading issue with Ruby default gems

Ruby includes many standard gems that are bundled into the Ruby installation. Here is an example for the gem strscan that will be displayed as default:

gem list strscan     

*** LOCAL GEMS ***

strscan (default: 3.0.1)

It is still possible to have newer version of a gem installed beside the default version:

gem install strscan  
Fetching strscan-3.0.3.gem
Building native extensions. This could take a while...
Successfully installed strscan-3.0.3
1 gem installed
gem list strscan   

*** LOC...

Do not forget mailer previews

When changing code in mailers, updating the corresponding mailer preview can be forgotten very easily.

Mailer previews can be tested like other code as well and I sometimes add the following tests to test suites:

# Make sure to require the previews
Dir[Rails.root.join('spec/mailers/previews/*.rb')].each { |file| require(file) }


ActionMailer::Preview.all.index_with(&:emails).each do |preview, mails|
mails.each do |mail|
    describe preview do
      specify "##{mail} works" do
        expect { preview.call(mail...

Show a JS fiddle in fullscreen

If you have a JS fiddle, you can open it in fullscreen by appending /show to the URL.

Example: https://jsfiddle.net/b275g910/3 => https://jsfiddle.net/b275g910/3/show

How to debug file system access in a Rails application

It might sometimes be useful to check whether your Rails application accesses the file system unnecessarily, for example if your file system access is slow because it goes over the network.

The culprit might be a library like carrierwave that checks file existence or modification times, whereas your application could determine all this from your database.

Introducing strace

One option it to use strace for this, which logs all system calls performed by a process.

To do this, start your rails server using something like

DISA...

Capybara: Most okayest helper to download and inspect files

Testing file download links in an end-to-end test can be painful, especially with Selenium.

The attached download_helpers.rb provides a download_link method for your Capybara tests. It returns a hash describing the download's response:

details = download_link('Download report')
details[:disposition]  # => 'attachment' or 'inline'
details[:filename]     # => 'report.txt'
details[:text]         # => file content as string
details[:content_type] # => 'text/plain'

Features

Compared to [other approaches](...

RSpec: How to turn off partial double verification temporarily

While verifying doubles in RSpec is a good default, it is limited in the amount of methods it actually is able to verify.

The background is that RSpec can't verify dynamically defined methods, which is a known issue for the usage of helper_method and also the reason why [RSpec >= 3.6](http://rspec.info/blog/2017/05/rspec-3-6-has-been-rel...

Project maintenance: four levels of code quality

Code quality can be measured in four levels:

  1. (Working code)
  2. Reliable code (minimum)
  3. Readable code (ok for short-lived code)
  4. Changeable code (standard level)

The code quality of a project directly impacts its maintainability.

Generally you should aim for level 3. If the code will stay for less than a few months, it may stay at level 2. Never go below level 1.

0. Working code

You have implemented that feature and it works. Congrats! You have reached level zero, which means three levels of code quality lie ahead.

First, m...

Use DatabaseCleaner with multiple test databases

There is a way to use multiple databases in Rails.
You may have asked yourself how you're able to keep your test databases clean, if you're running multiple databases with full read and write access at the same time. This is especially useful when migrating old/existing databases into a new(er) one.

Your database.yml may look like this:

default: &default
  adapter: postgresql
  encoding: unicode
  username: <%= ENV['DATABASE_USER'] %>
  host: <%= ENV['DATABASE...

How to bind an event listener only once with Unpoly

You can use Unpoly's up.on with a named listener function and immediately unbind this event listener with { once: true }:

up.on('up:fragment:inserted', { once: true }, function () { ... })

In Unpoly 1 you can immediately unregister the listener with up.off:

up.on('up:fragment:inserted', function fragmentInsertedCallback() {
  up.off('up:fragment:inserted', fragmentInsertedCallback)
  // ... code for the callback function, which should run only once
})

Exam...

Chrome DevTools: List Registered Event Listeners

In Chrome DevTools you can use getEventListeners(object) to get a list of registered event listeners on the specified object.

You can also do this without the console, by selecting an element in the DOM inspector. In the element details, select the tab Event Listeners".

Example

const registry = getEventListeners(document)

registry['up-click']
// 0: { useCapture: false, passive: false, once: false, type: 'up:click', listener: ƒ }
// 1: { useCapture: false, passive: false, once: false, type: 'up:click', listener: ƒ }
//...

How to get information about a gem (via CLI or at runtime from Ruby)

When you need information about a gem (like version(s) or install path(s)), you can use the gem binary from the command line, or the Gem API inside a ruby process at runtime.

gem binary (in a terminal)

You can get some information about a gem by running gem info <gem name> in your terminal.

Example:

$ gem info irb

*** LOCAL GEMS ***

irb (1.4.1, 1.3.5)
    Author: Keiju ISHITSUKA
    Homepage: https://github.com/ruby/irb
    Licenses: Ruby, BSD-2-Clause
    Installed at (1.4.1): /home/arne/.rbenv/versions/3.0.3/lib/ruby/g...

JavaScript: Working with Query Parameters

tl;dr: Use the URLSearchParams API to make your live easier if you want to get or manipulate query parameters (URL parameters).

URLSearchParams API

The URLSearchParams API is supported in all major browsers except IE 11.

It offers you a bunch of useful methods:

  • URLSearchParams.append() - appends a query parameter
  • URLSearchParams.delete() - deletes the specified query parameter
  • URLSearchParams.get() - returns the value of the specified query parameter
  • `URLSearchP...

Jasmine: Fixing common errors during initialization

Due to the way we setup Jasmine tests in our projects, you may run into various errors when Jasmine boots.

Setting jasmineRequire on undefined

Jasmine 4 may fail with an error like this:

Uncaught TypeError: Cannot set properties of undefined (setting 'jasmineRequire')

This is due to issues in Jasmine's [environment detection](https://github.com/jasmine/jasmine/blob/502cb24bb89212917a3c943b593fd918ffc481cb/lib/jasmine-core/...

Generating an Entity Relationship Diagram for your Rails application

This card explains how to generate an entity relationship diagram for your Rails application.
We also show how to limit your ERD to a subset of models, e.g. models inside a namespace.

Generating a full ERD

Option A: RubyMine

  1. Right-click anywhere in your project tree
  2. In the context menu, find the "Diagrams" menu item at/near the bottom
  3. Inside, choose "Show diagram" → "Rails Model Dependency Diagram"
  4. A new tab will open with the diagram inside. You can modify it there, and export it as an image.

Option B: Use rails-e...

Version 5 of the Ruby Redis gem removes Redis.current

Redis.current will be removed without replacement in redis-rb 5.0.
Version 4.6.0 adds deprecation warnings for Redis.current and Redis.current=:

`Redis.current=` is deprecated and will be removed in 5.0.

If your application still uses Redis.current, you can only fix it by no longer using it. Here is how.

Redis.new when you need it

You can easily instantiate a Redis client when you need it.

There is probably already a constant like REDIS_URL that you use to configure Sidekiq or similar. So just use that one.

``...

How to access Chrome Devtools when running JavaScript tests via CLI

While we are used to run our JavaScript tests on a test page within our Browser, it's also possible to run them on the command line with NodeJS. I think that's actually the most common way to run JS tests.

Given a Vue project that uses Jest (via vue-cli-service) with the following package.json:

{
  "scripts": {
    "test": "vue-cli-service test:unit --testMatch='**/tests/**/*.test.js' --watch"
  },
}

This allows us to run J...