Jerry
Jerry is a Ruby Inversion of Control container. You tell it how your classes depend on one another and it will create your application and wire all the dependencies correctly.
Jerry aims to be simple and straight forward. It also aims to be out of your way. Your classes don't need to know anything about jerry.
Why?
Dependency Injection is a great pattern for building loosely coupled applications. It allows you to build isolated components that can be swapped around.
The problem with this pattern is that it leaves you with a bunch of classes that you have to build and wire together yourself. Jerry does that for you.
Getting started
Important note
Currently jerry only supports constructor injection. If you're hoping to use setter injection, you're out of luck. You're going to need to switch to constructor injection.
Install it
You have 3 options:
Options 1: Add jerry to your Gemfile
gem 'jerry', '~> 2.0'Option 2: Add jerry to your *.gemspec
Gem::Specification.new do |spec|
# ...
spec.add_dependency 'jerry', '~> 2.0'
endOption 3: Just install it
gem install jerryCreate a configuration class
require 'jerry'
class MyConfig < Jerry::Config
def initialize(foo_db_url, bar_db_url)
@foo_db_url = foo_db_url
@bar_db_url = bar_db_url
end
bind Application, [FooService, BarService]
singleton bind FooService, [BarService, :foo_db]
singleton bind BarService, [:bar_db]
named_bind :foo_db Database [proc { @foo_db_url }]
named_bind :bar_db Database [proc { @bar_db_url }]
endLet's go over what's going on in this configuration class.
First, we define a constructor. It takes two database urls and stores them as instance variables. We'll go over what these urls are used for later. You should note that this constructor has no special meaning to jerry. It's entirely specific to this configuration class.
Second, we use bind to tell jerry how to wire the Application class. bind
takes two arguments. The first is the class we're telling jerry about and the
second is an array that tells jerry what constructor arguments to pass to the
class. Here you can notice that Application takes an instance of FooService
and an instance of BarService in its constructor.
Third, we tell jerry how to build FooService and BarService. Note that we're
calling singleton bind instead of bind here. singleton is used to tell
jerry that we want it to only instantiate the class we just described only once.
When we use singleton jerry will always pass the same instance of the given
class as a constructor argument. This is useful when some of your classes have
a persistent state. In this case, the BarService instance passed to both
Application and FooService will be the exact same instance.
Finally, we tell jerry how to build two instances of the Database class. The
first instance is named :foo_db and the second is named :bar_db. We
reference these instances when telling jerry about FooService and
BarService. This is what named_bind is for. We should also note that the
last arguments of the named_bind calls each contain a proc. In this case, the
procs are used to inject the database urls for each database. In a more general
sense, the procs are used to pass settings to various classes.
Create your application
require 'jerry'
jerry = Jerry.new MyConfig.new('db://localhost/foo', 'db://localhost/bar')
app = jerry[Application]Let's look at what's going on here.
First, we create an instance of our configuration class. We pass the urls for our two databases to the constructor.
Second, we create an instance of Jerry passing in the instance of our
configuration class.
Finally, we use the square bracket operator ([]) to create an instance of our
application. Of course our application is wired properly.
Learn more
If you'd like to learn more, here's some more documentation:
Development
Setup
./bin/setupRun tests
./bin/rake specRun linter
./bin/rake lintGenerate doc
./bin/rake docAutomatic watch
This will automatically watch the source code and run the tests, run the linter and build the doc everytime some files change.
./bin/guardReleasing
-
Bump version in
lib/jerry/version.rb -
Run release job
./bin/rake release