Ruby for Java Developers: A Test-Driven Guide to This Repository
Ruby TDD Guide
en/ruby_tdd_guide_for_java_developers.md
I wrote this guide for Java developers using this repository as a course, not as a generic Ruby handout. At the same time, I do not want that title to scare anyone away. If you are coming from another language, you can still use this course well. I use Java as a comparison point because it helps me explain certain Ruby ideas clearly.
The repository now contains fifteen topics, two appendices, runnable topic tests, and answer files kept outside the normal exercise flow. That means I can teach Ruby here as a real learning path rather than as a short workshop.
Why I Wrote The Guide This Way
I am not trying only to teach Ruby syntax. I am trying to teach how Ruby code is shaped, how tests help shape it, and how your instincts may need to change as the problems become more idiomatic.
If you want the shortest orientation, start with README.md. If you want the course map, read course_overview.md. I wrote this guide to sit between those two. It explains how I expect you to move through the repository and what mindset shifts matter most along the way.
Who I Had In Mind
When I wrote this guide, I assumed:
- you can already read Java comfortably
- you understand basic object-oriented programming
- you have written or read unit tests before
It does not assume prior Ruby experience.
If you already know another dynamic language, some of the syntax will feel familiar. The design questions will still matter.
What This Repository Actually Contains
The English course lives under the en/ directory and is organized into fifteen topics:
topic_01_ruby_basicstopic_02_methods_keywords_blockstopic_03_collections_enumerabletopic_04_strings_symbols_ranges_regextopic_05_control_nil_exceptionstopic_06_classes_modules_compositiontopic_07_duck_typing_polymorphismtopic_08_ruby_specific_featurestopic_09_mini_capstonetopic_10_rock_paper_scissorstopic_11_csv_files_queriestopic_12_sqlite_queriestopic_13_recursion_closurestopic_14_functional_style_lambdastopic_15_reduce_accumulators
There are also two appendices:
appendix_a_project_lifecycleappendix_b_vscode_ruby_workflow
Each topic directory uses the same basic shape:
overview.mdshortnote.mdcheatsheet.mdworked_examples.mdguide.mdexample.rbbasic_exercise.rbadv_exercise.rbanswer_basic_exercise.rbanswer_adv_exercise.rbtests/run_topic_tests.sh
That consistency matters. I do not want you to spend energy rediscovering the structure in every topic. I want you to spend that energy on the code.
How To Run The Course
From the en/ directory, run the full course:
./run_tests.shbash
Run a single topic from the course root:
./run_tests.sh topic_01_ruby_basicsbash
Or run a topic with its own runner:
./topic_01_ruby_basics/run_topic_tests.shbash
The root runner checks for the gems the repository needs and installs them if they are missing. At the moment that includes erb, csv, sqlite3, and rspec.
By the time you reach CSV and SQLite, you are no longer studying only language features. You are also working with the shape of a small Ruby project, and I want the tooling to stay easy enough that the design questions remain visible.
How I Recommend You Study One Topic
A good order looks like this:
- Read
overview.md. - Read
shortnote.md. - Study
worked_examples.md. - Keep
cheatsheet.mdopen while you read the Ruby files. - Inspect
example.rb. - Run the topic tests.
- Complete
basic_exercise.rb. - Complete
adv_exercise.rb. - Open the answer files only after making a real attempt.
That order matters. If you skip straight to the code, you often miss the design question I am trying to teach. If you skip straight to the answer, you lose the chance to feel where the design pressure really is.
The TDD Rhythm I Want You To Keep
The whole repository is built around a small, repeatable loop:
- Write or inspect a failing expectation.
- Write the smallest code that makes it pass.
- Refactor for clarity.
Java developers often understand this loop in principle, but still trust the implementation more than the test. Ruby usually rewards the opposite habit. Let the test keep the design small.
If a spec is awkward to write, I want you to treat that as information. The object may be doing too much. The names may be muddy. The collaborator boundary may be in the wrong place.
How The Fifteen Topics Build On One Another
The course is now large enough that I think in phases rather than isolated lessons.
Phase 1: Foundations In Ruby Thinking
Topics 1 through 5 teach the early mental shifts:
- expressions instead of ceremony
- methods and keyword arguments
Enumerableand collection transformations- strings, symbols, ranges, and regex
- guard clauses, nil safety, and exceptions
This is where Java habits show up most clearly. Many learners still write Ruby as though they are trying to satisfy a compiler. In this phase, the most useful question is not "Can I make this shorter?" but "Can I make the intent easier to see?"
Phase 2: Object Design In Ruby
Topics 6 through 9 move into object boundaries and collaboration:
- classes, modules, and composition
- duck typing and polymorphism
- dynamic Ruby features used with restraint
- a small capstone that pulls the earlier ideas together
Here I start asking a more interesting question: not only what Ruby can express, but where behavior should live.
Phase 3: Applied Ruby
Topics 10 through 12 put Ruby to work on small applied problems:
- iterative game design
- CSV workflows and small query services
- SQLite operations, queries, and prepared statements
These topics matter because they force the language into contact with state, files, input formats, and persistence. A learner who was comfortable in the early topics now has to keep the same discipline while dealing with more moving parts.
Phase 4: Higher-Level Ways Of Thinking
Topics 13 through 15 move into more abstract problem solving:
- recursion and closures
- functional-style pipelines with
map,zip, and lambdas - accumulator-driven design with
reduceandeach_with_object
By this point, I want you to be moving beyond recognition into fluency. You should be able to read a transformation and see not only what it does, but why that form was chosen.
The Main Java-To-Ruby Shifts
The hardest part of Ruby for a Java developer is rarely syntax. It is taste.
The recurring shifts look like this:
- prefer behavior-oriented names over type-oriented names
- prefer expressions over ceremony
- prefer built-in collection behavior over manual loops
- prefer composition over inheritance unless inheritance earns its keep
- prefer collaborators that can do the job over collaborators from the "right" hierarchy
- prefer concise code only when the names are carrying the meaning
A quick orientation map still helps:
| Java | Ruby |
|---|---|
Static typing (String name) |
Dynamic typing (name = "A") |
public class User {} |
class User ... end |
| getter/setter boilerplate | attr_reader, attr_accessor |
List<String> |
Array |
Map<K,V> |
Hash |
stream().map() |
map |
| interfaces | duck typing and modules |
| checked exceptions | no checked exceptions |
null |
nil |
I use that table for orientation only. If you ask only for equivalents, you will miss the more important question: what is the clearest Ruby way to model this idea?
Habits I Want You To Watch For
These habits often hurt Java developers in this course:
- turning every attribute into a getter and setter
- building inheritance trees before a simple collaborator would do
- writing manual loops instead of learning
Enumerable - treating every utility as a class method
- over-mocking tests instead of clarifying the design
- confusing shorter code with better code
Most of the course is really a long conversation with those habits.
How I Want You To Use The Answer Files
The answer files are intentionally separate from the normal runner flow. The tests use:
example.rbbasic_exercise.rbadv_exercise.rb
They do not use:
answer_basic_exercise.rbanswer_adv_exercise.rb
That separation is deliberate. I do not want the answer files to rescue you from the exercise too early. I want them to sharpen your judgment after you have struggled a little.
When you read an answer file, ask:
- Is the naming clearer than mine?
- Is the control flow simpler?
- Did the solution make the object boundary easier to see?
- Did it become elegant, or merely short?
If you use the answers that way, they become part of the course. If you use them too early, they become a way to avoid the course.
Why I Included The Appendices
Appendix A is for the operational side of Ruby work: tools, project lifecycle, and the habits around a working Ruby environment.
Appendix B is for learners and teachers who want a calmer, more visual workflow inside VS Code.
I do not see either appendix as extra material. Learning Ruby in a repository like this is not only about expressions and objects. It is also about learning how Ruby projects are actually worked on.
A Good Working Strategy
If you want a sensible route through the repository, I suggest this:
- Work topics 1 through 5 in order without skipping.
- Slow down for topics 6 through 9, because the design questions get richer.
- Treat topics 10 through 12 as applied programming, not just language study.
- Take topics 13 through 15 slowly enough to read the transformations aloud.
If you are teaching, I would give the same advice. The course is strongest when learners stay in one topic long enough to discuss the shape of the code, not merely its correctness.
Final Advice
Treat Ruby as a different language, not as Java with less punctuation.
This repository is now broad enough to teach more than a beginner syntax pass. I want it to teach how Ruby feels across foundations, object design, applied programming, and more abstract transformations. The quiet habit that matters all the way through is still the same: make a small claim, test it, make it pass, and then clean up the code until the design is visible.