Rare Ruby Reasons
Hello
Daniel Farina, a founder of Ubicloud
- An Open Source Ruby Program
- A new IaaS, compare AWS, Azure, GCP
- Aim for a 50-90% cost reduction
- You can try it today at ubicloud.com
- Source code https://github.com/ubicloud/ubicloud
What is it?
The Rare Reasons
- Rare Libraries
- A Rare Engineer
- Rare Testing
(in twelve minutes)
{2011, 2015}
Ruby
Postgres
Sequel
Sinatra
2019
Ruby
Postgres
Sequel
Roda
2023
Ruby
Postgres
Sequel
Roda
Rodauth
Never used Rails!
it just never happened
don't ask me to compare, I won't know
spent my one and only youth writing "fancy ssh clients"
Roda
"Routing Tree" Framework
The "tree" takes the form of nested blocks.
Matchers accept literal values, simple data types, http methods...
Replaces "before" filters, and sometimes middleware
class App < Roda
route do |r|
# Matches "/items/<whatever>"
r.on "items" do
# Matches /items/[0-9]+$
r.is Integer do |item_id|
@item = Item[item_id]
# e.g. GET /items/123
r.get { "Rendering item: #{@item}" }
# e.g. DELETE /items/123
r.delete { @item.destroy }
end
end
# Matches /foo, /foo/bar, /pear/apple/peach
r.on String do |a_prefix|
r.get { "You asked for #{a_prefix}" }
end
end
end
class CloverWeb < Roda
# [...Lots of plugin setup...]
route do |r|
r.public
r.assets
check_csrf!
@current_user = Account[rodauth.session_value]
r.rodauth
rodauth.load_memory
rodauth.check_active_session
r.root do
r.redirect rodauth.login_route
end
rodauth.require_authentication
r.hash_branches
end
endExample from Ubicloud
class CloverWeb
hash_branch("project", "firewall") do |r|
r.get true do
authorized_firewalls = @project.firewalls_dataset.authorized(@current_user.id, "Firewall:view").all
@firewalls = Serializers::Firewall.serialize(authorized_firewalls, {include_path: true})
view "networking/firewall/index"
end
r.on "create" do
r.get true do
Authorization.authorize(@current_user.id, "Firewall:create", @project.id)
authorized_subnets = @project.private_subnets_dataset.authorized(@current_user.id, "PrivateSubnet:edit").all
@subnets = Serializers::PrivateSubnet.serialize(authorized_subnets)
@default_location = @project.default_location
view "networking/firewall/create"
end
end
Reopen Class, define branch
- still "
CloverWeb" (one class, many files) -
hash_branchjumps to the matching block - runs more familiar Roda code
matches "/project/firewall"
Reopens
clover_web.rb:class CloverWeb < Roda
routes/web/project.rb:class CloverWeb
routes/web/github.rb:class CloverWeb
routes/web/project/firewall.rb:class CloverWeb
routes/web/project/github.rb:class CloverWeb
routes/web/project/user.rb:class CloverWeb
routes/web/project/load_balancer.rb:class CloverWeb
routes/web/project/vm.rb:class CloverWeb
routes/web/project/billing.rb:class CloverWeb
routes/web/project/policy.rb:class CloverWeb
routes/web/project/private_subnet.rb:class CloverWeb
routes/web/project/usage_alert.rb:class CloverWeb
routes/web/project/location/firewall.rb:class CloverWeb
routes/web/project/location/load_balancer.rb:class CloverWeb
routes/web/project/location/vm.rb:class CloverWeb
routes/web/project/location/private_subnet.rb:class CloverWeb
routes/web/project/location/postgres.rb:class CloverWeb
routes/web/project/postgres.rb:class CloverWeb
routes/web/project/location.rb:class CloverWeb
routes/web/account.rb:class CloverWeb
routes/web/webhook/github.rb:class CloverWebReopen a lot, it's okay

Why do things that way?

Plugins that Ship with Roda
Routing:
autoload_hash_branches: Allows autoloading file for a hash branch when there is a request for that branch.
autoload_named_routes: Allows autoloading file for a named route when there is a request for that route.
all_verbs: Adds request routing methods for all http verbs.
backtracking_array: Allows array matchers to backtrack if later matchers do not match.
break: Supports break inside routing blocks for skipping the current matching route block as if it didn't match.
class_level_routing: Adds class level routing methods, for a DSL similar to sinatra.
error_handler: Adds ability to automatically handle errors raised by the application.
hash_branches: Supports O(1) dispatching to multiple branches at all levels in the routing tree.
hash_paths: Supports O(1) dispatching to multiple paths at all levels in the routing tree.
hash_routes: Provides a DSL to configure the hash_branches and hash_paths plugins.
head: Treat HEAD requests like GET requests with an empty response body.
hmac_paths: Prevent path enumeration and support access control using HMACs in paths.
hooks: Adds before/after hook methods.
match_hook: Adds a hook method which is called when a path segment is matched.
match_hook_args: Similar to match_hook plugin, but supports passing matchers and block args to hooks.
multi_route: Allows dispatching to multiple named route blocks in a single call.
multi_run: Adds the ability to dispatch to multiple rack applications based on the request path prefix.
named_routes: Allows for multiple named route blocks that can be dispatched to inside the main route block.
not_allowed: Adds support for automatically returning 405 Method Not Allowed responses.
not_found: Adds not_found method for handling responses not otherwise handled by a route.
pass: Adds pass method for skipping the current matching route block as if it didn't match.
path_rewriter: Adds support for rewriting paths before routing.
route_block_args: Controls which arguments are passed to the route block.
run_append_slash: Makes r.run use "/" instead of "" for app's PATH_INFO
run_handler: Allows for modifying rack response arrays when using r.run, and continuing routing for 404 responses.
run_require_slash: Skip dispatching to another application if PATH_INFO for dispatch would violate Rack SPEC
static_routing: Adds class level static routing methods, for maximum performance when handling static routes (routes without placeholders).
status_handler: Adds status_handler method for handling responses without bodies for a given status code.
type_routing: Route based on path extensions and Accept headers.
unescape_path: Decodes URL-encoded PATH_INFO before routing.
Rendering/View:
additional_render_engines: Allows for considering multiple render engines, using path for first template that exists.
additional_view_directories: Allows for checking for templates in multiple view directories, using path for first template that exists.
assets: Adds support for rendering CSS/JS javascript assets on the fly in development, or compiling them into a single compressed file in production.
assets_preloading: Adds support for generating browser-hinting preload link tags and headers.
branch_locals: Adds ability to specify defaults for template locals on a per-branch basis.
capture_erb: Allows capturing the output of ERB template blocks, instead of injecting them into the template output.
chunked: Adds support for streaming template responses using Transfer-Encoding: chunked.
content_for: Allows storage of content in one template and retrieval of that content in a different template.
custom_block_results: Adds support for arbitrary objects as block results.
erb_h: Adds faster (if slightly less safe method) h method for html escaping, based on erb/escape.
exception_page: Shows page with debugging information for exceptions, designed for use in error handler in development mode.
h: Adds h method for html escaping.
hash_branch_view_subdir: Automatically appends a view subdirectory for each successful hash branch taken.
inject_erb: Allows injecting arbitrary content directly into ERB template output.
json: Allows match blocks to return arrays and hashes, using a json representation as the response body.
link_to: Simplifies creation of HTML links.
multi_public: Adds support for serving all files in multiple public directories.
multi_view: Allows for easily setting up routing for rendering multiple views.
named_templates: Adds the ability to create inline templates by name, instead of storing them in the file system.
padrino_render: Makes render method that work similarly to Padrino's rendering, using a layout by default.
partials: Adds partial method for rendering partials (templates prefixed with an underscore).
precompile_templates: Adds support for precompiling templates, saving memory when using a forking webserver.
public: Adds support for serving all files in the public directory.
recheck_precompiled_assets: Allows checking for the precompiled assets metadata file for updates.
render: Adds render method for rendering templates, using tilt.
render_each: Render a template for each value in an enumerable.
render_coverage: Sets compiled_path for Tilt templates, allowing coverage of compiled templates before Ruby 3.2 (requires tilt 2.1+).
render_locals: Adds ability to specify defaults for template locals.
static: Adds support for serving static files using Rack::Static.
streaming: Adds ability to stream responses.
symbol_views: Allows match blocks to return template name symbols, uses the template view as the response body.
timestamp_public: Adds support for serving files in the public directory, with paths that change based on file modification time.
view_options: Allows for setting view options on a per-request basis.
Request/Response:
assume_ssl: Makes request ssl? method always return true, for use with SSL-terminating reverse proxies that do not set appropriate headers.
caching: Adds request and response methods related to http caching.
content_security_policy: Allows setting an appropriate Content-Security-Policy header for the application/branch/action.
cookie_flags: Adds checks for certain cookie flags, to update, warn, or error if they are not set correctly.
cookies: Adds response methods for handling cookies.
default_headers: Allows modifying the default headers for responses.
default_status: Allows overriding the default status for responses.
delegate: Adds class methods for creating instance methods that delegate to the request, response, or class.
delete_empty_headers: Automatically delete response headers with empty values.
disallow_file_uploads: Disallow multipart file uploads.
drop_body: Automatically drops response body and Content-Type/Content-Length headers for response statuses indicating no body.
halt: Augments request halt method for support for setting response status and/or response body.
invalid_request_body: Allows for custom handling of invalid request bodies.
module_include: Adds request_module and response_module class methods for adding modules/methods to request/response classes.
permissions_policy: Allows setting an appropriate Permissions-Policy header for the application/branch/action.
plain_hash_response_headers: Uses plain hashes for response headers on Rack 3, for much better performance.
r: Adds r method for accessing the request, useful when r local variable is not in scope.
redirect_http_to_https: Adds request method to redirect HTTP requests to the same location using HTTPS.
request_aref: Adds configurable handling for [] and []= request methods.
request_headers: Adds a headers method to the request object, for easier access to request headers.
response_request: Gives response object access to request object.
sinatra_helpers: Port of Sinatra::Helpers methods not covered by other plugins.
status_303: Uses 303 as the default redirect status for non-GET requests by HTTP 1.1 clients.
symbol_status: Allows the use of symbols as status codes, converting them to the appropriate integer.
typecast_params: Allows for easily converting parameter values to explicit types.
typecast_params_sized_integers: Allows for easily converting parameter values to integers for specific integer sizes (8-bit, 16-bit, 32-bit, and 64-bit).
Matchers:
class_matchers: Adds support for handling matchers for arbitrary classes, with support for type conversion.
custom_matchers: Adds support for arbitrary objects as matchers.
empty_root: Makes root matcher match empty string in addition to single slash.
hash_matcher: Adds hash_matcher class method for easily defining hash matchers.
header_matchers: Adds matchers using information from the request headers.
Integer_matcher_max: Sets a maximum integer value that will be matched by the default Integer matcher.
match_affix: Adds support for overriding default prefix/suffix used in match patterns.
multibyte_string_matcher: Makes string matcher handle multibyte characters.
param_matchers: Adds matchers using information from the request params.
params_capturing: Stores matcher captures in the request params.
path_matchers: Adds matchers using information from the request path.
placeholder_string_matchers: Supports placeholders in strings for backwards compatibility.
optimized_segment_matchers: Adds performance optimized matchers for single String class argument.
optimized_string_matchers: Adds performance optimized matchers for single string arguments.
slash_path_empty: Considers a path of "/" as an empty path when doing a terminal match.
symbol_matchers: Adds support for symbol-specific matching regexps.
Mail:
error_email: Adds ability to easily email a notification when an error is raised by the application, using net/smtp.
error_mail: Adds ability to easily email a notification when an error is raised by the application, using mail.
mail_processor: Adds support for processing emails using the routing tree.
mailer: Adds support for sending emails using the routing tree.
Middleware:
direct_call: Makes Roda.call skip the middleware stack, allowing more optimization when dispatching routes.
middleware: Allows the Roda app to be used as middleware by another app.
middleware_stack: Allows removing middleware and inserting middleware before the end of the stack.
Other:
common_logger: Adds support for logging in common log format.
csrf: Older CSRF plugin for backwards compatibility using rack_csrf.
environments: Adds support for handling different execution environments (development/test/production).
early_hints: Adds support for using 103 Early Hints responses when using a compatible server.
filter_common_logger: Adds support for skipping the logging of certain requests when using the common_logger plugin.
flash: Adds flash handling.
heartbeat: Adds support for heartbeats.
host_authorization: Allows configuring an authorized host or an array of authorized hosts.
indifferent_params: Adds params method for indifferent parameters.
json_parser: Parses request bodies in JSON format.
path: Adds support for named paths.
relative_path: Adds support for turning absolute paths into paths relative to current request.
route_csrf: Recommended CSRF plugin with request-specific tokens and control over where CSRF tokens are checked during routing.
sessions: Implements support for encrypted sessions.
shared_vars: Stores and retrives variables shared between multiple Roda apps.
strip_path_prefix: Strips prefixes off internal absolute paths, making them relative paths.
Micro
Framework?
"Plugins"
Rodauth
A plugin for
All Things Authentication
Features Like
- Webauthn
- 2FA
- Session Management
- Password Recovery
- Account Verification
- Template overriding
- ...quite a few others
plugin :rodauth do
enable :argon2, :change_login, :change_password, :close_account, :create_account,
:lockout, :login, :logout, :remember, :reset_password,
:disallow_password_reuse, :password_grace_period, :active_sessions,
:verify_login_change, :change_password_notify, :confirm_password,
:otp, :webauthn, :recovery_codes
title_instance_variable :@page_title
hmac_secret Config.clover_session_secret
login_view { view "auth/login", "Login" }
login_redirect { "/after-login" }
login_return_to_requested_location? true
login_label "Email Address"
two_factor_auth_return_to_requested_location? true
already_logged_in { redirect login_redirect }
after_login { remember_login if request.params["remember-me"] == "on" }
before_login do
if Account[account_id].suspended_at
flash["error"] = "Your account has been suspended. " \
"If you believe there's a mistake, or if you need further assistance, " \
"please reach out to our support team at support@ubicloud.com."
redirect login_route
end
end
[...]
# Multifactor Auth
two_factor_auth_view { view "auth/two_factor_auth", "Two-factor Authentication" }
two_factor_auth_notice_flash { login_notice_flash }
# don't show error message when redirected after login
# :nocov:
two_factor_need_authentication_error_flash { (flash["notice"] == login_notice_flash) ? nil : super() }
# :nocov:
# If the single multifactor auth method is setup, redirect to it
before_two_factor_auth_route do
redirect otp_auth_path if otp_exists? && !webauthn_setup?
redirect webauthn_auth_path if webauthn_setup? && !otp_exists?
end
# OTP Setup
otp_setup_route "account/multifactor/otp-setup"
otp_setup_view { view "account/multifactor/otp_setup", "My Account" }
otp_setup_link_text "Enable"
otp_setup_button "Enable One-Time Password Authentication"
otp_setup_notice_flash "One-time password authentication is now setup, please make note of your recovery codes"
otp_setup_error_flash "Error setting up one-time password authentication"
# Webauthn Setup
webauthn_setup_route "account/multifactor/webauthn-setup"
webauthn_setup_view { view "account/multifactor/webauthn_setup", "My Account" }
webauthn_setup_link_text "Add"
webauthn_setup_button "Setup Security Key"
webauthn_setup_notice_flash "Security key is now setup, please make note of your recovery codes"
webauthn_setup_error_flash "Error setting up security key"
webauthn_key_insert_hash { |credential| super(credential).merge(name: request.params["name"]) }
# Webauthn Auth
webauthn_auth_view { view "auth/webauthn_auth", "Security Keys" }
webauthn_auth_button "Authenticate Using Security Keys"
webauthn_auth_link_text "Security Keys"
# Recovery Codes
recovery_codes_route "account/multifactor/recovery-codes"
recovery_codes_view { view "account/multifactor/recovery_codes", "My Account" }
recovery_codes_link_text "View"
add_recovery_codes_view { view "account/multifactor/recovery_codes", "My Account" }
auto_add_recovery_codes? true
auto_remove_recovery_codes? true
recovery_auth_view { view "auth/recovery_auth", "Recovery Codes" }
end
200 Lines of this for a complex application...

A Rare Engineer
Jeremy Evans
Maintains all of:

Not only an acknowledgement.
The three programs are cohesive.
Roda: request routing
Rodauth: authentication
Sequel: database access
Jeremy's Humility
Blink and you'll miss something important in his talks.
...it gives me a sense of accomplishment to be able to fix bugs in Ruby that have been known but unfixed for many years. That's a situation that doesn't happen in my other open source projects.
—From one tiny corner of an interview
Fact Check: TRUE

Monthly(?!) Releases



Check out
roda-sequel-stack
separately, Rodauth
Rare Testing
100%* Branch Coverage
Dynamic Language is Key
Can do it without major program distortions
Reasons
- Avoid "leaking" found bugs
- Easy to inspect uncovered code
:nocov: okay
# Negative modulus is a handy trick to fill out pads like this.
padding = (nested_private_key.length % -8).abs
nested_private_key.write("12345678".slice(0, padding))
# :nocov:
fail "BUG: padding broken" unless nested_private_key.length % 8 == 0
# :nocovBetter to have some files at 100% than every file at 95%.
Conclusion
Rare Ruby Reasons
By fdrfdr
Rare Ruby Reasons
- 281