Capybara: Running tests with headless Chrome
Headless Chrome is a way to run the Chrome browser without a visible window.
Configuring Capybara
Configure the Capybara driver like this:
Capybara.register_driver :selenium do |app|
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--disable-infobars')
options.add_emulation(device_metrics: { width: 1280, height: 960, touch: false })
unless ENV.key?('NO_HEADLESS')
options.add_argument('--headless')
o...
SSHKit 1.9.0 failure for Capistrano deploy
SSHKit 1.9.0 might fail with the following error, when trying to deploy a Rail application. Upgrading the gem to version 1.21.0 fixed the issue.
Traceback (most recent call last):
17: from /home/user/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/sshkit-1.9.0/lib/sshkit/runners/parallel.rb:12:in `block (2 levels) in execute'
16: from /home/user/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/sshkit-1.9.0/lib/sshkit/backends/abstract.rb:29:in `run'
15: from /home/user/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/sshkit-1.9....
Whenever requires you to set the application attribute in the Capistrano config
Whenever requires you to set the application
attribute in your Capistrano configuration. Otherwise your cronjobs are created multiple times.
Example entry in config/deploy.rb
:
set :application, 'some-app' # allows "set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }" to work as expected
Good
Then the crontab -l
output will look like this:
# Begin Whenever generated tasks for: som...
Configuring Webpacker deployments with Capistrano
When deploying a Rails application that is using Webpacker and Capistrano, there are a few configuration tweaks that optimize the experience.
Using capistrano-rails
capistrano-rails is a Gem that adds Rails specifics to Capistrano, i.e. support for Bundler, assets, and migrations. While it is designed for Asset Pipeline (Sprockets) assets, it can easily be configured for Webpacker. This brings these features to the Webpacker world:
- Automatic removal of expired assets
- Manifest backups
How to Make Your Code Reviewer Fall in Love with You
Why improve your code reviews?
Improving code review technique helps your reviewer, your team, and, most importantly: you.
Learn faster: If you prepare your changelist properly, it directs your reviewer’s attention to areas that support your growth rather than boring style violations. When you demonstrate an appreciation for constructive criticism, your reviewer provides better feedback .
Make others better: Your code review techniques set an example for your colleagues. Effective author practices rub off on your teammates, which...
Variable fonts for web developers
This card is mainly an explanation how variable fonts work in CSS, not necessarily a recommendation to actually use them.
What is a variable font?
Designing and rendering fonts are two highly complex topics. For an arbitrary text to appear properly on your screen, its font must be created multiple times for different "settings" like stroke width (boldness) and style (e.g. italic).
Now as web developers, we usually ship these variants of the same font via multiple @font-face
s of the same font-family:
@font-face
font-family...
Rails developers: Have better context in Git diffs
Git diffs show the surrounding contexts for diff hunks. It does so by applying regular expressions to find the beginning of a context. When it comes to Ruby, however, it will not find method heads and travel up to the class definition:
@@ -24,7 +24,7 @@ class TicketPdf # <=== Actually expected here: the method definition
ApplicationController.render(
"tickets/index.html.haml",
layout: "tickets",
- assigns: { tickets: tickets }
+ assigns: { tickets: tickets, event_name: event_name }
)
end
end
```...
Minidusen: Filtering associated records
Minidusen lets you find text in associated records.
Assume the following model where a Contact
record may be associated with a Group
record:
class Contact < ApplicationRecord
belongs_to :group
validates_presence_of :name, :street, :city, :email
end
class Group < ApplicationRecord
has_many :contacts
validates_presence_of :name
end
We can filter contacts by their group name by joining the groups
table and filtering on a joined column.
Note how the joined column is qualified as groups.name
(rather than just `na...
Show/Hide Rubocop marking in RubyMine
If you have installed Rubocop in your project, RubyMine can show you Rubocop violations immediately in your editor. You probably already know this feature.
Example
Enable/Disable marking
If your RubyMine does not show you any violations, although there are some, you may have to enable the setting first.
To do so, open Navigate -> Search Everywhere -> Actions (Or use the shortcut CTRL + SHIFT + A
) and type in "rubocop", then you should see some...
How to configure file watchers in RubyMine
Installation
You need to install the official plugin, it is not bundled with RubyMine by default.
Example: Setup a watcher to verify rubocop integrity
First, open Settings -> Tools -> File Watchers. Then, configure rubocop to check every change to the VCS:
Note that the "program" argument must be part of your $PATH
. I worked around this constraint by using b
as a shim for bundle exec
.
Resources
- [File watchers documen...
Convert curl commands to ruby code
curl-to-ruby is a handy tool that converts your curl
command to ruby code that uses the Net::HTTP library.
Example
curl -X POST -d
"grant_type=password&email=email&password=password"
localhost:3000/oauth/token
will output to:
require 'net/http'
require 'uri'
uri = URI.parse("http://localhost:3000/oauth/token")
request = Net::HTTP::Post.new(uri)
request.set_form_data(
"email" => "email",
"grant_type" => "password",
"password" => "password",
)
req_options =...
Using ffmpeg as a HLS streaming server
A practical and detailed walk-through tutorial on using ffmpeg for live-streaming HLS, filled with real-world examples.
- Using FFmpeg as a HLS streaming server (Part 1) – HLS Basics
- Using FFmpeg as a HLS streaming server (Part 2) – Enhanced HLS Segmentation
- Using FFmpeg as a HLS streaming server (Part 3) – Multiple Bitrates
- Using FFmpeg as a HLS streaming server (Part 4) – Multiple Video Resolutions
- Using FFmpeg as a HLS streaming server (Part 5) – Folder Structure
- Using FFmpeg as a HLS streaming server (Part 6) – Independent Seg...
Ruby: Comparing a string or regex with another string
In Rubocop you might notice the cop Style/CaseEquality
for e.g. this example:
def foo(expected, actual)
expected === actual
end
In case expected
is a Regex, it suggests to change it to the following pattern:
def foo(expected, actual)
expected.match?(actual)
end
In case expected
is a Regex or a String, you need to keep ===
. Otherwise the actual
expression is always converted to a regular expression.
# For expected === actual
foo('Test(s)', 'Test(s)') #=> true
# For expected.match?(actual)
foo('Test(...
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
.
...
How to negate scope conditions in Rails
Sometimes you want to find the inverse of an ActiveRecord scope. Depending on what you want to achieve, this is quite easy with Rails 7, and a bit more complicated with Rails 6 and below, or when the inverse scope may contain NULL values. [1]
There are two different ways of "inverting a scope":
As an example, consider the following model.
class User < ApplicationRecord
scope :admins, -> { where(role: ['admin', 'superuser']) }
# ...
end
Mathematical NOT
You know this one from basic set theory. It proces the "complementa...
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 ...
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...
Debugging SPF records
While debugging a SPF record I found spf-record.de to be very helpful.
- it lists all IPs that are covered by the SPF record
- shows syntax errors
- helps you debugging errors like DNS lookup limit reached
- it also lets you test a new SPF strings before applying it. This can save you time as you don't have to loop with operations
Also the advanced check at vamsoft.com has a very good interface to test new SPF policies.
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....
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...
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 ...
Simple form examples with bootstrap
Good reference how to build bootstrap forms with simple_form.