Skip to content
This repository has been archived by the owner on Nov 5, 2022. It is now read-only.
/ rackal Public archive

Convenience helpers when configuring Rack applications [experimental]

License

Notifications You must be signed in to change notification settings

rdnewman/rackal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rackal

Gem Version

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 metadata
  • Rackal.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") metadata
  • Rackal.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 assumes / as the 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.

About

Convenience helpers when configuring Rack applications [experimental]

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages