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
ruby
gem 'jerry', '~> 2.0'
Option 2: Add jerry to your *.gemspec
ruby
Gem::Specification.new do |spec|
# ...
spec.add_dependency 'jerry', '~> 2.0'
end
Option 3: Just install it
sh
gem install jerry
Create a configuration class
```ruby 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 }] end ```
Let’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
```ruby 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
sh
./bin/setup
Run tests
sh
./bin/rake spec
Run linter
sh
./bin/rake lint
Generate doc
sh
./bin/rake doc
Automatic watch
This will automatically watch the source code and run the tests, run the linter and build the doc everytime some files change.
sh
./bin/guard
Releasing
- Bump version in
lib/jerry/version.rb -
Run release job
sh bundle exec rake release