Setting Up A Fresh Ruby Project
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.
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.
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.
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 called Gemfile.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 calling Object.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 do my_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!
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.
Now, we could just direct users to invoke ruby themselves on the proper files - ruby lib/cool_program.rb to run the program, or ruby test/cool_program_test.rb for the tests. It would be better if we could specify those paths and abstract into test or run operations. That’s what rake 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 invoke rake without specifying a specific task. In this case, we just have it run the test 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 just rake on its own to run the test suite.
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.
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.
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