cucumber_factory: How to keep using Cucumber 2 Transforms in Cucumber 3
Cucumber up to version 2 had a neat feature called Step Argument Transforms which was dropped in favor of Cucumber 3 ParameterTypes. While I strongly encourage you to drop your legacy Transforms when upgrading to Cucumber 3, it might not always be possible due to their different design.
This is a guide on how to keep the exact same functionality of your old Transforms
while writing them in the style of new `Paramet...
Bundler: How to install version 1 instead of 2 (latest version)
When installing a gem you can use version comparators like >=
or ~>
. That way it is possible to fetch the latest version of Bundler 1 with this command:
gem install bundler -v '~>1'
How to install bundler for Ruby < 2.3 is a common usecase where you might need Bundler 1.
Selenium may break with ChromeDriver 75+
When you update your ChromeDriver to version 75 or beyond, you might get w3c errors in your tests.
For example, reading the browser console for errors no longer works, and page.driver.browser.manage.logs.get(:browser)
will raise an error like "undefined method `log' for #<Selenium::WebDriver::Remote::W3C::Bridge:0x000055903f307aa8>
".
Add options.add_option('w3c', false)
to your Selenium configuration (e.g. features/support/selenium.rb
) and you should be back to normal:
Capybara.register_driver :selenium do |app|
options ...
How to recognize CVE-2019-5418
If you get requests with values for formats
like this:
{:locale=>[:de], :formats=>["../../../../../../../../../../etc/services{{"], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :haml]}
or fails like this:
Invalid query parameters: invalid %-encoding (../../../../../../../../../etc/passwd%%0000.html)
Someone tries to exploit CVE-2019-5418.
If you use the latest Rails (or latest Rails LTS) you're...
Execution of shell code in Ruby scripts
Deprecated ways to execute shell code in Ruby
This is just a reference for legacy code. For new code, always use capture3
.
%x{ } or backticks – quick and easy
Returns the standard output of running the given command in a subshell. This is an alias for `...`, and you can use string interpolation.
Example:
name = 'ls'
result = `which #{name}`
It does not escape anything you inject in the string, so be aware of possible security vulnerabilities...
How to install npm packages globally without sudo on Linux
All quoted.
-
Set up a package root in your homedir to hold the Node "global" packages:
$ NPM_PACKAGES="$HOME/.npm-packages" $ mkdir -p "$NPM_PACKAGES"
-
Set NPM to use this directory for its global package installs:
$ echo "prefix = $NPM_PACKAGES" >> ~/.npmrc
-
Configure your PATH and MANPATH to see commands in your $NPM_PACKAGES prefix by adding the following to your .bashrc:
# NPM packages in homedir NPM_PACKAGES="$HOME/.npm-packages" # Tell our environment about user-ins...
Rails Asset Pipeline: Building an Icon Font from SVG Files
Webpacker can automatically create an icon font from SVG files, which is really handy. When you're using the asset pipeline, you can still have an icon font from SVG files, but it requires some manual work.
Creating the icon font
- Install the NPM package
icon-font-generator
. If you're not usingnvm
, runsudo npm install -g icon-font-generator
- Put all SVG icons for the font into their own directory.
- The icon name will be taken from the SVG file name
- Download the attached script and update the
Configure
...
Migrating from CoffeeScript to ES6
It is quite easy to migrate from CoffeeScript to ES6. You can use decaffeinate to convert your CoffeeScript source to modern JavaScript.
Install decaffeinate globally:
npm install -g decaffeinate
Call decaffeinate
on each .coffee
file, relaxing some options to get the most modern (and concise) JS:
decaffeinate file.coffee --use-cs2 --loose --optional-chaining --logical-assignment
Tip
If you use Babel and see errors while decaffeinati...
Fun with Ruby: Returning in blocks "overwrites" outside return values
In a nutshell: return
statements inside blocks cause a method's return value to change. This is by design (and probably not even new to you, see below) -- but can be a problem, for example for the capture
method of Rails.
Consider these methods:
def stuff
puts 'yielding...'
yield
puts 'yielded.'
true
end
We can call our stuff
method with a block to yield. It works like t...
Better compression for /boot partition
If you struggle with a /boot partition that is too small for updates, and you are too intimidated by the way to resize your /boot partition, there might be an easier fix:
It is possible to configure a better compression algorithm for the images in /boot
. To do this, edit /etc/initramfs-tools/initramfs.conf
and change the existing line to
COMPRESS=xz
Then rebuild the images using
sudo update-initramfs -u -k all
If you get an error during the last step, please immediately get help, because otherwise...
Use "overflow: hidden" to avoid floating elements from wrapping a container's text
Consider this HTML:
<div id="container">
<div id="actions">
<a href="#">Click me!</a>
</div>
<div id="content">
Hello Universe! Hello Universe! Hello Universe! Hello Universe! Hello Universe! Hello Universe!
</div>
</div>
If you want the actions
element to float on the left, you'd just say this in your CSS:
#actions { float: left; }
Unfortunately, any content of the content
's text will wrap underneath it:

const webpack = require('webpack')
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
)
module.exports = environment
This will work. But a side effect is that the fo...
PostgreSQL vs MySQL: How to UPDATE using a JOIN
When you want to UPDATE
a table with information from an associated table, you can JOIN
the associated table into the statement.
Example
Let's say you have a database schema where an Employee belongs_to :department
:
+-----------------+
| Employee | +------------+
|-----------------| n 1 | Department |
| email |-------------------|------------+
| department_id | | name |
+-----------------+ +------------+
Because of perfo...
How to test Autoprefixer and CSSnext in PostCSS
PostCSS is a tool for transforming styles with JS plugins. In Webpacker you can configure the plugins and their settings via the postcss.config.js
file. Make sure that postcss-loader
is part of your package.json
.
module.exports = {
plugins: [
require('postcss-import'),
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
})
]
}
Note: Stage 3 means you can use all CSS features that ar...
Speed up your websites: Put JavaScripts at bottom
For websites that don't do JavaScript rendering on the client, it's best practice to put script tags at the bottom of the HTML. This way, the page can start to render before scripts have been loaded and run.
The caveat is that you also have to move all other script tags from your views to the bottom of the page. This can be done with helpers.
How to implement
- Add the attached javascript_helper to your app.
- Move your `javascript_i...
HTML emails with inline stylesheets and webpacker
Many mail clients do not support external style sheets. Some even require all styling inline, which means you'll have to do your styling inline. For Rails applications, you can use Roadie or premailer, which lets you keep your well-structured CSS files and do the inlining for you.
Since Roadie is now in passive maintenance mode, we go with premailer:
Include premailer in your Gemfile:
gem 'premailer-ra...
Migration from the Asset Pipeline to Webpacker
This is a short overview of things that are required to upgrade a project from the Asset Pipeline to Webpacker. Expect this upgrade to take a few days even the diff is quite small afterwards.
Preparations
1. Find all libraries that are bundled with the asset pipeline. You can check the application.js
and the application.css
for require
and import
statements. The source of a library is most often a gem or a vendor directory.
2. Find an working example for each library in the application and write it down.
3. Find out the ver...
MySQL: How to create columns like "bigint" or "longtext" in Rails migrations, and what :limit means for column migrations
Rails understands a :limit
options when you create columns in a migration. Its meaning depends on the column type, and sometimes the supplied value.
The documentation states that :limit
sets the column length to the number of characters for string
and text
columns, and to the number of bytes for binary
and integer
columns.
Using it
This is nice since you may want a bigint
column to store really long numbers in it. You can just create it by ...
During deployment: "You are trying to install in deployment mode after changing your Gemfile"
While deploying an Ruby update to an old application these days, we encountered the following misleading error:
*** [err :: some-host.makandra.de] You are trying to install in deployment mode after changing
*** [err :: some-host.makandra.de] your Gemfile. Run `bundle install` elsewhere and add the
*** [err :: some-host.makandra.de] updated Gemfile.lock to version control.
*** [err :: some-host.makandra.de]
*** [err :: some-host.makandra.de] You have deleted from the Gemfile:
*** [err :: some-host.makandra.de] *
We found out a newe...
How to doubleclick in Selenium
Put the attached file into features/support/
.
Example usage:
When /^I open the task named "(.+?)"$/ do |task_name|
task = page.all('.task').detect do |t|
t.find('.label').text.downcase == task_name.downcase
end
task.double_click
end
Note: only Selenium understands doubleclicks.\
Credits: the attached Capybara issue discussion.
Why you can't use timezone codes like "PST" or "BST" for Time objects
Rails' ActiveSupport::TimeWithZone
objects have both a timezone code and offset, e.g. Thu, 28 Mar 2019 16:00:00 CET +01:00
. Ruby's stdlib TZInfo
also has time zones, but with different identifiers.
Unfortunately, not all timezone codes can be used to parse strings or to move time objects into another time zone.
Some timezone codes like CET
are supported by ActiveSupport extensions like String#in_time_zone
, while many codes will actually not work:
>> '2019-03-01 12:00'.in_time_zone('PST')
ArgumentError (Invalid Timezone: PST)
...
Git: Revert one or more commits
Reverting a commit means creating a new commit that undoes the old changes.
Imagine the following commit history:
* commit_sha3 [Story-ID 1] Fixup for my feature
* commit_sha2 [Story-ID 5] Other feature
* commit_sha1 [Story-ID 1] My feature
You can revert a single commit using the following syntax:
git revert commit_sha2
To revert changes that are split across multiple commits, use the --no-commit
flag.
git revert --no-commit commit_sha3
git revert --no-commit commit_sha1
git commit -m "Revert Story 1"