Often people need links which are not linked directly, but should trigger execution of javascript.
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 call preventDefault
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 what happens when an anc...
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.
premailer-rails
to your Gemfile
and bundle
.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...
Rewrote most of the card.
The RSpec matcher tests if two HTML fragments are equivalent. Equivalency means:
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)
...
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
).
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
...
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'
We no longer use non-deterministic versions like lts/gallium
. This is not supported by all tools. In particular asdf is sunsetting its support for LTS aliases.
tl;dr
Prefer request specs over end-to-end tests (Capybara) to joyfully test file downloads!
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 ...
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.. :-)
text-to-image "parmiggiano cheese wedding cake, digital art"
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...
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.
A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of a project.
To make it easier for users and...
process
definitions are only applied to the original filebefore
/after
) are applied to original file and each version by itself#version_name
: version uploaders return the version name, whereas the original uploader instance returns nil
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...
console
command: You can now globally disable the IRB multiline feature by setting irb_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 consolerspec
and cucumber
commands: Run specs even if the automatic chromedriver update failsdump
command: Drop...Rachel Andrew has built a website about CSS Grid.
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...
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.
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!
The CSS property z-index
is not as global as you might think. Actually, it is scoped to a so-called "stacking context". z-indexes only have meaning within their stacking context, while stacking contexts are treated as a single unit in their parent stacking context. This means indices like 99999
should never actually be needed.
In order to create a stacking context with the least possible side effects, use the isolation
property on an...
Trick: Do not use convert
but mogrify
:
mogrify -resize 50% *
This overwrites the original image file.
In contrast, convert
writes to a different image file. Here is an example if you need this:
cd /path/to/image/directory
for i in `ls -1 *jpg`; do convert -resize 50% $i "thumb_$i"; done
A common cause of non-accessible web pages are elements that were made interactive via JavaScript but cannot be focused or activated with anything but the mouse.
Let's take a look at a common example:
<form filter>
<input filter--query name="query" type="text">
<span filter--reset>Clear Search</span>
</form>
The HTML above is being activated with an Unpoly compiler like this:
up.compiler('[filter]', function(filterForm) {
const resetButton = filterForm.querySelec...