Architecture testing for Ruby. Part of ArchUnitEverything — one architecture-testing library per language.
Early development. Nothing to install yet.
Siblings: ArchUnitTS · ArchUnitPython
ArchUnitRuby analyzes a Ruby project as a directed dependency graph. The finished library will let teams express architecture rules as ordinary RSpec or Minitest tests, keeping dependency direction, layers, cycles, naming conventions, diagrams, and metrics executable in CI.
ArchUnitRuby is a working extraction prototype, not a released end-user library yet. The full source-to-graph path and the first immutable file-rule builder stages run today.
| Capability | Status |
|---|---|
Project discovery through a directory, Gemfile, or gemspec |
Working |
| Ruby source enumeration with configurable exclusions | Working |
Static require, require_relative, autoload, and load extraction |
Working |
Inline and next-line # archunit: ignore directives |
Working |
| Internal and external dependency classification | Working |
| Self-edges and parallel-edge merging | Working |
| Immutable graph values and graph caching | Working |
Immutable file selectors and should / should_not moods |
Working |
| File, layer, slice, metric, and graph-report rules | Planned |
| RSpec and Minitest assertion helpers | Planned |
| RubyGems installation | Not published yet |
The implementation has a growing RSpec suite and is tested on Ruby 3.3, 3.4, and 4.0 on Linux, plus Ruby 4.0 on Windows.
Requirements: Ruby 3.3 or newer and Bundler.
git clone https://github.com/LukasNiessen/ArchUnitRuby.git
cd ArchUnitRuby
bundle install
bundle exec rakeThe currently available API exposes the extracted graph directly:
require 'archunit'
graph = ArchUnit::Extraction.extract_graph(
'/path/to/project',
exclude_patterns: ['vendor', 'tmp', '**/*_generated.rb']
)
graph.each do |edge|
puts "#{edge.source} -> #{edge.target} (external: #{edge.external})"
endThe file-rule builder can already create and branch immutable scopes. Predicates and check are
the next backlog items, so these examples deliberately stop at the mood stage:
base = ArchUnit.project_files('/path/to/project')
.in_folder('lib/**')
.with_name('*.rb')
positive_rule = base.should
negative_rule = base.should_notGraph extraction is cached because a real test suite evaluates many rules against the same project.
Force one fresh extraction with CheckOptions, or clear every cached graph globally:
options = ArchUnit::CheckOptions.new(clear_cache: true)
graph = ArchUnit::Extraction.extract_graph('/path/to/project', options: options)
ArchUnit.clear_graph_cacheArchUnitRuby uses Prism, Ruby's official parser, and never executes the analyzed source. It records dependencies whose targets can be read statically.
| Ruby form | Import kind |
|---|---|
require 'json' |
:require |
require_relative '../models/user' |
:require_relative |
autoload :User, 'models/user' |
:autoload |
load 'config/setup.rb' |
:load |
Literal imports are resolved using Ruby's feature resolution rules. Project files use normalized, project-relative identifiers; standard-library and third-party dependencies retain the module name written in source. Files Prism cannot parse are skipped without aborting the project scan.
Ruby can compute dependency names dynamically, so calls such as require dependency_name or
require "plugins/#{name}" cannot be resolved reliably without executing application code. They
are deliberately omitted rather than guessed.
Known compatibility imports can be suppressed inline or on the immediately preceding line. Add module names to scope a directive instead of hiding every import on that line:
require 'legacy/client' # archunit: ignore legacy/client
# archunit: ignore experimental/plugin
require 'experimental/plugin'The public rule-building API is under development. Its intended shape is an English sentence read from left to right:
# Preview only — this fluent API is not implemented yet.
rule = project_files
.in_folder('app/api/**')
.should_not
.depend_on_files
.in_folder('app/database/**')
expect(rule).to passRules will be immutable values. Building a rule will do no filesystem work; the terminal check will perform extraction and return structured violations rather than raising for architecture failures.
The ArchUnitRuby RAG test repository is an executable layered retrieval-augmented-generation fixture. It contains realistic dependencies, two intentional architecture violations, application tests, architecture extraction tests, and its own cross-platform CI workflow.
The fixture proves the current prototype end to end: project discovery, source enumeration, import resolution, graph assembly, internal/external classification, caching, and deliberate violations.
Ruby packages are distributed through RubyGems rather than PyPI. The archunit gem name is not
published yet, so there are no meaningful package-download statistics today. After the first release:
- RubyGems will report total and per-version downloads.
- ClickGems will provide PePy-style download charts over time, including version, Ruby version, system, and country breakdowns.
- A RubyGems total-download badge can be enabled with
https://img.shields.io/gem/dt/archunit.
Counts begin with the first RubyGems publication; GitHub clones are separate and are visible only to repository maintainers through GitHub traffic insights.
bundle exec rspec # specifications
bundle exec rubocop # style and static checks
bundle exec rake # both
gem build archunit.gemspecCI runs compatibility tests on Ruby 3.3, 3.4, and 4.0 across Ubuntu and Windows. A single Ruby 4.0 Ubuntu quality job enforces randomized specs, 98% line and 90% branch coverage, RuboCop, gem build, and installation from the built artifact. A separate job runs the public RAG fixture against the exact revision under test. Weekly Dependabot checks cover Bundler and GitHub Actions dependencies. There is no automatic release or documentation deployment yet.
The project follows the conventions in AGENTS.md; Ruby idioms win where a sibling
language's design does not fit naturally.
The build backlog lives in GitHub Issues. Extraction is complete through issue #12. Projection is complete through issue #15, including standard edge mappers, evidence-preserving relabeling, node views, and Tarjan/Johnson cycle detection. The Files API has immutable selectors and its two moods through issue #17.
Not implemented yet:
- file-rule predicates and terminal checks;
- the fluent layer, slice, metric, and graph-report APIs;
- architecture assertions over the projected graph;
- RSpec's
passmatcher and Minitest'sassert_passeshelper; - RubyGems publication and stable installation instructions;
- diagram validation, reporting, logging, and metrics.
Until those pieces land, treat the gem as an actively developed prototype and use the direct graph API only for experimentation.