Passive event listeners may speed up your scroll and touch events
Scroll and touch event listeners tend to be computationally expensive as they are triggered very often. Every time the event is fired, the browser needs to wait for the event to be processed before continuing - the event could prevent the default behavior. Luckily there is a concept called passive event listeners which is supported by all modern browsers.
Below are the key parts quoted from WICG's explainer on passive event listeners. See [this demo video](https://www.youtube.com/watch?v=NPM6172...
Ruby: A short summary of available hooks in Cucumber
Here is a short summary of Cucumber hooks in Ruby taken from https://github.com/cucumber/cucumber-ruby. Note that the BeforeStep
is currently not existing in the Ruby implementation of Cucumber.
Before
hooks run before the first step of each scenario.
Before do |scenario|
...
end
After
hooks run after the last step of each scenario, even when the step result is failed
, undefined
, pending
or skipped
.
...
Manage Linux services on the command line (Ubuntu)
Ubuntu 18.04 uses systemd
to manage services.
There are basically two commands for listing all services and manipulating the state of a certain service: service
and systemctl
:
-
service
manages System V init scripts -
systemctl
controls the state of the systemd system and service manager. It is backwards compatible to System V and includes the System V services
Therefore I prefer to use systemctl
.
See which services are there
>systemctl list-units -a --type=service
UNIT LOAD ...
HTML file inputs support picking directories
HTML's <input type="file">
accepts a single file. You can allow multiple files via <input type="file" multiple>
.
But sometimes, selecting multiple files is not enough and can be cumbersome for the user. Enter webkitdirectory
:
<input type="file" webkitdirectory multiple>
Using webkitdirectory
switches the browser's file picker to select a directory. All files inside that directory, and inside any nested subdirectories, will be selected for the file input.
This can be useful when users want to upload all files from a nested dire...
Migrate gem tests from Travis CI to Github Actions with gemika
We currently test most of our gems on Travis CI, but want to migrate those tests to Github Actions. This is a step-by-step guide on how to do this.
Note that this guide requires the gem to use gemika.
- Go to a new "ci" branch:
git checkout -b ci
- Update gemika to version >= 0.5.0 in all your Gemfiles.
- Have gemika generate a Github Actions workflow definition by running
mkdir -p .github/workflows; bundle exec rake gemika:generate_github_actions_workflow > .github/workf...
How to downgrade Google Chrome in Ubuntu
If you're experiencing problems with your Google Chrome installation after an update, it might help downgrading Chrome to check if the problem disappears. Keep in mind though that running outdated software, especially web browsers, is in most cases not a good idea. Please verify periodically if you still need to run the old version or if an even more recently updated version fixes the problems introduced in your version.
Here's how to get old versions of Chrome for your Ubuntu installation:
First, go to [UbuntuUpdates](https://www.ubuntuup...
Installing old versions of mysql2 on Ubuntu 20.04+
On some of our older projects, we use the mysql2 gem. Unfortunately, versions 0.2.x (required for Rails 2.3) and versions 0.3.x (required for Rails 3.2) can no longer be installed on Ubuntu 20.04. Trying this either leads to errors when compiling the native extension, or a segfaults when using it.
For Rails 4.2, mysql2 version 0.4.10 seems to work okay. If you still have issues, upgrade to 0.5.x, which should be compatible.
To install it, you have to switch the mysql2 gem to our fork. In your Gemfile, ...
Installing Ruby <= 2.3 on Ubuntu 20.04+
Installing old Rubies (<= 2.3) with a standard rbenv + ruby-build is no longer possible on Ubuntu 20.04. This is because those Rubies depend on OpenSSL 1.0 which is no longer shipped with current Ubuntus.
We have forked ruby-build with a workaround that makes it compile and statically link the latest OpenSSL 1.0 version. This works on Ubuntu 20.04, as well as on Ubuntu 18.04.
To switch to our fork of ruby-build, update ruby-build like this
git -C ~/.rbenv/plugins/ruby-build remote add makandra...
VCR: Alternative way of mocking remote APIs
If you need to test interaction with a remote API, check out the VCR gem as an alternative to Webmock or stubbing hell.
The idea behind VCR is that is performs real HTTP requests and logs the interaction in a .yml file. When you run the test again, requests and responses are stubbed from the log and the test can run offline.
It's a great way to mock network requests to an external service without going through the pain of log...
Error when deploying 1.8.7 app: "NoMethodError: undefined method `select!' for ["zlib@openssh.com", "zlib"]:Array"
Fix: downgrade net-ssh
to version 2.9.1.
PostgreSQL: Importing dumps created with newer versions
When loading a database dump created with pg_dump
into your database, you might run into an error like
pg_restore: error: unsupported version (1.15) in file header
This is because your local pg_restore
version is too old to match the format created by pg_dump
. The version of the PostgreSQL server doesn't matter here.
For example, the official Ubuntu 20.04 sources include only PostgreSQL 12, so your pg_restore
version will also be v12. Ubuntu 22.04 includes version 14 in its sources.
Both seem to be incompatible with dumps ...
Rails: How to restore a postgres dump from the past
It sometimes happen that a database dump, that would want to insert into your development database, does not match the current schema of the database. This often happens when you have an old dump, but your current setup is up to date with the the master.
Hint: In most cases it is sufficient to delete and recreate the local database in order to import the dump. If any problems occur, proceed as follows:
1. Figure out the original migration status of the dumpfile
- Convert your dump to plaintext: `pg_restore -f some.dump > some.dump....
Security issues with hash conditions in Rails 2 and Rails 3
Find conditions for scopes can be given either as an array (:conditions => ['state = ?', 'draft']
) or a hash (:conditions => { 'state' => 'draft' }
). The later is nicer to read, but has horrible security implications in some versions of Ruby on Rails.
Affected versions
Version | Affected? | Remedy |
---|---|---|
2.3.18 | yes | Use chain_safely workaround |
3.0.20 | no | ... |
Where to find .desktop files on Ubuntu
.desktop
files define launchers for applications installed on your machine. They specify the command that will be executed when launched, icons, titles, etc. There are two directories in which these files are stored:
# basic installation
/usr/share/applications
# installed via snap
/var/lib/snapd/desktop/applications/
How to implement simple queue limiting/throttling for Sidekiq
The sidekiq-rate-limiter gem allows rate-limiting Sidekiq jobs and works like a charm. However, it needs to be integrated on a per-worker basis.
If you want to limit a whole queue instead, and if your requirements are simple enough, you can do it via a Sidekiq middleware yourself.
Here is an example that limits concurrency of the "mailers" queue to 1. It uses a database mutex via the [with_advisory_lock](https://github.com/ClosureTree/wit...
Generated face images for UI mockups
Generated Photos produces AI-generated face images.
This is useful for UI mockups where you don't want to show real people or copyrighted stock photography.
VCR and the webdrivers gem
If you're using the webdrivers gem and VCR together, depending on your configuration, VCR will yell at you regulary.
The webdrivers gem tries to update your webdrivers on your local machine. To do so, it checks the internet for newer versions, firing an HTTP-request to e.g. https://chromedriver.storage.googleapis.com
You can "fix" this in multiple ways:
-
Update your drivers on your machine with
RAILS_ENV=test rake webdrivers:chromedriver:update
-
Ignore the driver update-URL in your ...
Rails: How to list all validations on a model or an attribute
If a model inherits from others or uses many concerns / traits, it might be hard to see in the code which validators it has.
But fortunately there's a method for that:
irb(main):002:0> pp UserGroup.validators
[#<ActiveModel::Validations::InclusionValidator:0x00007f55efff97a8
@attributes=[:deleted],
@delimiter=[true, false],
@options={:in=>[true, false], :allow_nil=>false}>,
#<ActiveModel::Validations::InclusionValidator:0x00007f55f15748d0
@attributes=[:cancelled],
@delimiter=[true, false],
@options={:in=>[true, false], ...
Simple form examples with bootstrap
Good reference how to build bootstrap forms with simple_form.
Always, always declare your associations with symbols
Never ever declare your associations with a string, especially when doing metaprogramming. A common mistake is something like
# WRONG
class Page < ActiveRecord::Base
%w[main sub].each do |type|
belongs_to "#{type}_title"
end
end
# RIGHT
class Page < ActiveRecord::Base
%w[main sub].each do |type|
belongs_to :"#{type}_title"
end
end
Always convert to a symbol, otherwise you'll have all [kinds](/m...
How to include Sidekiq job IDs in Rails logs
When logging in Rails, you can use the log_tags
configuration option to add extra information to each line, like :request_id
or :subdomain
. However, those are only valid inside a request context and have no effect when your application is logging from inside a Sidekiq process.
This includes custom as well as any framework logs, like query logging from ActiveRecord.
Since Sidekiq Workers run inside threads of a single process, running multiple jobs in...
Pagy
Pagy is a gem for pagination.
They make some bold claims:
Pagy is the ultimate pagination gem that outperforms the others in each and every benchmark and comparison.
Maybe this is worth trying out.
How to generate GIDs from an ActiveRecord scope
ActiveRecord provides the ids
method to pluck ids from a scope, but what if you need to pluck Global IDs?
While you could just call map(&:to_global_id)
on your scope, this approach would instantiate each record just to do that. When you have many records, this will at the very least be slow.
Here is a method that does it for you efficiently. It respects Single Table Inheritance (STI).
Put it in your project's ApplicationRecord
to make it available on all models.
class ApplicationRecord
...
Chrome: Using browser notifications
Development
Google Chrome disables Notification
s for insecure origins (i.e. those using HTTP). Only http://localhost
is considered secure.
If you need to use browser notifications on other origins, you can set a flag: chrome://flags/#unsafely-treat-insecure-origin-as-secure. Enable the flag and add your origins. Remember that "origin" refers to the combination of protocol+hostname+port, e.g. "http://example.com:8088".