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', ...
RSpec: How to turn off partial double verification temporarily
While verifying doubles in RSpec is a good default, it is limited in the amount of methods it actually is able to verify.
The background is that RSpec can't verify dynamically defined methods, which is a known issue for the usage of helper_method and also the reason why [RSpec >= 3.6](http://rspec.info/blog/2017/05/rspec-3-6-has-been-rel...
Ruby tempfiles
Tempfiles get deleted automatically
With the the ruby Tempfile class you can create temporary files. Those files only stick around as long as you have a reference to those. If no more variable points to them, the GC may finalize the object at some point and the file will be removed from the filesystem. If you would try to access your tempfile then using its path (which you stored previously), you would get an error because the file no longer exists.
Unlink your tempfiles when you're done with them
-...
How to show jQuery event handler on element
Chrome gives you the currently selected element in the inspector with $0
. If you select a button in the DOM you can set and inspect the event handler with the following two code lines:
$($0).on('click', function() { console.log('Hello') })
jQuery._data($0, "events").click[0].handler
// => "function () { console.log('Hello') }"
This is useful for debugging.
When upgrading/downgrading RubyGems and Bundler on a server, you must clear bundled gems
On application servers, gems are usually bundled into the project directory, at a location shared across deployments.
This is usually shared/bundle
inside your project's root directory, e.g. /var/www/your-project/shared/bundle/
.
If you can't find that, take a look at current/.bundle/config
and look for BUNDLE_PATH
.
When you are changing the version of RubyGems or Bundler on a system where gems are installed this way, you must wipe that bundle directory in addition to the user and system gems or gems that are already ins...
Rails asset pipeline: Why relative paths can work in development, but break in production
The problem
When using the asset pipeline your assets (images, javascripts, stylesheets, fonts) live in folders inside app
:
app/assets/fonts
app/assets/images
app/assets/javascripts
app/assets/stylesheets
With the asset pipeline, you can use the full power of Ruby to generate assets. E.g. you can have ERB tags in your Javascript. Or you can have an ERB template which generates Haml which generates HTML. You can chain as many preprocessors as you want.
When you deploy, Rails runs assets:precompile
...
How to make RubyMine aware of Cucumber steps defined in gems
If your Ruby project includes a gem like Spreewald that comes with some external step definition, RubyMine does not know about them by default and will highlight the step as an undefined reference:
To link these external step definitions to RubyMine, add the corresponding gems to your RubyMine-Settings:
- Go to Settings (
ctrl + alt + s
) - Go to Languages and Frameworks
- Go to Cucumber
- There, add your gem (e.g "spreewald") via the little "+" from the b...
Flexbox: How to prevent <pre> elements from overflowing
I recently had the problem that embedded code boxes crashed my layout.
It turned out that pre
s break out of their containers when using them inside a deeper nested flex layout.
For me it was a flex inside a flex item (fleXzibit).
<div class="flex">
<div class="flex-item">
...
<div class="nested-flex">
<div class="nested-flex-item">
<pre>A code example</pre>
</div>
</div>
...
</div>
</div>
The reason is that flexbox items default to `mi...
JavaScript: New Features in ES2021
tl;dr
With ES2021 you now can use
str.replaceAll()
,Promise.any()
, logical assignment operators, numeric separators andWeakRef
on all major browsers except IE11.
replaceAll
JavaScript's replace(searchValue, replaceValueOrFn)
by default replaces only the first match of a given String or RegExp.
When supplying a RegExp as the searchValue argument, you can specify the g
("global") modifier, but you have to remember doing that, hence using replace
when you expect global replacement is prone to errors.
When supplying st...
Rails: How to write custom email interceptors
Nowadays it is fairly easy to intercept and modify mails globally before they are sent. All you have to do is register an interceptor class which responds to .delivering_email(message)
. This card will show you two common use cases.
Subject prefix:
Usually you want to prefix the subject line of emails with the current environment (except production) so you can differentiate between production mails and mails from other environments. Of course a...
Inspect the page content in a Cucumber session
When you need to see the content of a page (i.e. not all the HTML but the relevant text body)
- you can do
pp (html_content)
- pp will format the html String human readable pretty printed
- where html_content can be replaced by one of the following commands:
Rails
body
or response.body
Capybara:
page.driver.html.content
page.body
Webrat:
Nokogiri::HTML(response.body).content
The returned strings can be cleaned up by calling .gsub(/^\s*$/, '').squeeze("\n")
on them.\
Although this may be useful for d...
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...
ActiveRecord: Query Attributes
tl;dr
You can useattribute?
as shorthanded version ofattribute.present?
, except for numeric attributes and associations.
Technical Details
attribute?
is generated for all attributes and not only for boolean attributes.
These methods are using #query_attribute
under the hood. For more details you can see ActiveRecord::AttributeMethods::Query
.
In most circumstances query_attribute
is working like attribute.present?
. If your attribute is responding to :zero?
then you have to be aware that `query_attri...
How to bind an event listener only once with Unpoly
You can use Unpoly's up.on with a named listener function and immediately unbind this event listener with { once: true }
:
up.on('up:fragment:inserted', { once: true }, function () { ... })
In Unpoly 1 you can immediately unregister the listener with up.off:
up.on('up:fragment:inserted', function fragmentInsertedCallback() {
up.off('up:fragment:inserted', fragmentInsertedCallback)
// ... code for the callback function, which should run only once
})
Exam...
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...
Bookmarklet to generate a Pivotal Tracker story from Zammad Ticket
This is a bookmarklet you can add to Chrome or Firefox which will allow you to create a story in Pivotal Tracker from a Zammad ticket. This might come in handy when creating stories for SWAT Teams.
But first you will have to set two variables in the script below:
-
pt_project_id
: the ID of the Pivotal Tracker Project you want to add stories to. This can be found as part of the URL of the project (https://www.pivotaltracker.com/n/projects/<pt_project_id>
) -
pt_token
: the Pivotal Tracker token used for authentication. Can be found in y...
Chrome DevTools: List Registered Event Listeners
In Chrome DevTools you can use getEventListeners(object)
to get a list of registered event listeners on the specified object.
You can also do this without the console, by selecting an element in the DOM inspector. In the element details, select the tab Event Listeners".
Example
const registry = getEventListeners(document)
registry['up-click']
// 0: { useCapture: false, passive: false, once: false, type: 'up:click', listener: ƒ }
// 1: { useCapture: false, passive: false, once: false, type: 'up:click', listener: ƒ }
//...
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...
RSpec: Expect one of multiple matchers to match
RSpec let's you chain a matcher with .or
. The expectation will then pass if at least one matcher matches:
expect(color).to eq("red").or eq("green")
Real-world example
A real-world use case would be to test if the current page has a button with the label "Foo". There are many ways to render a button with CSS:
<input type="button" value="Foo">
<input type="submit" value="Foo">
<button>Foo</button>
We cannot express it with a single have_css()
matcher, since we need the { text: 'Foo' }
optio...
Before you make a merge request: Checklist for common mistakes
Merge requests are often rejected for similar reasons.
To avoid this, before you send a merge request, please confirm that your code ...
- has been reviewed by yourself beforehand
- fulfills every requirement defined as an acceptance criterion
- does not have any log or debugging statements like
console.log(...)
,byebug
etc. - has green tests
- has tests...
Thread-safe collections in Ruby
When using threads, you must make your code thread-safe. This can be done by either locking (mutexes) all data shared between threads, or by only using immutable data structures. Ruby core classes like String
or Array
are not immutable.
There are several gems providing thread-safe collection classes in Ruby.
concurrent-ruby
The concurrent-ruby gem provides thread-safe versions of Array
and Hash
:
sa = Concurrent::Array.new # supports standard Array.new forms
sh = Co...
JavaScript: Working with Query Parameters
tl;dr: Use the URLSearchParams
API to make your live easier if you want to get or manipulate query parameters (URL parameters).
URLSearchParams
API
The URLSearchParams
API is supported in all major browsers except IE 11.
It offers you a bunch of useful methods:
-
URLSearchParams.append()
- appends a query parameter -
URLSearchParams.delete()
- deletes the specified query parameter -
URLSearchParams.get()
- returns the value of the specified query parameter - `URLSearchP...
Faking and testing the network with WebMock
An alternative to this technique is using VCR. VCR allows you to record and replay real HTTP responses, saving you the effort to stub out request/response cycles in close details. If your tests do require close inspection of requests and responses, Webmock is still the way.
WebMock is an alternative to FakeWeb when testing code that uses the network. You sh...
ActionMailer: Previewing mails directly in your email client
In Rails, we usually have a mailer setup like this:
class MyMailer < ActionMailer::Base
def newsletter
mail to: 'receiver@host.tld',
from: 'sender@host.tld',
subject: 'My mail'
end
end
If you want to preview your mail in the browser, you can use the Action Mailer Preview. To inspect the mail directly in your email client, just create an .eml
file and open it with your client:
mail = MyMailer.newsletter
Fil...