Inventory
Inventory keeps track of the contents of your RubyÂč projects. Such an
inventory can be used to load the project, create gem specifications and
gems, run unit tests, compile extensions, and verify that the projectâs
content is what you think it is.
Âč See http://ruby-lang.org/
§ Usage
Letâs begin by discussing the project structure that Inventory expects you
to use. Itâs pretty much exactly the same as the standard Ruby project
structureÂč:
âââ README
âââ Rakefile
âââ lib
â âââ foo-1.0
â â âââ bar.rb
â â âââ version.rb
â âââ foo-1.0.rb
âââ test
âââ unit
âââ foo-1.0
â âââ bar.rb
â âââ version.rb
âââ foo-1.0.rb
Here you see a simplified version of a project called âFooââs project
structure. The only real difference from the standard is that the main
entry point into the library is named âfoo-1.0.rbâ instead of âfoo.rbâ and
that the root sub-directory of âlibâ is similarly named âfoo-1.0â instead
of âfooâ. The difference is the inclusion of the API version. This must
be the major version of the project followed by a constant â.0â. The
reason for this is that it allows concurrent installations of different
major versions of the project and means that the wrong version will never
accidentally be loaded with require.
Thereâs a bigger difference in the content of the files.
âčLib/foo-1.0/version.rbâș will contain our inventory instead of a String:
require 'inventory-1.0'
class Foo
Version = Foo.new(1, 4, 0){
authors{
author 'A. U. Thor', '[email protected]'
}
homepage 'http://example.org/'
licenses{
license 'LGPLv3+',
'GNU Lesser General Public License, version 3 or later',
'http://www.gnu.org/licenses/'
}
def dependencies
super + Dependencies.new{
development 'baz', 1, 3, 0
runtime 'goo', 2, 0, 0
optional 'roo-loo', 3, 0, 0, :feature => 'roo-loo'
}
end
def package_libs
%w[bar.rb]
end
}
end
Weâre introducing quite a few concepts at once, and weâll look into each in
greater detail, but we begin by setting the âčVersionâș constant to a new
instance of an Inventory with major, minor, and patch version atoms 1, 4,
and 0. Then we add a couple of dependencies and list the library files
that are included in this project.
The version numbers shouldnât come as a surprise. These track the version
of the API that weâre shipping using {semantic versioning}ÂČ. They also
allow the Inventory#to_s method to act as if youâd defined Version as
âč'1.4.0'âș.
Next follows information about the authors of the project, the projectâs
homepage, and the projectâs licenses. Each author has a name and an email
address. The homepage is simply a string URL. Licenses have an
abbreviation, a name, and a URL where the license text can be found.
We then extend the definition of âčdependenciesâș by adding another set of
dependencies to âčsuperâș. âčSuperâș includes a dependency on the version of
the inventory project thatâs being used with this project, so youâll never
have to list that yourself. The other three dependencies are all of
different kinds: development, runtime, and optional. A development
dependency is one thatâs required while developing the project, for
example, a unit-testing framework, a documentation generator, and so on.
Runtime dependencies are requirements of the project to be able to run,
both during development and when installed. Finally, optional dependencies
are runtime dependencies that may or may not be required during execution.
The difference between runtime and optional is that the inventory wonât try
to automatically load an optional dependency, instead leaving that up to
you to do when and if it becomes necessary. By that logic, runtime
dependencies will be automatically loaded, which is a good reason for
having dependency information available at runtime.
The version numbers of dependencies also use semantic versioning, but note
that the patch atom is ignored unless the major atom is 0. You should
always only depend on the major and minor atoms.
As mentioned, runtime dependencies will be automatically loaded and the
feature they try to load is based on the name of the dependency with a
â-X.0â tacked on the end, where âXâ is the major version of the dependency.
Sometimes, this isnât correct, in which case the :feature option may be
given to specify the name of the feature.
You may also override other parts of a dependency by passing in a block to
the dependency, much like weâre doing for inventories.
The rest of an inventory will list the various files included in the
project. This project only consists of one additional file to those that
an inventory automatically include (Rakefile, README, the main entry point,
and the version.rb file that defines the inventory itself), namely the
library file âčbar.rbâș. Library files will be loaded automatically when the
main entry point file loads the inventory. Library files that shouldnât be
loaded may be listed under a different heading, namely âadditional_libsâ.
Both these sets of files will be used to generate a list of unit test files
automatically, so each library file will have a corresponding unit test
file in the inventory. Weâll discuss the different headings of an
inventory in more detail later on.
Now that weâve written our inventory, letâs set it up so that itâs content
gets loaded when our main entry point gets loaded. We add the following
piece of code to âčlib/foo-1.0.rbâș:
module Foo
load File.expand_path('../foo-1.0/version.rb', __FILE__)
Version.load
end
Thatâs all thereâs to it.
The inventory can also be used to great effect from a Rakefile using a
separate project called Inventory-RakeÂł. Using itâll give us tasks for
cleaning up our project, compiling extensions, installing dependencies,
installing and uninstalling the project itself, and creating and pushing
distribution files to distribution points.
require 'inventory-rake-1.0'
load File.expand_path('../lib/foo-1.0/version.rb', __FILE__)
Inventory::Rake::Tasks.define Foo::Version
Inventory::Rake::Tasks.unless_installing_dependencies do
require 'lookout-rake-3.0'
Lookout::Rake::Tasks::Test.new
end
Itâs âčInventory::Rake::Tasks.defineâș that does the heavy lifting. It takes
our inventory and sets up the tasks mentioned above.
As we want to be able to use our Rakefile to install our dependencies for
us, the rest of the Rakefile is inside the conditional
#unless_installing_dependencies, which, as the name certainly implies,
executes its block unless the task being run is the one that installs our
dependencies. This becomes relevant when we set up Travis⎠integration
next. The only conditional set-up we do in our Rakefile is creating our
test task via Lookout-Rakeâ”, which also uses our inventory to find the unit
tests to run when executed.
Travis integration is straightforward. Simply put
before_script:
- gem install inventory-rake -v '~> VERSION' --no-rdoc --no-ri
- rake gem:deps:install
in the projectâs âč.travis.ymlâș file, replacing âčVERSIONâș with the version
of Inventory-Rake that you require. Thisâll make sure that Travis installs
all development, runtime, and optional dependencies that youâve listed in
your inventory before running any tests.
You might also need to put
env:
- RUBYOPT=rubygems
in your âč.travis.ymlâș file, depending on how things are set up.
Âč Ruby project structure: http://guides.rubygems.org/make-your-own-gem/
ÂČ Semantic versioning: http://semver.org/
Âł Inventory-Rake: http://disu.se/software/inventory-rake-1.0/
⎠Travis: http://travis-ci.org/
â” Lookout-Rake: http://disu.se/software/lookout-rake-3.0/
§ API
If the guide above doesnât provide you with all the answers you seek, you
may refer to the APIÂč for more answers.
Âč See http://disu.se/software/inventory-1.0/api/Inventory/
§ Financing
Currently, most of my time is spent at my day job and in my rather busy
private life. Please motivate me to spend time on this piece of software
by donating some of your money to this project. Yeah, I realize that
requesting money to develop software is a bit, well, capitalistic of me.
But please realize that I live in a capitalistic society and I need money
to have other people give me the things that I need to continue living
under the rules of said society. So, if you feel that this piece of
software has helped you out enough to warrant a reward, please PayPal a
donation to [email protected]Âč. Thanks! Your support wonât go unnoticed!
Âč Send a donation:
https://www.paypal.com/cgi-bin/webscr?cmd=_donations&[email protected]&item_name=Inventory
§ Reporting Bugs
Please report any bugs that you encounter to the {issue tracker}Âč.
Âč See https://github.com/now/inventory/issues
§ Authors
Nikolai Weibull wrote the code, the tests, the documentation, and this
README.
§ Licensing
Inventory is free software: you may redistribute it and/or modify it under
the terms of the {GNU Lesser General Public License, version 3}Âč or laterÂČ,
as published by the {Free Software Foundation}Âł.
Âč See http://disu.se/licenses/lgpl-3.0/
ÂČ See http://gnu.org/licenses/
Âł See http://fsf.org/