To start up a Ruby project, you don't need to do anything other than put some Ruby code in a file and invoke it with ruby program.rb
.
As projects grow, though, you'll likely add dependencies and tests. You can mitigate this with documentation - tell users what gems they need to pull, and which files contain the test suites - but that becomes unwieldy quick. It's much better to lean on ecosystem tools to specify and automate your build steps.
To follow along, you'll need Ruby installed. The latest at time of writing is version 2.7.0.
EDIT: If you don't want to do this from scratch, try bundler gem
:
I find the easiest way to start a new Ruby project is
bundler gem
, even when not actually writing a gem. It also follows Ruby conventions, i.e. alib
folder instead ofsrc
.This is how you do it:
You can then just delete
foo.gemspec
😀Make a directory
Don't just spread your ruby source all across your home directory - keep your projects self contained. Create a directory:
Open this directory in your favorite editor. Everything else in this post goes in here.
Add Bundler
To manage dependencies, use Bundler. This tool allows you to specify gems required to run your project and lets users issue a single
bundle install
command to pull down any required.First, install the gem in you haven't already:
Then, create a file called
Gemfile
in your project root. For now, we'll just specify the package repository URL:As we need dependencies, we'll add them here below this line.
Add a Test file
The first dependency we need is for testing. This example uses minitest. Add that to your
Gemfile
:Now you can invoke
bundle install
to pull this down automatically. When you do, a new file calledGemfile.lock
will be generated containing the specific package version in use.This is really up to you, but I like keeping my tests in a separate subdirectory:
Create a file in this folder called
test/cool_program_test.rb
with the following contents:The first line,
# frozen_string_literal: true
, is a magic comment that is kind of like callingObject.freeze
on every string literal. This is done for performance reasons, but you can opt out for a given string by prefixing it with a+
character:+'my newly mutable string literal'
. Now you can domy_str << some_other_str
. In Ruby, though, I'm not finding myself manipulating strings like this.We know we'll be able to use the
minitest
dependency in the first line because we specified it with Bundler. The actual source code doesn't exist yet, though!Add an Implementation File
This is also personal preference, but it's a sensible idea to keep your implementations in a separate subdirectory as well:
Create the file we pulled into the test file at
lib/cool_program.rb
with these contents:Groovy! Everything's in place.
Add a Rakefile
Now, we could just direct users to invoke
ruby
themselves on the proper files -ruby lib/cool_program.rb
to run the program, orruby test/cool_program_test.rb
for the tests. It would be better if we could specify those paths and abstract intotest
orrun
operations. That's whatrake
is for! This tool is a lot like GNU Make, but for Ruby.First, add it to your
Gemfile
:Then, add a new file in your project root called
Rakefile
:If you know how
make
works, this is similar (if you don't, I've got ya covered). The first line defines the default task, or what happens when you invokerake
without specifying a specific task. In this case, we just have it run thetest
task as a dependency with no block itself. This is a list, you can specify multiple tasks here.Each task below can be invoked at the command line directly - you'd use
rake run
to actually execute your program and justrake
on its own to run the test suite.Add a Linter
I've become fairly reliant on the Rubocop linter to keep me in line with the Ruby style guide. It now ships with a ready-to-go Rake task.
First, add it to your
Gemfile
:Then, modify your
Rakefile
:It's my personal preference to run the linter and the tester by default, but not fail on lint errors. Season to taste.
Optional - Add a GitHub Action
I host almost all my code on GitHub and have become a fan of GitHub Actions. Using YAML, you can have GitHub automatically run your tests whenever you commit or open a PR. Create a new file at
<project root>/.github/workflows/ruby.yml
:You can tweak each step very easily here - the commands specified will get run and if everything completes without errors, you get a green check mark. Sweet! Using
rake
allows this file to stay concise, and then you'd be able to manage changes to your structure in your Rakefile without having to worry about this file at all.Add a README and stuff
We're just about done, but you should always include a README:
Add a
.gitignore
:You should probably add a LICENSE file, too - here's the BSD-3-Clause:
At the end, your directory should look like this:
Finally,
git init && git add . && git commit -m "Initial commit"
. Happy hacking!If you don't feel a pressing need to do this from scratch, you can just use this GitHub template with the code from this post.
Photo by Jukan Tateisi on Unsplash