Appendix A: Ruby Project Lifecycle
en/appendix_a_project_lifecycle
merged appendix page
Ruby Project Lifecycle and Core Tooling ๏ธ
Why this appendix exists ๐ก
A student can understand Ruby syntax and still feel lost when working in a real project. The missing knowledge is often not "more language features." It is the operational flow around the language:
- Which command comes first?
- How do I know which Ruby version I am using?
- How do I install dependencies safely?
- Why do some projects use
bundle execeverywhere? - How do I look up documentation without opening a browser?
- When should I care about documentation generators, linters, task runners, and debuggers?
This appendix teaches Ruby tools through the story of a real project lifecycle, from "I have an empty directory" to "I am working in repeated sprint cycles with a maintainable codebase."
Main learning outcomes ๐ฏ
By the end of this appendix, students should be able to:
- explain the roles of
ruby,gem,bundle,ri, andrbenv; - start a Ruby project in a reproducible way;
- understand when to use
gem installversusbundle add; - run Ruby code directly from the command line and check syntax quickly;
- use
rifor local API lookup during development; - understand where
rake,rubocop,rdoc,yard, andrdbgfit in project life; - troubleshoot common environment problems without guessing blindly.
Teaching philosophy ๐งญ
This appendix does not teach tools as an alphabetical catalog.
It teaches them in the order a real developer tends to need them:
- choose the Ruby version;
- confirm the interpreter works;
- create the project;
- add dependencies;
- start the test loop;
- look up docs while coding;
- automate repeated tasks;
- keep style and docs consistent;
- debug runtime behavior;
- troubleshoot environment drift.
That order matters. When students learn tools in project order, the purpose of each tool becomes obvious.
Files in this appendix ๐๏ธ
story.md: the detailed project-life-cycle narrativecheatsheet.md: commands in first-use ordersprint_flow.md: how the tools fit into daily sprint worktroubleshooting.md: common failures and diagnostic orderaddons.md: tools that are useful later, after the basics are stable
What this appendix is not ๐ซ
It is not:
- a full RubyGems manual;
- a complete Bundler reference;
- a shell tutorial;
- a replacement for official docs.
It is a practical survival guide for students moving from "I can write Ruby" to "I can work inside a Ruby project responsibly."
The Ruby Project Lifecycle Story
Stage 0: Before the project exists ๐
Before a Ruby project has code, it already has one invisible dependency: the Ruby interpreter itself.
If the wrong Ruby version is active, every later step becomes unstable:
- gems may install into the wrong location;
- native extensions may fail;
- scripts may behave differently;
- your machine may not match the project's intended environment.
This is why project lifecycle starts with the runtime, not with source files.
Tools introduced here
rubywhichrbenv
Commands
ruby -v
which ruby
rbenv versions
rbenv local 3.4.8
rbenv which rubybash
What each command tells you
ruby -v
- shows the active Ruby version
- use this whenever a project expects a specific version
which ruby
- shows which executable your shell will actually run
- this is critical when version managers are involved
rbenv versions
- lists installed versions and shows which one is active
rbenv local 3.4.8
- writes the local project version
- this means "when I am in this directory, use Ruby 3.4.8"
rbenv which ruby
- tells you exactly which Ruby binary
rbenvresolved
Real-life situation
You clone a Ruby project and bundle install fails with a strange native extension error. A common cause is not the gem itself. The common cause is that your shell is using the wrong Ruby.
So the first debugging question is not:
- "Why is Bundler broken?"
It is:
- "Which Ruby am I actually using?"
That is why version management comes first.
Stage 1: Try Ruby before creating the project ๐งช
Before making a project skeleton, verify that the interpreter and shell workflow are working. This keeps environment issues separate from project issues.
Tools introduced here
rubyirb
Commands
ruby -e 'puts "hello from ruby"'
ruby -e 'puts [1, 2, 3].map { |n| n * 2 }.inspect'
irbbash
Why this stage matters
ruby -e is a fast smoke test:
- the interpreter runs
- the shell quoting works
- you can evaluate small expressions quickly
irb is your live Ruby scratchpad:
- test an expression
- inspect how a method behaves
- experiment before editing a file
Real-life situation
You are unsure whether String#gsub or Array#zip behaves the way you remember. Instead of guessing or editing production code blindly, you can use irb for quick validation.
Example:
irb
irb(main):001> %w[Ana Bob].zip([88, 76])
=> [["Ana", 88], ["Bob", 76]]ruby
That is a real daily workflow, not a beginner trick.
Stage 2: Create the project ๐
Now that Ruby itself works, create the project directory and initialize dependency management immediately.
Tools introduced here
bundle
Commands
mkdir my_ruby_project
cd my_ruby_project
bundle initbash
What happens here
bundle init
- creates a
Gemfile - marks the project as a dependency-managed Ruby project
This is one of the most important habits in Ruby work:
- do not start by installing random gems globally and hoping the project will work later
- start by declaring project dependencies
Real-life situation
If you skip Bundler and only run gem install rspec, your machine may work, but a teammate's machine might not. Bundler is what turns "my machine" into "the project environment."
Stage 3: Run files and check syntax โถ๏ธ
After the project exists, you need a few commands for direct file execution and fast feedback.
Commands
ruby app.rb
ruby -c app.rb
ruby -Ilib script.rbbash
Why these matter
ruby app.rb
- run a Ruby file directly
ruby -c app.rb
- check syntax without running the program
- very useful when debugging syntax errors quickly
ruby -Ilib script.rb
- add directories to the load path
- useful in small scripts where you want
requireto find local project files
Real-life situation
A student changes several methods and now gets a syntax error. They do not need the whole test suite to discover that. ruby -c gives a fast answer before deeper testing.
Stage 4: Add dependencies the project way ๐ฆ
Now the project needs libraries.
Tools introduced here
gembundle
Core idea
There are two separate concerns:
- the machine-level gem system
- the project's declared dependency set
Students must learn the difference.
Machine-level commands
gem -v
gem list
gem env
gem which rakebash
These help you inspect the RubyGems environment.
Project-level commands
bundle add rspec
bundle install
bundle info rspecbash
What these mean
bundle add rspec
- adds the gem to the project's
Gemfile - preferred over random global installation for project dependencies
bundle install
- resolves and installs dependencies for the current project
bundle info rspec
- shows where Bundler resolved the gem from
Real-life situation
Suppose csv works on one machine and not another. A student might think:
- "Ruby is inconsistent."
But the real question is:
- "Was
csvdeclared for the project, or was it only present on one machine?"
That is exactly the kind of confusion Bundler is meant to prevent.
Stage 5: Start the first test loop โ
This is the moment the project becomes real development work.
Commands
bundle exec rspec
bundle exec rspec spec/my_spec.rb
bundle exec rspec spec/my_spec.rb:12bash
Why bundle exec matters
bundle exec
- ensures the command runs inside the project's dependency context
- avoids accidentally using a gem version from outside the project
Students often resist bundle exec early because it feels repetitive. It is worth teaching early because it solves a real project problem.
Real-life situation
You have multiple versions of RSpec installed across projects. Running rspec directly might use the wrong executable. Running bundle exec rspec uses the project's declared dependency resolution.
That is not stylistic preference. That is environment correctness.
Stage 6: Use documentation while coding ๐
Once sprint work begins, students need fast ways to look up Ruby APIs.
Tools introduced here
ri
Commands
ri Array#map
ri Enumerable#reduce
ri String#gsub
ri Filebash
Why ri matters
ri is the local documentation reader for Ruby APIs.
It is useful because:
- it is fast
- it works without opening a browser
- it reinforces the habit of looking up behavior precisely
Real-life situation
A student knows map exists but forgets whether reduce needs an initial value or what String#gsub returns. ri gives the answer in the middle of implementation, which is how professionals actually use docs.
Stage 7: Turn repeated commands into project tasks ๐
Once a project has a repeated workflow, raw shell commands are no longer enough.
Tools introduced here
rake
Commands
bundle exec rake -T
bundle exec rakebash
Why rake matters
rake is Ruby's traditional task runner.
Use it when a project has repeated actions such as:
- running test suites
- generating docs
- cleaning build artifacts
- seeding local data
- custom project tasks
Real-life situation
A team keeps telling everyone:
- "Run these four commands in this exact order."
That is usually a sign the project wants a task runner.
Stage 8: Keep style consistent โจ
As the codebase grows, readability and consistency need automation.
Tools introduced here
rubocop
Commands
bundle exec rubocop
bundle exec rubocop -Abash
Why rubocop matters
rubocop helps teams:
- apply consistent style
- catch some simple smells
- reduce code-review noise about formatting
It is not a substitute for design review, but it is useful because it automates repetitive feedback.
Real-life situation
Without a formatter/linter, code review gets filled with:
- spacing changes
- quote-style debates
- layout arguments
That wastes human attention that should be spent on logic and design.
Stage 9: Document the project for humans ๐
Once code is shared, others need more than passing tests. They need readable API docs.
Tools introduced here
rdocyard
Commands
rdoc
yard doc
yard server --reload
yard stats --list-undocbash
Difference between ri, rdoc, and yard
ri
- read local Ruby docs
rdoc
- generate documentation from Ruby source comments
yard
- a widely used Ruby documentation tool with richer project-doc workflows
Why this stage comes later
Students should first understand:
- how to write code
- how to run tests
- how to use docs
Only then does it make sense to ask them to generate and maintain docs for others.
Real-life situation
A service object is being reused across several scripts. Passing tests prove it works, but they do not explain:
- expected input shape
- return structure
- side effects
That is where documentation tools become practical.
Stage 10: Debug execution, not just source code ๐
As projects grow, printed output is sometimes not enough.
Tools introduced here
rdbg
Commands
rdbg app.rb
rdbg -c -- bundle exec rspecbash
Why rdbg matters
A debugger helps when:
- recursion behaves unexpectedly
- database state differs from expectations
- a closure captures the wrong value
- a test passes data through too many layers to inspect easily with
puts
Real-life situation
A recursive traversal duplicates some paths only in one edge case. Adding print statements everywhere becomes noisy. A debugger lets you inspect the call stack and current values more precisely.
Stage 11: Mature project add-ons ๐ณ
After the core lifecycle is stable, students may meet supporting tools such as:
simplecovbundler-auditruby-lspsolargraph
These are important, but they are not the first tools a student should learn.
They belong after the core project loop is already understood.
Sprint Flow: How These Tools Fit Daily Work
The repeated loop ๐
Once a Ruby project is alive, the daily loop is usually:
- confirm the environment
- install or sync dependencies if needed
- run one test or one spec file
- change code
- re-run the tests
- look up Ruby behavior when uncertain
- lint or format before finishing
That loop is where the tools stop being "commands to memorize" and become part of real project practice.
A realistic sprint example ๐งช
Imagine you are implementing a topic exercise or a new project feature.
Step 1: Confirm the runtime
ruby -v
which rubybash
Why:
- avoids working for 20 minutes in the wrong Ruby version
Step 2: Sync dependencies
bundle installbash
Why:
- ensures your project dependencies match the
Gemfileand lockfile
Step 3: Run only the relevant tests
bundle exec rspec spec/my_spec.rbbash
Why:
- faster feedback
- easier focus on one problem at a time
Step 4: Inspect docs mid-implementation
ri Enumerable#filter_mapbash
Why:
- lets you answer one concrete question without leaving your flow
Step 5: Check syntax fast if needed
ruby -c lib/my_class.rbbash
Why:
- useful if the failure looks like a syntax issue rather than a logic issue
Step 6: Run the linter before considering the work finished
bundle exec rubocopbash
Why:
- reduce avoidable review comments
When rake enters the sprint loop ๐ ๏ธ
If the project has repeatable workflows, a team often stops writing raw commands in README files and starts formalizing them as tasks.
Examples:
bundle exec rake testbundle exec rake docsbundle exec rake setup
That is a sign the project is maturing operationally.
When rdbg enters the sprint loop ๐
Use the debugger when:
- the failing state is deep in recursion;
- you need to inspect intermediate values;
- print debugging is becoming messy;
- a query result, block, or lambda is behaving unexpectedly.
In those cases, rdbg is not advanced decoration. It is a time-saving inspection tool.
Project Lifecycle Cheatsheet โก
1. Check the runtime first ๐
ruby -v
which ruby
rbenv versions
rbenv local 3.4.8
rbenv which rubybash
2. Try Ruby quickly ๐งช
ruby -e 'puts "hello"'
ruby -e 'puts [1, 2, 3].map { |n| n * 2 }.inspect'
irbbash
3. Create the project ๐
mkdir my_ruby_project
cd my_ruby_project
bundle initbash
4. Run files and syntax-check โถ๏ธ
ruby app.rb
ruby -c app.rb
ruby -Ilib script.rbbash
5. Add dependencies ๐ฆ
bundle add rspec
bundle install
bundle info rspecbash
6. Inspect gem environment ๐
gem -v
gem list
gem env
gem which rakebash
7. Start the test loop โ
bundle exec rspec
bundle exec rspec spec/my_spec.rb
bundle exec rspec spec/my_spec.rb:12bash
8. Read docs while coding ๐
ri Array#map
ri Enumerable#reduce
ri String#gsub
ri Filebash
9. Use project tasks ๐
bundle exec rake -T
bundle exec rakebash
10. Keep style consistent โจ
bundle exec rubocop
bundle exec rubocop -Abash
11. Generate docs ๐
rdoc
yard doc
yard server --reload
yard stats --list-undocbash
12. Debug runtime behavior ๐
rdbg app.rb
rdbg -c -- bundle exec rspecbash
Troubleshooting Guide
The most important rule โ ๏ธ
Do not guess randomly.
Check the environment in a fixed order.
Diagnostic order ๐ฉบ
- Which Ruby is active?
- Which executable is the shell using?
- Is the dependency declared for the project?
- Did you run the command through Bundler?
- Is the gem installed but not available on
PATH? - Is there a native extension or default-gem packaging problem?
Problem: wrong Ruby version ๐ข
Symptoms:
- gem install path looks strange
- native gems fail unexpectedly
- project works in one terminal tab but not another
Check:
ruby -v
which ruby
rbenv versions
rbenv which rubybash
Interpretation:
- if
ruby -vdoes not match the project expectation, fix the version first
Problem: gem command works, project command fails ๐ฆ
Symptoms:
gem list rspecshows RSpecbundle exec rspecstill fails
Check:
bundle info rspec
bundle installbash
Interpretation:
- the gem may exist globally but not be resolved for the project
Problem: executable not found ๐ซ
Symptoms:
bundleorrubocoporyardis "not found"
Check:
which bundle
gem envbash
Interpretation:
- the gem may be installed, but the executable directory is not on
PATH - or the version manager shell integration is incomplete
Problem: Ruby says a standard library feature is missing ๐งฉ
Symptoms:
cannot load such file -- csvcannot load such file -- erb
Interpretation:
Recent Ruby versions may package some formerly-default pieces as separately installed gems.
What to do:
- add the dependency to the project
Gemfile - install it through Bundler or the project bootstrap
Problem: native extension build failure ๐๏ธ
Symptoms:
- gems like
sqlite3fail while building - compiler or header errors appear
Check:
gem env
ruby -v
pkg-config --modversion sqlite3bash
Interpretation:
- often caused by missing system headers or a mismatched Ruby environment
Problem: command works outside the project but fails inside it ๐งญ
Symptoms:
ruby -eworks- project scripts fail
Interpretation:
- the issue is likely project dependency resolution, not the Ruby interpreter itself
Check:
bundle install
bundle exec rspecbash
Problem: documentation command does not show what you expect ๐
Symptoms:
rioutput looks sparseyarddocs are incomplete
Interpretation:
rireads installed docs for Ruby/core APIsyarddepends on comment quality in your project
In other words:
riis for consuming docsyardis for publishing docs
Add-On Tools and Why They Matter Later
These tools are valuable, but they are not first-line tools for a beginner. Students should meet them after the core Ruby project loop is already familiar.
simplecov ๐
Use when:
- the team wants test coverage reports
Why it matters:
- helps identify untested areas
Why it comes later:
- coverage is useful only after students can already run and trust tests
bundler-audit ๐
Use when:
- the project needs dependency vulnerability checks
Why it matters:
- dependency security becomes part of real project maintenance
Why it comes later:
- students first need to understand ordinary dependency management
ruby-lsp or solargraph ๐ง
Use when:
- editor integration matters more
- students want inline hover docs, completion, and navigation
Why they matter:
- improve day-to-day editing experience
Why they come later:
- editor tooling should support understanding, not replace it
reek ๐
Use when:
- a team wants smell-oriented feedback beyond formatting
Why it matters:
- encourages design conversation
Why it comes later:
- students should first learn the language and project flow before smell taxonomy
brakeman ๐ก๏ธ
Use when:
- the project uses Rails
Why it matters:
- security scanning for Rails applications
Why it comes later:
- not relevant to every Ruby project
The broader lesson ๐งญ
Ruby projects grow in layers:
- runtime
- project setup
- dependencies
- tests
- docs and style
- debugging
- ecosystem support tools
Students should know that these add-ons exist, but they should not be buried under too many tools before the core workflow feels natural.