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 found
  • unassigned_behavior (string, default: warn): How to handle files that don't belong to any module
    • warn: Just warn about unassigned files
    • fail: Treat unassigned files as violations
    • ignore: 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:

How It Works

  1. Load Configuration: Parses the YAML file to understand your architecture
  2. Scan Code: Finds all Ruby files in your project
  3. 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)
  4. Validate: Checks if each dependency is allowed according to your configuration
  5. 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.