Layer Checker
This project was made with a little help of vibe-coding.
A Ruby gem to validate architectural layer dependencies in your projects based on YAML configuration files.
Installation
Add this line to your application's Gemfile:
gem 'layer-checker'
And then execute:
bundle install
Or install it yourself as:
gem install layer-checker
Usage
1. Create a Configuration File
Create a project_layers.yml file in your project root:
version: 1
modules:
controller:
paths:
- app/controllers/**
depends_on:
- service
- presenter
service:
paths:
- app/services/**
depends_on:
- model
model:
paths:
- app/models/**
depends_on: []
presenter:
paths:
- app/presenters/**
depends_on: []
options:
fail_on_violation: true
unassigned_behavior: warn
allow_external_constants:
- ActiveRecord::Base
- ApplicationController
2. Run the Checker
Command Line
layer_checker
With options:
layer_checker --config custom_config.yml --format json
In Rails (Rake Task)
rake layer_checker:check
With environment variables:
CONFIG=custom_config.yml FORMAT=json rake layer_checker:check
Programmatically
require 'layer_checker'
checker = LayerChecker::Checker.new(
config_path: 'project_layers.yml',
project_root: Dir.pwd
)
result = checker.check
checker.report(format: :console)
if result[:success]
puts "All good!"
else
puts "Found #{result[:violations].size} violations"
end
Configuration
Module Structure
Simple Modules
modules:
controller:
paths:
- app/controllers/**
depends_on:
- service
Nested Modules (DDD Style)
modules:
billing:
modules:
domain:
paths:
- app/billing/domain/**
depends_on: []
application:
paths:
- app/billing/application/**
depends_on:
- domain
infrastructure:
paths:
- app/billing/infrastructure/**
depends_on:
- application
- domain
Feature-Based Modules
modules:
authentication:
modules:
controller:
paths:
- app/authentication/controllers/**
depends_on:
- service
service:
paths:
- app/authentication/services/**
depends_on:
- model
model:
paths:
- app/authentication/models/**
depends_on: []
Options
fail_on_violation(boolean, default:false): Exit with error code 1 if violations are foundunassigned_behavior(string, default:warn): How to handle files that don't belong to any modulewarn: Just warn about unassigned filesfail: Treat unassigned files as violationsignore: Ignore unassigned files
allow_external_constants(array, default:[]): List of external constants that are allowed (e.g., Rails framework classes)
Examples
See the examples/ directory for complete configuration examples:
- conventional-layer.yml: Traditional MVC layered architecture
- ddd-layer.yml: Domain-Driven Design with nested modules
- featured-layer.yml: Feature-based architecture
How It Works
- Load Configuration: Parses the YAML file to understand your architecture
- Scan Code: Finds all Ruby files in your project
- Extract Dependencies: Uses AST parsing to detect:
- Constant references (e.g.,
UserService,User::Profile) - Method calls (e.g.,
UserService.new) - Class inheritance (e.g.,
class Controller < ApplicationController)
- Constant references (e.g.,
- Validate: Checks if each dependency is allowed according to your configuration
- Report: Shows violations with file locations and line numbers
Output Formats
Console (Default)
================================================================================
Layer Checker Results
================================================================================
✗ Found 2 violation(s)
Violations found:
controller:
app/controllers/users_controller.rb:15
→ controller cannot depend on model
→ Referenced: User
service:
app/services/billing_service.rb:23
→ service cannot depend on presenter
→ Referenced: InvoicePresenter
================================================================================
Summary:
Total violations: 2
Modules affected: 2
================================================================================
JSON
{
"success": false,
"message": "Found 2 violation(s)",
"violations": [
{
"source_file": "app/controllers/users_controller.rb",
"source_module": "controller",
"target_constant": "User",
"target_module": "model",
"line_number": 15,
"violation_type": "forbidden_dependency"
}
],
"summary": {
"total_violations": 2,
"modules_affected": 2
}
}
CLI Options
Usage: layer_checker [options]
-c, --config PATH Path to config file (default: project_layers.yml)
-p, --project PATH Project root directory (default: current directory)
-f, --format FORMAT Output format: console or json (default: console)
-h, --help Show this help message
-v, --version Show version
Integration with CI/CD
Add to your CI pipeline:
# .github/workflows/ci.yml
- name: Check Layer Architecture
run: bundle exec layer_checker
Or with Rake:
- name: Check Layer Architecture
run: bundle exec rake layer_checker:check
Set fail_on_violation: true in your config to fail the build on violations.
Development
After checking out the repo, run:
bundle install
To build the gem:
gem build layer_checker.gemspec
To install locally:
gem install ./layer-checker-0.1.0.gem
Contributing
Bug reports and pull requests are welcome on GitHub.
License
The gem is available as open source under the terms of the MIT License.