ES6 imports are hoisted to the top

From Exploring ES6:

Module imports are hoisted (internally moved to the beginning of the current scope). Therefore, it doesn’t matter where you mention them in a module and the following code works without any problems:

foo();
import { foo } from 'my_module';

Footgun example

When you're not aware of import hoisting you may be surprised that your code runs in a different order than you see in the source file.

The example below is taken from the [...

Disable PostgreSQL's Write-Ahead Log to speed up tests

The linked article suggests an interesting way to speed up tests of Rails + Postgres apps:

PostgreSQL allows the creation of “unlogged” tables, which do not record data in the PostgreSQL Write-Ahead Log. This can make the tables faster, but significantly increases the risk of data loss if the database crashes. As a result, this should not be used in production environments. If you would like all created tables to be unlogged in the test environment you can add the following to your...

JavaScript without jQuery

This is a presentation from 2019-01-21.

Summary

  • We want to move away from jQuery in future projects
  • Motivations are performance, bundle size and general trends for the web platform.
  • The native DOM API is much nicer than it used to be, and we can polyfill the missing pieces
  • Unpoly 0.60.0 works with or without jQuery

Is jQuery slow?

From: Sven
To: unpoly@googlegroups.com
Subject: performance on smartphones and tablets

Hello

I just used your framework in one project and must say,
I am really pleased with it -- but o...

RSpec: Efficiently rerunning failed examples during development

Note

Don't use reruns as a mean to work around flaky tests. You should always try to fix those instead of rerunning them regularly.

Setup

Configure RSpec to persist the result of your test runs to a file. This is necessary to be able to rerun examples.
Add this to your spec/spec_helper.rb :

  config.example_status_persistence_file_path = 'spec/examples.txt'

Rerun all failed examples using --only-failures

bundle exec rspec --only-failures (or `...

Unpoly: Loading large libraries on-demand

When your JavaScript bundle is so massive that you cannot load it all up front, I would recommend to load large libraries from the compilers that need it.

Compilers are also a good place to track whether the library has been loaded before. Note that including same <script> tag more than once will cause the browser to fetch and execute the script more than once. This can lead to memory leaks or cause duplicate event handlers being registered.

In our work we mostly load all JavaScript up front, since our bundles are small enough. We recent...

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

Lightning Talk: Coverage based Test Case Prioritization in Ruby on Rails

For my computer science bachelor's thesis I programmed and evaluated a CLI Test Case Prioritization (TCP) tool for makandra. It has been written as a Ruby Gem and was tested and evaluated against one Ruby on Rails project. This card will summarize and present the research results, the evaluation and the programmed CLI tool.

The code has been published for educational purposes on GitHub. The german bachelor's thesis has also been included for download at the end.


...

SASS: Reusing styles from other files

SASS has an @extend keyword to inherit styles.

.alert
  color: red
  
  &.-framed
    border: 1px solid red
    padding: 5px
    
  &.-homepage
    @extend .-framed
    border-width: 5px

When compiling, SASS will simply join the selectors. Note how .-homepage is written where .-framed was defined:

...
.alert.-framed, .alert.-homepage {
  border: 1px solid red;
  padding: 5px;
}
.alert.-homepage {
  border-width: 5px;
}

Warning

Unfortunately, this does...

How to create Rails Generators (Rails 3 and above)

General

Programatically invoke Rails generators

Require the generator, instantiate it and invoke it (because generators are Thor::Groups, you need to invoke them with invoke_all). Example:

 require 'generators/wheelie/haml/haml_generator'
 Generators::HamlGenerator.new('argument').invoke_all

Other ways: Rails invokes its generators with Rails::Generators.invoke ARGV.shift, ARGV. From inside a Rails generator, you may call the [inherited Thor method invoke(args=[], options={}, config={})](https://github...

How to use Simplecov to find untested code in a Rails project with RSpec and Cucumber

Simplecov is a code coverage tool. This helps you to find out which parts of your application are not tested.

Integrating this in a rails project with rspec, cucumber and parallel_tests is easy.

  1. Add it to your Gemfile and bundle

    group :test do
      gem 'simplecov', require: false
    end
    
  2. Add a .simplecov file in your project root:

    SimpleCov.start 'rails' do
      # any custom configs like groups and filters can be here at a central place
      enable_cov...
    

Slack integration for deployments via Capistrano

You can hook into Slack when using Capistrano for deployment. The slackistrano gem does most of the heavy lifting for you. Its default messages are unobtrusive and can be adjusted easily.

When deploying, it posts to a Slack channel like this:

Example

How to integrate

Integrating Slackistrano with Capistrano 3 is fairly simple.

[NOTE "If you are not a Slack...

Middleman configuration for Rails Developers

Middleman is a static page generator that brings many of the goodies that Rails developers are used to.

Out of the box, Middleman brings Haml, Sass, helpers etc. However, it can be configured to do even better. This card is a list of improvement hints for a Rails developer.

Gemfile

Remove tzinfo-data and wdm unless you're on Windows. Add these gems:

gem 'middleman-livereload'
gem 'middleman-sprockets' # Asset pipeline!

gem 'bootstrap-sass' # If you want to use Bootstrap

gem 'byebug'

gem 'capistrano'
gem 'capistrano-mid...

Enabling YJIT

YJIT is Ruby's default just-in-time compiler. It is considered production-ready since Ruby 3.2 (source).

To activate YJIT you need two steps:

  • Your ruby binary needs to be compiled with YJIT support.
  • You need to enable YJIT.

Getting a Ruby with YJIT support

We usually install Ruby with tools like rbenv or asdf. This compiles the ruby binary from the source code. Support for YJIT will be automatically added during this compilation...

What we know about PDFKit

What PDFKit is

  • PDFKit converts a web page to a PDF document. It uses a Webkit engine under the hood.
  • For you as a web developer this means you can keep using the technology you are familar with and don't need to learn LaTeX. All you need is a pretty print-stylesheet.

How to use it from your Rails application

  • You can have PDFKit render a website by simply calling PDFKit.new('http://google.com').to_file('google.pdf'). You can then send the...

Local development with SSL and Puma

Sometimes the need arises for SSL in local development. We have guides for different webservers, this one is for puma.

  1. make sure mkcert is installed

  2. create an SSL certificate for localhost with mkcert:

$ mkcert-v1.4.4-linux-amd64 localhost
Created a new local CA 💥
...
  1. use the certificate in the Puma config config/puma.rb:
localhost_key = "#{File.join('localhos...

Running Rubocop as a pre-push hook

Git has the concept of hooks: bash scripts that are invoked at certain points in the Git lifecycle. One handy use is a pre-push hook that runs Rubocop. It will prevent pushing code that Rubocop finds fault with.

Configuring the hook

Git hooks are normally stored locally with a repository. They are not committed.

  1. Store this snippet in .git/hooks/pre-push:
if [ -f ./.rubocop.yml ]; then                                                  
  echo 'Running Rubocop ...'                                                    
  bundle exe...

How to fix: Gems are unavailable although they are installed

  • If Rails or Rake are complaining about a missing gem that is listed in your Gemfile.lock and the listed version is properly installed, something is seriously wrong and needs to be fixed.
  • If you accidently executed bundle install some_gem although you wanted bundle update some_gem

What is wrong

Let's say your Gemfile asks for some-gem which you can see when running gem list but bundle show some-gem just gives you an error:

Could not find gem 'some-gem', in any of the sources

Another indicator: Doing a `...

ActiveStorage: How to add a new preprocessed named version

Given there is a user with an attachable avatar:

class User < ApplicationRecord
  has_one_attached :avatar
end

If you want to add a preprocessed version follow these steps:

  1. Add the named version and deploy
class User < ApplicationRecord
  has_one_attached :avatar do |attachable|
    attachable.variant :preview, resize_to_fit: [177, 177 * 9 / 16], preprocessed: true
  end
end
  1. Preprocess this version for all existing records `bundle exec rails runner 'User.find_each { |user| user.avatar.variant(:preview).proc...

How to monitor Sidekiq: A working example

In order to have monitoring for Sidekiq (like queue sizes, last run of Sidekiq) your application should have a monitoring route which returns a json looking like this:

{
  "sidekiq": {
    "totals": {
      "failed": 343938,
      "processed": 117649167
    },
    "recent_history": {
      "failed": {
        "2016-11-06": 1,
        "2016-11-07": 46,
        "2016-11-08": 0,
        "2016-11-09": 0,
        "2016-11-10": 0
      },
      "processed": {
        "2016-11-06": 230653,
        "2016-11-07": 230701,
        "2016-11-08"...

How to fix "undefined method `name' for Array" error when running bundled commands on Ruby 1.8.7 + Rails 2.3

On recent/fresh installations of Ruby 1.8.7 you may encounter this error why calling any bundled binary (or just bundle exec):

/home/arne/.rvm/gems/ruby-1.8.7-p374@global/gems/rubygems-bundler-1.4.2/lib/rubygems-bundler/noexec.rb:75:in `setup': undefined method `name' for #<Array:0x7fe04783ef30> (NoMethodError)
  from /home/arne/.rvm/rubies/ruby-1.8.7-p374/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:29:in `map'
  ...

Apparently, this is due to bundler (or maybe the rubygems-bundler that RVM supplies by default) no lon...

RubyMine: How to add a german spell checker

Grazie Lite

Rubymine 2024.3 bundles Grazie Lite by default. You need to enabled "German" under Settings/Preferences | Editor | Natural Languages.

Hunspell (legacy)

  1. Install the Hunspell plugin and restart Ruby Mine
  2. Run sudo apt install hunspell-de-de
  3. Select /usr/share/hunspell/de_DE.dic in File > Settings > Editor > Spelling > Custom Directory +

![Screenshot_from_2018-10-17_16-47-03.png](https://makandracards.com/makandra/57341-rubymine...

Some tips for upgrading Bootstrap from 3 to 4

Recently I made an upgrade from Bootstrap 3 to Bootstrap 4 in a bigger project. Here are some tips how to plan and perform such an upgrade. The effort will scale with the size of the project and its structure. If your stylesheets already follow strict rules, it may take less time to adapt them to the new version.

Preparation

There are several gems and libraries that works well with bootstrap or provide at least stylesheets/plugins to easily integrate the bootstrap theme. But very often they only work with specific version or are no long...

Capistrano 3: Running a command on all servers

This Capistrano task runs a command on all servers.

bundle exec cap production app:run cmd='zgrep -P "..." RAILS_ROOT/log/production.log'

Code

# lib/capistrano/tasks/app.rake

namespace :app do

  # Use e.g. to grep logs on all servers:
  #   b cap production app:run_cmd cmd='zgrep -P "..." RAILS_ROOT/log/production.log' 
  #
  # * Use RAILS_ROOT as a placeholder for the remote Rails root directory.
  # * Append ` || test $? =1;` to grep calls in order to avoid exit code 1 (= "nothing found")
  # * To be able to process ...

Configuring Webpacker deployments with Capistrano

When deploying a Rails application that is using Webpacker and Capistrano, there are a few configuration tweaks that optimize the experience.

Using capistrano-rails

capistrano-rails is a Gem that adds Rails specifics to Capistrano, i.e. support for Bundler, assets, and migrations. While it is designed for Asset Pipeline (Sprockets) assets, it can easily be configured for Webpacker. This brings these features to the Webpacker world:

  • Automatic removal of expired assets
  • Manifest backups