Rackal
The rackal
gem provides convenience helpers when configuring Rack applications.
The main intent is abstract away some common boilerplate and reduce hardcoded details in
application configuration, especially in config.ru
, in a way that still allows some
direct control of how it is applied.
Rackal was originally developed to simplify set up of Roda apps but is intended to not
assume or depend on Roda. As of this writing, no testing with Sinatra or bare Rack apps has
been performed, so milage may vary. This gem is still considered experimental (at least
until version number is updated to at least 0.1.0).
Features
- Environment aware: "production", "staging", "test", and "development" are recognized (based on ENV['RACK_ENV'])
- Database configuration: easy access to database configuration (based on YAML configuration file)
- Application metadata: easy access to application details (trivial YAML configuration file)
- Application protection: easy use of Refrigerator gem (when available)
Easy setup for application logging is being considered for inclusion in Rackal.
Example config.ru
require 'rackal'
# support logging
if Rackal.environment.unprotected? # by default: "development" or "test" is unprotected
require 'logger'
logger = Logger.new($stdout)
end
require 'roda'
Gem.ruby
# these output lines demonstrate some use
puts "Starting #{Rackal.application.name} in #{Rackal.environment.env} environment."
# => Starting MyApp in production environment.
puts "(root directory is \"#{Rackal.root}\")"
# => (root directory is "/home/someuser/src/my_app")
run(Rackal.application.main_class.freeze.app) # main_class is the driving class of the application
Rackal.protect! # applies Refrigerator if gem is present in production settings
An demonstration application using Rackal will be provided in a later version.
Main interface
Available as namespaced methods:
Rackal.application
returns an object allowing access to various application metadataRackal.root
returns the inferred root directory of the application (same as Rackal.appliation.root
)Rackal.database_parameters
returns Hash of database connection attributes (see below)Rackal.environment
returns an object allowing access to various runtime environment (e.g., "production") metadataRackal.env
convenience use of ENV
array (with caching) (e.g., Rackal.env("RACK_ENV")
== ENV["RACK_ENV"]
)Rackal.protect!
applies Refrigerator gem (if available) to lock/freeze the application during run time. Merely returns false
if gem is not available.
If ENV["RACK_ENV"]
is nil
for whatever reason, Rackal will assume a development environment.
Configuration
Two configuration files, written in YAML, will be assumed to be under /config
directory for
the application: database.yml
and rackal.yml
Twelve-factor app
If adhering to the twelve-factor app standard, recall that
deploy-level configuration should not included in code, but application configuration can
be.
Rackal does not interfere with use of tools like dotenv
or figaro to support deploy-level environment variable.
Merely add that to the application startup (e.g., config.ru
) in the usual way before
calling any Rackal methods.
Since the YAML files used for Rackal's configuration support ERB, those files can then
follow the environment variables supplied dynamically when wanted, while leaving
application-level directly supplied. The database.yml
example below shows such a use
for credentials.
database.yml
The database.yml
file is just to collect, by runtime environment, the parameters for
connecting to the database.
If Rackal.database_parameters
is never called, this YAML file need not be present.
Example (for Sequel using Postgres):
default: &default
adapter: 'postgres'
# host: 'some_db_url'
# port: '5432'
database: 'myapp'
max_connections: 10
username: <%= Rackal.env('MYAPP_DATABASE_USERNAME') %>
password: <%= Rackal.env('MYAPP_DATABASE_PASSWORD') %>
development:
<<: *default
host: 'localhost'
database: 'myapp_dev'
test:
<<: *default
host: 'localhost'
database: 'myapp_test'
staging:
<<: *default
production:
<<: *default
For the given runtime environment, the configured parameters are available in code via
Rackal.database_parameters
which provides a Hash (using symbols as keys):
Rackal.database_parameters[:database]
# => "myapp_test" if ENV['RACK_ENV'] == "test"
rackal.yml
The rackal.yml
file is for any specifics to inform Rackal of assumptions it can make.
Presently, only the name of the application is configured to support inference of how
to refer to it in the boilerplate it abstracts away (e.g., class name, source file name).
If neither Rackal.root
nor Rackal.application
are ever called (unlikely), this YAML file
need not be present.
Example:
rackal:
app_main: 'SomeApp' # note that this is the class name, provided as a string
app_main
: class name of the main class used to drive the application.
- The string, as given, is available in code as
Rackal.application.name
- The class, as a constant, is available in case as
Rackal.application.main_class
Performance
Given that one key feature of Roda is its performance and memory footprint, care was taken
to avoid interferring with that. Any cost is constrained as much as possible to only
application startup:
- Rackal is expected to add minimal time to application startup.
- Rackal is expected to consume marginally additional memory in the application for holding its
state once the application has started.
Rigorous performance testing has not yet been done to ensure those claims.
Contributing
Since a Gemfile is used for testing and development conveniences without polluting the
gem itself, be sure to bundle install
. RSpec, simplecov, and rubocop are assumed, but
only RSpec itself is required.
The provided RSpec tests have strong coverage for regression testing. Mutation testing
will be attempted soon.
Further development is invited to better support Roda applications, extensions and
generalization for non-Roda Rack applications, and performance improvements.
Acknowledgements
Jeremy Evans's roda-sequel-stack
repository
was used as an original reference for boilerplate (though the "up"/"down" mechanics for
database migrations are not considered in Rackal).
Some application metadata concepts were inspired by Rails (for instance, Rackal.root
),
though with a much lighter (and so less robust) approach taken in Rackal.
Limitations
- Rackal (primarily
Rackal.root
) assumes use in a Linux style OS and so use of /
as a
path delimiter. - Right now,
Rackal.database_parameters
has only been tested with Sequel ORM for database
connections, though the use of YAML to produce the Hash should be universally capable. - (As stated in the introduction to this notes,) Rackal has not been tested with a bare
Rack application or with a Sinatra application.
Please report issues or bugs.
License
Rackal is released under the MIT License.