Cucumber's table diffing does not play nice with Spreewald's `patiently do`
Turns out, Cucumber::MultilineArgument::DataTable#diff!
caches some stuff. Code of the following form will not work as intended:
Then('some table should look like') do |expected_table|
patiently do
actual_table = calculate_actual_table
expected_table.diff!(actual_table) # not actually patient, will keep failing if it failed the first time
end
end
Instead, simply use
expected_table.dup.diff!(actual_table)
Debug SAML in development using a local keycloak server
Developing or debugging SAML functionality can be a hassle, especially when you need to go back and forth with someone external who is managing the identity provider (IDP).
But you can setup a local keycloak server to act as your IDP to play around with. This might seam intimidating, but is actually quite simple when using docker and turning off some verification steps.
1. Start a keycloak instance using docker
`mkdir -p keycloak_data && docker run --network=host -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN...
Ruby: How to connect to a host with expired SSL certificate
If you need to make an HTTPS connection to a host which uses an expired certificate, do not disable certificate verifications entirely. Doing that enables e.g. man in the middle attacks.
If you accept only a single expired and known certificate, you are much less in trouble.
Setup
All the solutions described below use a verify_callback
for the request's OpenSSL::X509::Store
where you can specify a lambda to adjust its verification response.
Your callback must return either true
or false
and OpenSSL's verification result is...
Your Cronjobs should not rely on a perfect schedule
Due to network or hardware failures, it can happen that one of your cronjobs will not run at the time you specify in the schedule. Your code should be built in a way that it can be re-run at a later time (when the failure is resolved).
For example, if you are synchronizing data with another service once every day, your cronjob should not only synchronize changes from the last 24 hours. If you do this and a network failure will delay the execution of your job by 5 hours, you will only synchronize changes from hour 6-29, but forget change...
Stretching an HTML page to full height
This card existed before, but was outdated due to browser implementation changes. The information below is validated for the current list of browsers we support.
By default your html
and body
elements are only as high as the actual page content inside their container. If you only have two lines of text in your page, your html
and body
elements will only be around 40 pixels high, regardless of the size of your browser window.
You might be surprised by this, since setting a background
on either html
and `body...
Ruby's percent notation can do more than strings
Percent Notation
We already know that that we can create strings using the percent notation:
%(<foo="bar's ton">)
is perfectly fine Ruby.
Modifier
But there is more. The curly brackets ({}
) are interchangable with most unicode characters (e.g. square brackets[]
).
Furthermore, you can add a "modifier" to the percent notation to control the return type of th...
Triggering JavaScript when an element is clicked
Often people need links which are not linked directly, but should trigger execution of JavaScript.
❌ Bad workarounds
You can find a lot of workarounds for that:
-
<a href="#">Do something with js!</a>
This defines an empty anchor. This may lead the browser to let the page jump to the top when the link is clicked, unless you callpreventDefault
on the event. This is probably not what you want. -
<a href="#!">Do something with js!</a>
This tells the browser to jump to an anchor!
. It depends on the browser implementation wha...
Auto-generating plain-text bodies for HTML e-mails in Rails apps
When building an application that sends e-mails to users, you want to avoid those e-mails from being classified as spam. Most obvious scoring issues will not be relevant to you because you are not a spammer.
However, your application must do one thing by itself: When sending HTML e-mails, you should include a plain-text body or tools like SpamAssassin will apply a significant score penalty. Here is how to do that automatically.
- Add
premailer-rails
to yourGemfile
andbundle
. - Done! ...
DNS debug tools
There are several tools for DNS debugging which offer you more or less information. Most of the time the more simple ones, like host
oder nslookup
will be sufficient.
host
simple DNS lookup utility.
>host heise.de
heise.de has address 193.99.144.80
heise.de has IPv6 address 2a02:2e0:3fe:1001:302::
heise.de mail is handled by 10 relay.heise.de.
nslookup
query Internet domain name servers. Nslookup has two modes: interactive and non-interactive.
>nslookup heise.de
Server: 146.254.160.30
Address: 146.254.160.3...
RSpec matcher to compare two HTML fragments
The RSpec matcher tests if two HTML fragments are equivalent. Equivalency means:
- Whitespace is ignored
- Types of attribute quotes are irrelevant
- Attribute order is irrelevant
- Comments are ignored
You use it like this:
html = ...
expect(html).to match_html(<<~HTML)
<p>
Expected content
</p>
HTML
You may override options from CompareXML by passing keyword arguments after the HTML string:
html = ...
expect(html).to match_html(<<~HTML, ignore_text_nodes: true)
...
Why has_many :through associations can return the same record multiple times
An association defined with has_many :through
will return the same record multiple times if multiple join models for the same record exist (a n:m relation). To prevent this, you need to add ->{ uniq }
as second argument to has_many
(below Rails 4 it is a simple option: has_many :xyz, :uniq => true
).
Example
Say you have an Invoice
with multiple Items
. Each Item
has a Product
:
class Invoice < ActiveRecord::Base
has_many :items
has_many :products, :through => :items
end
class Item < ActiveRecord::Base
...
Git: Switching back to the previous branch
Using git checkout -
you can switch back to the branch you previously worked on.
(master) $ git checkout foobar
Switched to branch 'foobar'
(foobar) $ git checkout -
Switched to branch 'master'
(master) $
This also works with other commands like git merge
:
(master) $ git checkout foobar
Switched to branch 'foobar'
(foobar) $ git merge -
Merged branch 'master'
Rails: Testing file downloads with request specs
tl;dr
Prefer request specs over end-to-end tests (Capybara) to joyfully test file downloads!
Why?
Testing file downloads via Capybara is not easy and results in slow and fragile tests. We tried different approaches and the best one is just okay.
Tests for file downloads via Capybara ...
- ... are slow,
- ... are fragile (breaks CI, breaks if Selenium driver changes, ...),
- ... need workarounds for your specia...
List of handy Ruby scripts to transcode different file types (often by using GPT)
It's 2024 and we have tools like ffmpeg, imagemagick and GPT readily available. With them, it's easy to convert texts, images, audio and video clips into each other.
For the everyday use without any parameter tweaking I'm using a collection of tiny scripts in my ~/bin
folder that can then be used as bash functions. And: It's faster to use the CLI than interacting with a website and cheaper to use the API than buying GPT plus.. :-)
Usage
text-to-image "parmiggiano cheese wedding cake, digital art"
- `text-to-audio "Yesterday I ate ...
MySQL: Disable query cache for database profiling
If you want to see how long your database queries actually take, you need to disable MySQL's query cache. This can be done globally by logging into a database console, run
SET GLOBAL query_cache_type=OFF;
and restart your rails server.
You can also disable the cache on a per query basis by saying
SELECT SQL_NO_CACHE * FROM ...
You also probably want to disable Rails internal (per-request) cache. For this, wrap your code with a call to ActiveRecord::Base.uncached
. For example, as an around_filter
:
d...
How to write a good changelog
We want to keep a changelog for all gems we maintain. There are some good practices for writing a changelog that adds value, please stick to these.
- Add a notice to the README's contribute section about the changelog
- For every release update the changelog
- Note the date format yyyy-mm-tt
What is a changelog?
A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of a project.
Why keep a changelog?
To make it easier for users and...
Carrierwave processing facts
- Class-level
process
definitions are only applied to the original file - Versions are generated based on the processed original file
- Callbacks (
before
/after
) are applied to original file and each version by itself - Under the hood, a version is an instance of the uploader class that has no versions
- Version uploader and original uploader can be distinguished by checking
#version_name
: version uploaders return the version name, whereas the original uploader instance returnsnil
- Version instances do not have a re...
Ubuntu: Disable webcam microphone
If you want to system-wide disable the microphone of your external webcam in PulseAudio use the following one-liners:
# Connected cards
$ pactl list short cards
1 alsa_card.pci-0000_00_1f.3 module-alsa-card.c
5 alsa_card.usb-Lenovo_ThinkPad_Thunderbolt_4_Dock_USB_Audio_000000000000-00 module-alsa-card.c
6 alsa_card.usb-HD_Webcam_C270_HD_Webcam_C270-02 module-alsa-card.c
# Disable HD_Webcam_C27
$ pactl list short cards | grep HD_Webcam_C27 | cut -f2 | xargs -rt -I % pactl set-card-profile % off
pactl s...
Geordi 10.0.0 released
10.0.0 2024-03-07
Compatible changes
-
console
command: You can now globally disable the IRB multiline feature by settingirb_flags: --nomultiline
in~/.config/geordi/global.yml
. All configured irb_flags are automatically passed on to the console IRB. -
console
command:Ctrl + C
now properly exits a local Rails console -
rspec
andcucumber
commands: Run specs even if the automatic chromedriver update fails - Improve detection of IRB version
- Add new hints to 'Did you know'
Breaking changes
-
dump
command: Drop...
Grid by Example: a website about CSS Grid
Rachel Andrew has built a website about CSS Grid.
- Video tutorials
- More than 30 layout examples for feature demonstration
- Layout patterns for copy-paste use
- All grouped by topic: "Placing items onto the grid", "Sizing of tracks and items" etc. with video, linked articles, examples each
Chaining Capybara matchers in RSpec
You can chain multiple Capybara matchers on the page
or any element:
expect(page)
.to have_content('Example Course')
.and have_css('.course.active')
.and have_button('Start')
When you chain multiple matchers using and
, [Capybara will retry the entire chain](https://github.com/teamcapybara/capybara/blob/c0cbf4024c1abd48b0c22c2930e7b05af58ab284/lib/capybara/rspec/matc...
UX details for web developers
A list of implementation details that make for a better / expected user experience. Have these in mind when implementing a web design.
This document outlines a non-exhaustive list of details that make a good (web) interface. It is a living document, periodically updated based on learnings. Some of these may be subjective, but most apply to all websites. The WAI-ARIA spec is deliberately not duplicated in this document. However, some accessibility guidelines may be pointed out.
CSS: Opacity is not inherited in Internet Explorer
Non-static elements will not inherit their parent's opacity in IE for no good reason. This can lead to unexpected behaviour when you want to fade/hide an element and all its children.
To fix it, give the parent element defining the opacity a non-static positioning. For example:
.parent {
opacity: 0.2;
position: relative; /* for IE */
}
While the linked article describes this problem for IE9 and below, I have encountered the same issue in IE10 and IE11.
Just go away, Internet Explorer!