CSS: Don't target multiple vendor-prefixed pseudo-elements in a single rule
Some pseudo-elements need to be addressed with vendor prefixes. E.g. ::selection is not supported by Firefox, you need to use ::-moz-selection instead.
What you cannot do is to define a single CSS rule to address both the standard and vendor-prefixed form:
::selection, ::-moz-selection {
background-color: red;
}
This rule will be ignored by all browsers. If a browser does not know al...
Rails 6.1: where.not changes behaviour from NOR to NAND
Since Rails 6.1, if we use where.not with multiple attributes, it applies logical NAND (NOT(A) OR NOT(B)) instead of NOR (NOT(A) AND NOT(B)). If you do not take care, this change will increase the matched set.
Examples
"Don't send newsletters neither to admins nor to trashed users!" becomes "Don't send newsletters to trashed admins".
User.where.not(role: 'admin', trashed: true)
# Before Rails 6.1, with NOR
=> "SELECT "users".* FROM "users" WHERE "users"."role" != 'admin' AND "users"."trashed" != TRUE"
# Equivale...
HTTP headers can only transport US-ASCII characters safely
HTTP header values must only contain low-ASCII (7-bit) characters for safe transport. From RFC 7230:
Historically, HTTP has allowed field content with text in the ISO-8859-1 charset [ISO-8859-1], supporting other charsets only through use of [RFC2047] encoding. In practice, most HTTP header field values use only a subset of the US-ASCII charset [USASCII]. Newly defined header fields SHOULD limit their field values to US-ASCII octets.
If you need to transport 8-bit+ characters (e.g...
Knapsack: Rerun a flaky test locally
Knapsack allows you to rerun a specific job locally. This is helpful to run specs in the exactly same order like in the CI.
Example for running rspec 3/8 with a seed output of 20689:
CI_NODE_INDEX=2 CI_NODE_TOTAL=8 bundle exec rake "knapsack:rspec[--seed=20689]"
*Note: the environment variable ...
Beware: Many browsers define window.event
Some browsers define window.event, which will return a copy of the "current" event. However, this is not defined by the W3C. Most importantly, Firefox does not support it, neither do recent versions of IE.
You should completely avoid accessing the global event and instead pass the event object around that the event handler receives. The easiest protection against accidentally accessing window.event is just never naming the event event, but e or evnt or so.
function brokenInFirefox() {
event.preventDefault() // Brea...
How to split up a git commit
Quick steps
-
git rebase -i-> mark your commit withedit -
git reset HEAD~(remove the marked commit, but keep its changes) - Make several commits (optionally setting the previous author manually)
git rebase --continue
Detailed instructions
Basically, you will review the last n commits and stop at the splittable commit. Then you'll undo that commit and put its changes into new commits at your liking.
-
Review commits (
rebase)git rebase -i HEAD~3 # or git rebase -i origin/master...
How to explain SQL statements via ActiveRecord
ActiveRecord offers an explain method similar to using EXPLAIN SQL statements on the database.
However, this approach will explain all queries for the given scope which may include joins or includes.
Output will resemble your database's EXPLAIN style. For example, it looks like this on MySQL:
User.where(id: 1).includes(:articles).explain
EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
+----+-------------+-------+-------+---------------+
| id | select_type | table | type | possible_keys |
+----+-----...
Always disable autocomplete for date pickers
When we write a form with date fields, we often use graphical data picker like Rome to get a consistent calendar popup on all browsers.
When you integrate a date picker popup, remember to also set autocomplete="off" on the text input that opens the calendar on click. Otherwise the autocomplete suggestions will cover the calendar box and make it unusable:
If you are using a tool like Unpoly you might want to set autocomplete="off" i...
Cancelling event propagation
Within an event handler, there are multiple methods to cancel event propagation, each with different semantics.
-
event.preventDefault()Only prevents the default browser behavior for the click, i.e. going to a different url or submitting a form.
When invoked on a
touchstartevent, this also prevents mouse events likeclickto be triggered. -
event.stopPropagation()Prevents the event from bubbling up the DOM.
-
`event.st...
Controlling how your website appears on social media feeds
When a user shares your content, a snippet with title, image, link and description appears in her timeline. By default social networks will use the window title, the first image, the current URL and some random text snippet for this purpose. This is often not what you want.
Luckily Facebook, Twitter, etc. lets you control how your content appears in the activity streams. They even have agreed on a common format to do this: OpenGraph <meta> tags that go into your HTML's <head>:
<meta property="og:url" content="http://start.m...
How to bulk-unwatch many repositories on Github
To easily opt out of notifications for a large number of Github repositories, go to https://github.com/watching.
Defining custom RSpec matchers
There are three ways to define your own RSpec matchers, with increasing complexibility and options:
1) Use RSpec::Matchers.define
RSpec::Matchers.define :be_a_multiple_of do |expected|
match do |actual|
actual % expected == 0
end
# optional
failure_message do |actual|
"expected that #{actual} would be a multiple of #{expected}"
end
# optional
failure_message_when_negated do |actual|
"expected that #{actual} would not be a multiple of #{expected}"
end
end
- This is automatically available i...
Your database tables should always have timestamps
Whenever you create a table from a database migration, remember to add updated_at and created_at timestamps to that table. Without those timestamps, investigating future bug reports will be hell. Always have timestamps.
Adding timestamps to new tables
When you create a table using create_table, you can add timestamps by using the timestamps shortcut:
class CreateEpisode < ActiveRecord::Migration
def change
create_table :episodes do |t|
t.string :name
t.timestam...
Rubocop fails with undefined StringIO
If your rubocop run fails with a stack like
rubocop-1.61.0/lib/rubocop/server/socket_reader.rb:36:in `ensure in read!': undefined method `string' for nil:NilClass (NoMethodError)
Cache.stderr_path.write(stderr.string)
^^^^^^^
...
rubocop-1.61.0/lib/rubocop/server/socket_reader.rb:27:in `read!': uninitialized constant RuboCop::Server::SocketReader::StringIO (NameError)
stderr = StringIO.new
^^^^^^^^
this card might help you.
In old versions of rubocop stringio w...
Controlling the order of DOM event listeners
Event listeners are called in the order of their registration:
button.addEventListener('click', () => console.log("I run first"))
button.addEventListener('click', () => console.log("I run second"))
Sometimes you want a listener to always run first (or last), but have no control over the order in which other listeners are registered.
There is no clean mechanism in the DOM API for this. This card shows some hacks to do it anyway.
Exploiting the capturing phase
Before an event bubbles up from an element to the document, it...
How to accept more than 4k query parameters in Rails
I have a form with a dynamic number of fields. Submitting it worked fine until I tried out a very large version of it. The development log was not very helpful:
Invalid or incomplete POST params
As it turned out, the following exception did not reach the log output
Rack::QueryParser::QueryLimitError
Error Message: total number of query parameters (6313) exceeds limit (4096)
If you ever happen to be in the same position, this is how to increase the limit of allowed query parameters:
# config/initializers/rack_query_parser.rb
...
Testing ActiveJob `limits_concurrency` with Solid Queue
The :test adapter doesn't respect limits_concurrency configuration. Switch to :solid_queue adapter in your test to verify blocking behavior.
Job Configuration
class MembershipJob < ApplicationJob
limits_concurrency(key: ->(membership) { membership })
end
The problem
When using the default test mode for enqueuing jobs, both will be enqueued immediately. However, we actually we want to test that only one of both will be enqueued as the other should have been blocked.
# This doesn't actually test concurren...
Generating test images on the fly via JavaScript or Ruby
When you need test images, instead of using services like lorempixel or placehold.it you may generate test images yourself.
Here we build a simple SVG image and wrap it into a data: URI. All browsers support SVG, and you can easily adjust it yourself.
Simply set it as an image's src attribute.
JavaScript
Simple solution in modern JavaScript, e.g. for use in the client's browser:
function svgUri(text) {
let svg = `
<svg wid...
Use a global .gitignore file to ignore stuff from your machine
Sometimes you want git to ignore certain files that appear on your machine. You can do this in 3 ways:
- Per project, in the project's
.gitignorefile - Per project, in a local exclude file
- Globally on your machine
Downsides of per-project .gitignore entries
While it might be tempting to set it per project (other devs might benefit from it), you
- need to do it each time for every project
- "pollute" a project's
.gitignorefile with stuff...
Faux-disabled fields in HTML forms
You want to prevent input to a form field, but all the solutions have side effects:
- The
[readonly]attribute is only available for text fields, but not for checkboxes, selects, buttons, etc. - The
[disabled]attribute is available for all kinds of fields, but will no longer include the field value in the submitted form data. -
pointer-events: nonestill allows keyboard input, and does not indicate disabledness visually, or to screen readers.
Ye...
Opt out of selenium manager's telemetry
If you use the selenium-webdriver gem, it will sneakily phone home once every hour whenever you run a browser based feature spec.
Check if you're affected
Check if ~/.cache/selenium/se-metadata.json exists. (It contains a "ttl" timestamp of its last/next anaytics call. You can parse it with Ruby's Time.at.)
Opt out
You can opt out either globally:
# .bashrc
export SE_AVOID_STATS=true
or project based
# spec_helper...
Cucumber CI job quirks
Most of our CI pipelines don't use the --retry flag for Cucumber and instead build their own retry via the tmp/failing_features.txt file.
Benefits:
- It's possible to only use
-f prettyfor the rerun.
Drawbacks:
- MAJOR: With our current setup, when the main run fails without writing a
tmp/failing_features.txt(e.g. due to a syntax error), the CI job will pass - MINOR: With our current setup, we lose the test coverage of the main run
A fix for the passing CI despite syntax error could look like this:
cucumber:
# ...
sc...
Debugging Rails Active Jobs with the Vanilla Adapters
Short reference on how to quickly debug the vanilla Rails job adapters.
Queue Adapters by Environment
| Environment | Adapter | Jobs Run In | Worker Needed? |
|---|---|---|---|
| development | :async |
Rails server process | No |
| test | :test |
Not executed (stored) | No |
| production | :solid_queue |
Separate worker | Yes (bin/jobs) |
Development (:async)
Jobs run in background threads ([Concurrent Ruby ThreadPoolExecutor](https://ruby-concurrency.github.io/concurrent-ruby/maste...