A small Ruby project is easier to navigate when files have clear roles.

layout Model the project layout as data first: source files, tests, and executables should each have an obvious place.

Project Layout

files
project_layout.rb
Replay: real traced execution (multi-file project)
files = ["lib/app.rb", "test/app_test.rb", "bin/app"]
source_files = files.select { |path| path.start_with?("lib/") }
test_files = files.select { |path| path.include?("test") }
bin_files = files.select { |path| path.start_with?("bin/") }
has_readme = files.include?("README.md")

puts "files=#{files.join(',')}"
puts "source_count=#{source_files.length}"
puts "test_count=#{test_files.length}"
puts "bin_count=#{bin_files.length}"
puts "has_readme=#{has_readme}"
files = ["lib/report.rb", "test/report_test.rb"]
source_files = files.select { |path| path.start_with?("lib/") }
test_files = files.select { |path| path.include?("test") }
bin_files = files.select { |path| path.start_with?("bin/") }
has_readme = files.include?("README.md")

puts "files=#{files.join(',')}"
puts "source_count=#{source_files.length}"
puts "test_count=#{test_files.length}"
puts "bin_count=#{bin_files.length}"
puts "has_readme=#{has_readme}"
files = ["lib/app.rb", "README.md"]
source_files = files.select { |path| path.start_with?("lib/") }
test_files = files.select { |path| path.include?("test") }
bin_files = files.select { |path| path.start_with?("bin/") }
has_readme = files.include?("README.md")

puts "files=#{files.join(',')}"
puts "source_count=#{source_files.length}"
puts "test_count=#{test_files.length}"
puts "bin_count=#{bin_files.length}"
puts "has_readme=#{has_readme}"
  1. files ← ["lib/app.rb", "test/app_test.rb", "bin/app"], source_files ← ["lib/app.rb"]

    1files→ ["lib/app.rb", "test/app_test.rb", "bin/app"] = ["lib/app.rb", "test/app_test.rb", "bin/app"]  #@files=["lib/report.rb", "test/report_test.rb"], ["lib/app.rb", "README.md"]2source_files→ ["lib/app.rb"] = files["lib/app.rb", "test/app_test.rb", "bin/app"].select { |path| path.start_with?("lib/") }3test_files→ ["test/app_test.rb"] = files["lib/app.rb", "test/app_test.rb", "bin/app"].select { |path| path.include?("test") }4bin_files→ ["bin/app"] = files["lib/app.rb", "test/app_test.rb", "bin/app"].select { |path| path.start_with?("bin/") }5has_readme→ false = files.include?("README.md")false67puts "files=#{files.join(',')lib/app.rb,test/app_test.rb,bin/app}"8puts "source_count=#{source_files.length1}"9puts "test_count=#{test_files.length1}"10puts "bin_count=#{bin_files.length1}"11puts "has_readme=#{has_readmefalse}"
    outputfiles=lib/app.rb,test/app_test.rb,bin/app
    source_count=1
    test_count=1
    bin_count=1
    has_readme=false
  1. files ← ["lib/report.rb", "test/report_test.rb"], source_files ← ["lib/report.rb"]

    1files→ ["lib/report.rb", "test/report_test.rb"] = ["lib/report.rb", "test/report_test.rb"]2source_files→ ["lib/report.rb"] = files["lib/report.rb", "test/report_test.rb"].select { |path| path.start_with?("lib/") }3test_files→ ["test/report_test.rb"] = files["lib/report.rb", "test/report_test.rb"].select { |path| path.include?("test") }4bin_files→ [] = files["lib/report.rb", "test/report_test.rb"].select { |path| path.start_with?("bin/") }5has_readme→ false = files.include?("README.md")false67puts "files=#{files.join(',')lib/report.rb,test/report_test.rb}"8puts "source_count=#{source_files.length1}"9puts "test_count=#{test_files.length1}"10puts "bin_count=#{bin_files.length0}"11puts "has_readme=#{has_readmefalse}"
    outputfiles=lib/report.rb,test/report_test.rb
    source_count=1
    test_count=1
    bin_count=0
    has_readme=false
  1. files ← ["lib/app.rb", "README.md"], source_files ← ["lib/app.rb"]

    1files→ ["lib/app.rb", "README.md"] = ["lib/app.rb", "README.md"]2source_files→ ["lib/app.rb"] = files["lib/app.rb", "README.md"].select { |path| path.start_with?("lib/") }3test_files→ [] = files["lib/app.rb", "README.md"].select { |path| path.include?("test") }4bin_files→ [] = files["lib/app.rb", "README.md"].select { |path| path.start_with?("bin/") }5has_readme→ true = files.include?("README.md")true67puts "files=#{files.join(',')lib/app.rb,README.md}"8puts "source_count=#{source_files.length1}"9puts "test_count=#{test_files.length0}"10puts "bin_count=#{bin_files.length0}"11puts "has_readme=#{has_readmetrue}"
    outputfiles=lib/app.rb,README.md
    source_count=1
    test_count=0
    bin_count=0
    has_readme=true