Duct is a small wrapper around bundler. It allows you to embed a Gemfile in a script.
Sometimes you write small scripts to do different tasks. Sometimes you store them for future use. Sometimes those
scripts use some gems to do their task (database access, web requests, whatever). So, after some time, you reuse them
and you don't know which version of which gems did you use and you can run into trouble (like with full fledged apps in
the pre-bundler days). That's when you do the obvious workaround: create a directory to store the script together with a
Gemfile
and a Gemfile.lock
.
That's a good solution but feels a bit overkill. Duct allows you to embed the Gemfile
(and the Gemfile.lock
) in the same file, so it's a single file to store together with others, as a gist, etc.
Duct is a command line utility, so just install it via rubygems:
$ gem install duct
First, write your Gemfile
in the data section of your script, after the __END__
label, and after a @@ Gemfile
label:
require 'sinatra'
get '/' do
'Hello, world!'
end
__END__
@@ Gemfile
source 'https://rubygems.org'
gem 'sinatra'
(this is very much like the Sinatra inline templates, and can in fact be combined with them).
Then, run the script using the duct
command:
$ duct my_script.rb
The default action is running the script, checking previously whether dependencies are met, and installing them (via
bundle install
) if needed. Notice that your script data section will be updated with a section for the Gemfile.lock
if needed (beware of conflicts with your editor while you develop the script).
If your script expects parameters, just pass them after the filename:
$ duct my_script.rb param1 param2
You can run any of the bundle
subcommands (mainly update
, with or without a gem name, but also outdated
, check
,
list
, show
and all the rest) passing them before the
filename:
$ duct update sinatra my_script.rb
Remember that updating the bundle will update the Gemfile.lock
section in your script, so remember to save those changes.
Under Unix-like operating systems, you can instruct the program loader to use Duct to run your script. Just put the following shebang in the first line of your script (the # ruby
comment is needed because of something explained here):
#!/usr/bin/env duct # ruby
and add execute permissions to your script:
chmod +x my_script
This gives you the ability to treat your script as an executable that, once in your $PATH, to execute it directly.
Duct will ignore the part of the data section before the first @@ XYZ
label (and the sections with other labels
than @@ Gemfile
and @@ Gemfile.lock
, as it was mentioned for the Sinatra inline templates case), so you can still
use that ruby feature, but you will need to make sure your script handles and ignores the Gemfile
and Gemfile.lock
sections, of course.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
Released under the MIT License, Copyright (c) 2014 Sergio Gil.