Subs
A lightweight alternative to Ruby gems
Overview
There are often cases when a developer/team needs to reuse and share portions of code which just "aren't enough" for a gem. Subs might be a solution to this problem. Read on.
The name "subs", the concept of subs, the technology behind subs are yet experimental. All sorts of feedback is highly appreciated.
Examples of subs
- A library or extension in its early stage of existence with a high reuse potential.
- A low-level extension to a class which implements a particular pattern, which isn't enough for a gem. Examples: boilerplate initializer, attribute validation, attribute caching etc.
Sub features
- Subs are truly lightweight.
- Subs don't have version numbers.
- Subs don't have init code. They won't gain control until you
require
them. - The amount of formalities required to update a sub is almost zero.
- There is no minimum amount of code required to make a sub. If your extension is 1 line long, but is reusable — go make a sub of it.
- Subs do have home repositories, but updates to subs are made directly in the projects which use them.
- Sub's home repository is checked out to N locations simultaneously.
- After you've made an update to the sub commit your changes right away to the sub's
origin
. - Underlying mechanism to manage the distribution of subs is Git submodules.
- Subs are often local to developer/team which produced them.
- Subs don't require unique names like gems do. It's okay to name your sub
downloader
if you can uniquely identify what it is. - Subs have 100% test coverage. This is to compensate for their highly dynamic and version-free nature.
Setup
Consider you are in the local working copy of your project and you want to install a sub from https://github.com/dadooda/feature_cache into it. Steps follow.
-
Create a directory for subs:
$ mkdir -p vendor/subs
-
Check out the sub as Git submodule:
$ git submodule add git@github.com:dadooda/feature_cache.git vendor/subs/feature_cache
-
Add the
$:
include path update to your boot code. E.g. in yourconfig/boot.rb
do a:Dir[File.expand_path("../../vendor/subs/*/lib", __FILE__)].each {|fn| $: << fn if File.directory?(fn)}
-
To use the sub in your code do a:
require "feature/cache"
-
To install/update all installed subs to their latest versions, do a:
$ git submodule update --init --remote
Further reading
More information on working with subs is available at the project's wiki pages.
Cheers!
— Alex Fortuna, © 2015-2016