CSP: Nonces are propagated to imports
When you load a <script> with a nonce, that script can await import() additional sources from any hostname. The nonce is propagated automatically for the one purpose of importing more scripts.
This is not related to strict-dynamic, which propagates nonces for any propose not limited to imports (e.g. inserting <script> elements).
Example
We have a restrictive CSP that only allows nonces:
Content-Security-Policy: default-src 'none'; script-src 'nonce-secret123'
Our HTML loads script.js using that nonce:
A restrictive (but still practicable) CSP for Rails projects
Below is a strict, but still workable Content Security Policy for your Ruby on Rails project. Use this CSP if you want to be very explicit about what scripts you allow, while keeping pragmatic defaults for styles, images, etc. This CSP does not use the viral strict-dynamic source (reasoning).
We also have a very compatible CSP which is more liberal. Compatibility might outweigh strictness if you have a lot of scripts you can...
Caching file properties with ActiveStorage Analyzers
When working with file uploads, we sometimes need to process intrinsic properties like the page count or page dimensions of PDF files. Retrieving those properties requires us to download (from S3 or GlusterFS) and parse the file, which is slow and resource-intensive.
Active Storage provides the metadata column on ActiveStorage::Blob to cache these values. You can either populate this column with ad-hoc metadata caching or with custom Analyzers.
Attachment...
Sending newsletters via rapidmail with SMTP and one-click unsubscribe
If you need to implement newsletter sending, rapidmail is a solid option.
Support is very fast, friendly and helpful, and the initial setup is simple. Since rapidmail works via SMTP, you can simply ask the Ops team to configure SMTP credentials for your application.
You also do not need to use rapidmail’s built-in newsletter feature. Instead, you can send emails as transactional mails, which allows you to keep the entire newsletter logic inside your application.
One thing to keep an ey...
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...
Git: Finding changes in ALL commits
Finding changes
When you're looking for a specific change in Git, there are multiple axes you can choose:
-
git log -- path/to/filelists all commits that touch a file -
git log -G some_stringlists all commits where the diff contains "some_string"
Note that you can do most of these things with Git tools as well, e.g. tig path/to/file.
Considering ALL commits
By default, only the current branch (HEAD) is searched. To search across the entire local repository, add these options:
-
--all: Search all known refs (branches...
File System Access API: Recursive Directory Traversal
The File System Access API is a new capability of modern browsers that allows us to iterate over selected folders and files on a user's machine. Browser support is not great yet, but if the feature is only relevant for e.g. a single admin user it could still be worth using it prior to wider adaption instead of building yet another ZIP upload form.
Below is a simple compiler that i used to evaluate this feature.
!...
GoodJob: Ensure you get notified about background exceptions
GoodJob and ActiveJob rescue exceptions internally, preventing exception_notification from triggering. This can cause silent job failures.To get notified, subscribe to ActiveJob events and configure GoodJob's on_thread_error hook. This lets you manually call your exception notifier for every retry, discard, or internal GoodJob error.
# config/initializers/good_job.rb
# Manually notify on job failures, as they are handled internally by ActiveJob/GoodJob.
ActiveSupport::Noti...
Reliably sending a request when the user leaves the page
navigator.sendBeacon is a way to reliably send a POST request, even on unload.
Please note, however, that there are generally two ways to detect a "user leaving the page":
- The
unloadevent, which fires after a page is actually gone (e.g. after tab close, page refresh, and navigation away). - The
visibilitychangeevent. It is much softer, and will fire after tab contents have been hidden by any means (e.g. when closing a tab, but also when switchin...
Stabilize integrations tests with flakiness introduced by Turbo / Stimulus / Hotwire
If you run a Rails app that is using Turbo, you might observe that your integration tests are unstable depending on the load of your machine. We have a card "Fixing flaky E2E tests" that explains various reasons for that in detail.
Turbo currently ships with three modules:
- Turbo Drive accelerates links and form submissions by negating the need for full page reloads.
- Turbo Frames decompose pages into independent contexts, which scope navigation and can be lazily loaded.
- T...
Processing GitLab Merge Requests within RubyMine
GitLab has a RubyMine plugin that enables you to review and process merge requests within RubyMine!
Setup
- Open RubyMine settings (Ctrl + Alt + S) > Plugins > Search for "GitLab" > Install
- (You might need to re-open settings afterwards.)
- In the RubyMine settings > Version Control > GitLab > Connect your GitLab account with "+"
Working with merge requests
- From the Actions menu (Ctrl + Shift + A), choose "View merge...
Better performance insights with gem `rails_performance`
Even if you don't make any beginner mistakes like N+1 queries or missing DB indices, some requests can have bad performance. Without good performance metrics, you probably won't notice this until it's too late.
We investigated multiple gems and found that rails_performance (https://github.com/igorkasyanchuk/rails_performance) provides a lot of valuable information with very little setup cost. It only needs Redis which we use in the majority of our applications anyw...
Web performance snippets: little scripts that return performance metrics
Use these snippets when you want to measure yourself.
Currently available:
Core Web Vitals
Largest Contentful Paint (LCP)
Largest Contentful Paint Sub-Parts (LCP)
Quick BPP (image entropy) check
Cumulative Layout Shift (CLS)
Loading
Time To First Byte
Scripts Loading
Resources hints
Find Above The Fold Lazy Loaded Images
Find non Lazy Loaded Images outside of the viewport
Find render-blocking resources
Image Info
Fonts Preloaded, Loaded, and Used Above The Fold
First And Third Party Script Info
First And Third Party Script Timings
I...
Sidekiq: How to check the maximum client Redis database size
You can check the maximum client Redis database size in Sidekiq with this command.
Sidekiq.redis { |redis| puts redis.info.fetch('maxmemory_human') }
#=> 512.00M
If you just want the maximum database size for a known Redis database URL you can use the Redis Ruby client or the Redis CLI:
Redis database size via Ruby client
irb(main):002> Redis.new(url: 'redis://localhost:16380/1').info.fetch('maxmemory_human')
=> "512.00M"
Redis database size via CLI
$ redis-c...
Rails: Keeping structure.sql stable between developers
Why Rails has multiple schema formats
When you run migrations, Rails will write your current database schema into db/schema.rb. This file allows to reset the database schema without running migrations, by running rails db:schema:load.
The schema.rb DSL can serialize most common schema properties like tables, columns or indexes. It cannot serialize more advanced database features, like views, procedures, triggers or custom ditionaries. In these cases you must switch to a SQL based schema format:
# in application.rb
config.a...
Implementing upload progress and remove button with ActiveStorage DirectUpload
DirectUpload allows you to upload files to your file storage without having to wait for the form to submit. It creates AJAX requests to persist the file within your form and wraps them in a little API. This card will show you how to use it in order to create in-place file uploads with progress and a remove button.
This is basic functionality, you may add additional elements, styles and logic to make this look fancy, but the core functionality is the same. I created a file upload that looks like this:

const svgo = require('svgo')
const options = {
// ...
loader: {
// ...
'.svg': 'copy', // this may be different...
RSpec: Executing specs by example id (or "nesting index")
There are several ways to run a single spec. I usually copy the spec file path with the line number of the example and pass it to the RSpec binary: bin/rspec spec/models/user_spec.rb:30 (multiple line numbers work as well: :30:36:68). Another is to tag the example with focus: true or to run the example by matching its name.
In this card I'd like to ...
Using Low-Level Prompts for High-Accuracy AI Coding
The key to unlocking the full potential of LLMs in coding lies in crafting precise prompts. The main challenge is learning how to structure prompts effectively to guide the model toward accurate results. Further evidence supporting this is the fact that Aider already writes ~70% of its own code (as of 02/2025). However, when starting out, your results may fall short of efficiently generating large portions of your code with the...
How to disable telemetry for various open source tools and libraries
Hint
If you are using our opscomplete.com hosting we can set all environment variables mentioned below for your deployment on request.
If you're lucky DO_NOT_TRACK=1 opts you out of CLI telemetry - it's not widely adopted. When you're using any of the libraries below, I'd rather opt out explicitly:
Yarn
https://yarnpkg.com/advanced/telemetry (Since: Version 2.2)
Disable for a project:
#...
Rails 8 introduces `params.expect`
The new params.expect method in Rails 8 improves parameter filtering, addressing issues with malformed input and enhancing security. It provides a cleaner, more explicit way to enforce the structure and types of incoming parameters.
What changed
-
Replaces
requireandpermit: Combines both methods for concise parameter validation. - Explicit Array Handling: Requires double array syntax to define arrays of hashes, improving clarity.
- Enhanced Validation: Ensures expected parameter structure, rejecting malformed input wi...
Rails console tricks
Also see the list of IRB commands.
Switching the context
Changes the "default receiver" of expressions. Can be used to simulate a "debugger situation" where you are "inside" an object. This is especially handy when needing to call private methods – just invoke them, no need to use send.
- Switch to an object:
chws $object - Reset to
main:chws - Show current context:
cwws(usually shown in IRB prompt)
[Technical details](https://technology.doximity.com/articles/the-hidden-gems-of-r...