Skip to content

Commit c9816e6

Browse files
committed
add zeitwerk
1 parent 56e40d8 commit c9816e6

File tree

6 files changed

+93
-16
lines changed

6 files changed

+93
-16
lines changed

.rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,4 @@ Style/HashSyntax:
120120

121121
Gemspec/DevelopmentDependencies:
122122
Enabled: true
123-
EnforcedStyle: gemspec
123+
EnforcedStyle: Gemfile

Gemfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
11
source 'https://rubygems.org'
22

33
gemspec
4+
5+
gem 'debug'
6+
gem 'packwerk'
7+
gem 'railties'
8+
gem 'rake'
9+
gem 'rspec'
10+
gem 'rubocop'
11+
gem 'rubocop-gusto', '~> 10.0'
12+
gem 'sorbet'
13+
gem 'tapioca'

code_ownership.gemspec

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,5 @@ Gem::Specification.new do |spec|
3030
spec.add_dependency 'code_teams', '~> 1.0'
3131
spec.add_dependency 'packs-specification'
3232
spec.add_dependency 'sorbet-runtime', '>= 0.5.11249'
33-
34-
spec.add_development_dependency 'debug'
35-
spec.add_development_dependency 'packwerk'
36-
spec.add_development_dependency 'railties'
37-
spec.add_development_dependency 'rake'
38-
spec.add_development_dependency 'rspec', '~> 3.0'
39-
spec.add_development_dependency 'rubocop'
40-
spec.add_development_dependency 'sorbet'
41-
spec.add_development_dependency 'tapioca'
33+
spec.add_dependency 'zeitwerk'
4234
end

lib/code_ownership.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@
77
require 'sorbet-runtime'
88
require 'json'
99
require 'packs-specification'
10-
require 'code_ownership/mapper'
11-
require 'code_ownership/validator'
12-
require 'code_ownership/private'
13-
require 'code_ownership/cli'
14-
require 'code_ownership/configuration'
10+
require 'zeitwerk'
11+
12+
loader = Zeitwerk::Loader.for_gem
13+
loader.setup
1514

1615
if defined?(Packwerk)
17-
require 'code_ownership/private/permit_pack_owner_top_level_key'
16+
require 'code_ownership/private/pack_ownership_validator'
1817
end
1918

2019
module CodeOwnership

lib/code_ownership/private/permit_pack_owner_top_level_key.rb renamed to lib/code_ownership/private/pack_ownership_validator.rb

File renamed without changes.

spec/zeitwerk_spec.rb

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# typed: false
2+
# frozen_string_literal: true
3+
4+
# Zeitwerk Compliance Smoke Test
5+
#
6+
# This test serves as a Zeitwerk compliance smoke test that validates the gem's
7+
# file structure and naming conventions. It ensures that all files in the gem
8+
# follow Zeitwerk's strict naming conventions by forcing the autoloader to
9+
# eagerly load every constant and file in the gem.
10+
#
11+
# How it works:
12+
# 1. Eager Loading: Forces Zeitwerk to immediately load all files and constants
13+
# in the gem, rather than loading them on-demand
14+
# 2. Error Detection: If there are any naming convention violations, Zeitwerk
15+
# will raise an error during this process
16+
# 3. Validation: The test passes only if no errors are raised
17+
#
18+
# What it catches:
19+
# - Misnamed files (e.g., my_class.rb should define MyClass)
20+
# - Incorrect directory structure relative to module nesting
21+
# - Missing constants (files that exist but don't define expected constants)
22+
# - Extra or orphaned files that don't follow naming patterns
23+
# - Namespace violations (constants defined in wrong namespace for their location)
24+
25+
RSpec.describe 'zeitwerk autoloader' do
26+
it 'werks (successfully loads the gem)' do
27+
Zeitwerk::Loader.eager_load_namespace(CodeOwnership)
28+
rescue => error
29+
# Enhance the error message with more specific information
30+
enhanced_message = build_enhanced_error_message(error)
31+
raise enhanced_message
32+
end
33+
34+
private
35+
36+
def build_enhanced_error_message(error)
37+
message_parts = [
38+
'Zeitwerk eager loading failed with the following error:',
39+
'',
40+
"Original Error: #{error.class}: #{error.message}",
41+
'',
42+
]
43+
44+
# Add backtrace information to help identify the problematic file
45+
if error.backtrace
46+
gem_related_trace = error.backtrace.select do |line|
47+
line.include?('lib/') || line.include?('zeitwerk')
48+
end
49+
50+
if gem_related_trace.any?
51+
message_parts << 'Relevant backtrace:'
52+
gem_related_trace.first(5).each do |line|
53+
message_parts << " #{line}"
54+
end
55+
message_parts << ''
56+
end
57+
end
58+
59+
# Try to identify which file might be causing the issue
60+
if /(?:wrong constant name|uninitialized constant|expected.*to define)/i.match?(error.message)
61+
message_parts << 'This error typically indicates:'
62+
message_parts << "- A file name doesn't match its constant name"
63+
message_parts << '- A constant is defined in the wrong namespace'
64+
message_parts << "- A file exists but doesn't define the expected constant"
65+
message_parts << ''
66+
end
67+
68+
# Add helpful debugging information
69+
message_parts << 'To debug this issue:'
70+
message_parts << '1. Check that all files in lib/ follow zeitwerk naming conventions'
71+
message_parts << '2. Ensure each file defines a constant matching its file path'
72+
message_parts << '3. Verify modules/classes are in the correct namespace'
73+
74+
message_parts.join("\n")
75+
end
76+
end

0 commit comments

Comments
 (0)