net-ssh and openssl-3.0.0
You'll need openssl-3 or newer for servers running 22.04
Ruby version 3.1 uses by default the gem openssl-3.0.0. This can cause issues with the gem net-ssh (6.1.0). This is a known bug.
Typically this can cause an error while deploying an application with capistrano:
could not verify server signature (SSHKit::Runner::ExecuteError)
or
Ed25519::VerifyError: signature verification failed!
As temporary workaround add the following line to your Gemfile:
gem 'openssl', ...
Use DatabaseCleaner with multiple test databases
There is a way to use multiple databases in Rails.
You may have asked yourself how you're able to keep your test databases clean, if you're running multiple databases with full read and write access at the same time. This is especially useful when migrating old/existing databases into a new(er) one.
Your database.yml may look like this:
default: &default
adapter: postgresql
encoding: unicode
username: <%= ENV['DATABASE_USER'] %>
host: <%= ENV['DATABASE...
Gem development: recommended gem metadata
The gemspec for gems allows to add metadata to your gem, some of which have a special meaning and are helpful for users.
You can provide links to your Github bugtracker or changelog file that are then used on the rubygems page of your gem (in the sidebar, e.g. see gem page of consul).
Here are some keys that should be filled:
Gem::Specification.new do |s|
s.name = 'my-gem'
s.homepage = 'https://github.com/makandra/my-gem'
s.metadata = {
'source_code_uri' => s.homepage,
'bug_tracker...
How to get information about a gem (via CLI or at runtime from Ruby)
When you need information about a gem (like version(s) or install path(s)), you can use the gem binary from the command line, or the Gem API inside a ruby process at runtime.
gem binary (in a terminal)
You can get some information about a gem by running gem info <gem name> in your terminal.
Example:
$ gem info irb
*** LOCAL GEMS ***
irb (1.4.1, 1.3.5)
Author: Keiju ISHITSUKA
Homepage: https://github.com/ruby/irb
Licenses: Ruby, BSD-2-Clause
Installed at (1.4.1): /home/arne/.rbenv/versions/3.0.3/lib/ruby/g...
jeremyevans/ruby-warning: Add custom processing for warnings
ruby-warning adds custom processing for warnings, including the ability to ignore specific warning messages, ignore warnings in specific files/directories, include backtraces with warnings, treat warnings as errors, deduplicate warnings, and add custom handling for all warnings in specific files/directories.
This tool can precisely silence deprecation warnings.
While you should fix deprecations in your application, ruby-warning is handy to silence those warnings that you cannot fix. E.g. when they originate from libraries that you ca...
Version 5 of the Ruby Redis gem removes Redis.current
Redis.current will be removed without replacement in redis-rb 5.0.
Version 4.6.0 adds deprecation warnings for Redis.current and Redis.current=:
`Redis.current=` is deprecated and will be removed in 5.0.
If your application still uses Redis.current, you can only fix it by no longer using it. Here is how.
Redis.new when you need it
You can easily instantiate a Redis client when you need it.
There is probably already a constant like REDIS_URL that you use to configure Sidekiq or similar. So just use that one.
``...
Integrating ESLint
Introduction
To ensure a consistent code style for JavaScript code, we use ESLint. The workflow is similar to integrating rubocop for Ruby code.
1. Adding the gem to an existing code base
You can add the following lines to your package.json under devDependencies:
"devDependencies": {
"@eslint/js": "x",
"@stylistic/eslint-plugin": "x",
"eslint": "x",
"eslint-plugin-import": "x",
"globals": "x",
}
...
How to add esbuild to the rails asset pipeline
This are the steps I needed to do to add esbuild to an application that used the vanilla rails asset pipeline with sprockets before.
Preparations
- update Sprockets to version 4
- add a
.nvmrcwith your preferred node version (and install it) - add gems
jsbundling-railsandforemanto yourGemfile:gem 'jsbundling-rails' group :development, :test do gem 'foreman' # ... end bundle install- run
bin/rails javascript:install:esbuildin a console to prepare esbuild. - run `yarn instal...
Understanding Ruby's def keyword
This StackOverflow question about nested function definitions in Ruby imparts a good understanding of Ruby's def.
New gem: Rack::SteadyETag
Rack::SteadyETag is a Rack middleware that generates the same default ETag for responses that only differ in CSRF tokens or CSP nonces.
By default Rails uses Rack::ETag to generate ETag headers by hashing the response body. In theory this would enable caching for multiple requests to the same resourc...
Ensure passing Jasmine specs from your Ruby E2E tests
Jasmine is a great way to unit test your JavaScript components without writing an expensive end-to-end test for every small requirement.
After we integrated Jasmine into a Rails app we often add an E2E test that opens that Jasmine runner and expects all specs to pass. This way we see Jasmine failures in our regular test runs.
RSpec
In a [feature spec](https://web.archive.org/web/20150201092849/http://www.rel...
RSpec: how to prevent the Rails debug page if you want to actually test for 404s
Within development and test environments, Rails is usually configured to show a detailed debug page instead of 404s. However, there might be some cases where you expect a 404 and want to test for it.
An example would be request-specs that check authorization rules. (If you use a gem like consul for managing authorization rules, you should always check these rules via power-specs. However, request-specs can be used as a light-weight version of integration tests here.)
In this case, Rails will replace the 404 page that you want to test ...
RSpec: automatic creation of VCR cassettes
This RailsCast demonstrated a very convenient method to activate VCR for a spec by simply tagging it with :vcr.
For RSpec3 the code looks almost the same with a few minor changes. If you have the vcr and webmock gems installed, simply include:
# spec/support/vcr.rb
VCR.configure do |c|
c.cassette_library_dir = Rails.root.join("spec", "vcr")
c.hook_into :webmock
end
RSpec.configure do |c|
c.around(:each, :vcr) do |example|
name = example.metadata[:full_descripti...
Better numeric inputs in desktop browsers
You want to use <input type="number"> fields in your applications.
However, your desktop users may encounter some weird quirks:
- Aside from allowing only digits and decimal separators, an "e" is also allowed (to allow scientific notation like "1e3").
- Non-technical users will be confused by this.
- Your server needs to understand that syntax. If it converts only digits (e.g.
to_iin Ruby) you'll end up with wrong values (like 1 instead o...
Fix REPL of better_errors page
The gem better_errors offers a detailed error page with an interactive REPL for better debugging.
I had the issue that on a few projects with Ruby 2.5.8, the REPL was not shown.
Solution
To make the REPL work properly with this Ruby version I had to update the gem binding_of_caller to at least version 0.8.0.
From the [better_errors](https://github.com/BetterE...
Ruby: You can nest regular expressions
Ruby lets you re-use existing RegExp objects by interpolating it into new patterns:
locales_pattern = /de|en|fr|es/i
html_tag_pattern = /<html lang="#{locales_pattern}">/
Any modifiers like /i or /x will be preserved within the interpolated region, which is pretty cool. So in the example above only the interpolated locales are case-insensitive, while the pattern around it (/<html .../) remains case-sensitive.
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)
...
How to extract a Ruby gem
The rubygems binary gem allows to extract a local gem with gem unpack GEMNAME. For more details see the official documentation.
This was useful for compliance checks, when it was necessary to check the license of the C-files in nokogiri.
Spreewald development steps
Our gem spreewald supports a few helpers for development. In case you notice errors in your Cucumber tests, you might want to use one of them to better understand the underlying background of the failure. The following content is also part of the spreewald's README, but is duplicated to this card to allow repeating.
Then console
Pauses test execution and opens an IRB shell with current cont...
How to avoid raising RestClient exceptions for 4xx or 5xx results
When using RestClient to make an HTTP request, it will raise an exception when receiving a non-successful response.
HTTP status codes like 422 or 403 might be totally expected when talking to APIs, so plastering your code with rescue RestClient::Exception or similar can feel annoying.
It may not be intuitive, but the readme says you can also pass a block to methods like RestClient.get or RestClient::Request.execute. In that case, RestClient will not raise ...
Chromedriver: Disabling the w3c option might break your integration tests with Chrome 91
We recently noticed issues with Chrome 75+ when having the w3c option enabled within the Selenium webdriver. It looks like recent Selenium versions don't have any issues with the w3c interface anymore. And starting with Chrome 91 this fix might cause unexpected issues, so you should try to enabled this option again or just remove the following line from you configuration:
options.add_option('w3c', false)
Background: Setting the w3c option t...
Heads up: Counting may be slow in PostgreSQL
The linked article points out that COUNT queries might be unexpectedly slow in PostgreSQL.
If you just need to know "are there any records" use any?. This uses SELECT 1 AS one FROM ... LIMIT 1 under the hood.
If you just need to know "are there no records" use empty? or none?. This uses SELECT 1 AS one FROM ... LIMIT 1 under the hood.
In short: Replace foo.count > 0 with foo.any? or foo.count == 0 with foo.none?
If you require quick counts and can tolerate some level of imprecision, consider exploring the ...
Heads up: Byebug has problems with zeitwerk
I encountered a unlucky behavior of byebug 11.1.3 (the most recent version at time of writing) when using it with Rails 6 and it's new autoloading component, zeitwerk. There already is a issue for that, so I hope it will be fixed with a future release.
The following test succeeds:
context 'factories' do
let(:test_case) { FactoryBot.create(:test_case) }
it 'are valid' do
expect(test_case).to be_valid
end
end
But when I did the same in byebug the foll...
Ruby: Fixing strings with invalid encoding and converting to UTF-8
When dealing with external data sources, you may have to deal with improperly encoded strings.
While you should prefer deciding on a single encoding with the data-providing party, you can not always force that on external sources.
It gets worse when you receive data with encoding declaration that does not reliably fit the accompanying string bytes.
Here is a Ruby class that helps converting such strings to a proper encoding.
Note that it tries several approaches of changing the encoding. **This is not a silver bullet and may or may not work...