Openhood

bundler/inline for single-file ruby scripts

Image by by Joshua Fuller on unsplash

Sometimes you want to create a single ruby script using exact versions of some gems, but you don’t want to have to create a directory just to have a Gemfile and your script file in it, then have to do the bundle install/bundle exec dance to run it properly.

Enter bundler/inline

This require will allow your script to install and use the exact gems you specify, right inside the file.

You can then run it using only ruby my_single_file.rb.

Here’s an example which allows to test a complex interaction using a Chrome browser (installed on demand) all in a single script.

It uses capybara‘s puma integration to start an HTTP server, then access it using the specified version of Chrome for Testing (installed automatically by selenium-webdriver‘s Selenium Manager) running in headless mode.

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'puma'
  gem 'capybara', '3.40.0'
  gem 'selenium-webdriver', "~> 4.29.1"
end

require 'selenium-webdriver'
require 'capybara/dsl'

# Make sure selenium-webdriver will download the proper `Chrome for Testing` if
# not already in cache.
ENV["SE_FORCE_BROWSER_DOWNLOAD"] = "true"

Capybara.register_driver :chrome do |app|
  Capybara::Selenium::Driver.new(
    app,
    browser: :chrome,
    options: Selenium::WebDriver::Options.chrome.tap do |options|
      options.add_option :browser_version, '126.0.6478.182'
      options.add_argument 'headless'
    end
  )
end

html = <<~HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Testing beforeunload in Chrome with Capybara</title>
    <meta charset="utf-8">
    <script type="text/javascript">
      window.addEventListener('beforeunload', (event) => {
        event.preventDefault();
        return 'HERE';
      });
    </script>
  </head>
  <body>
    <h1><a href="/demo">Load another page</a></h1>
  </body>
</html>
HTML

app = proc { |env| [200, { "Content-Type" => "text/html" }, [html] ] }

session = Capybara::Session.new(:chrome, app)
session.visit "/"
session.accept_alert do
  # interact with the page, to get Chrome to fire `beforeunload`
  # It doesn't work anymore starting from Chrome >= 127 as it's disabled until
  # a `user interaction` which never happens when driven by selenium.
  session.click_on "Load another page"
end
# Ensure the alert/confirm is gone after the end of previous block
session.find_all("a")
session.reset!

puts "it worked!"
Copyright © 2025 Openhood SARL