CLAUDE.md
May 16, 2026 · View on GitHub
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What This Gem Does
grape-swagger-rails is a Rails Engine gem that mounts a Swagger UI interface for APIs documented with the grape-swagger gem. It provides a single mountable engine that renders Swagger UI v5 with configurable authentication, theming, and authorization hooks.
Commands
bundle exec rake # Run full suite: RuboCop + RSpec (default)
bundle exec rake spec # Run all RSpec tests only
bundle exec rake rubocop # Run RuboCop linting only
bundle exec rspec spec/features/swagger_spec.rb # Run a single spec file
yarn build:frontend # tsc → index.js, then esbuild → index.min.js (+ .map)
yarn build:frontend:js # Just tsc (readable bundle)
yarn build:frontend:min # Just esbuild (minified bundle, consumes index.js)
yarn typecheck # Type-check TypeScript without emitting
bundle exec rake swagger_ui:dist:update # Update bundled Swagger UI assets
SWAGGER_UI_VERSION=v5.32.5 bundle exec rake swagger_ui:dist:update # Pin to a version
Tests use Capybara + Selenium with Firefox. Firefox and geckodriver must be installed locally. On macOS, xvfb is not needed (unlike CI). Tests launch a real browser to validate UI behavior.
After editing TypeScript, run yarn build:frontend before running specs — the specs exercise app/assets/javascripts/grape_swagger_rails/index.js, which is the compiled output. Never edit the compiled JS directly. The build also emits index.min.js (+ sourcemap); the view picks the minified bundle in production (Rails.env.production?) via grape_swagger_rails_runtime_asset and the readable one everywhere else.
Architecture
The gem has minimal moving parts:
lib/grape-swagger-rails.rb— DefinesGrapeSwaggerRails.optionsas an OpenStruct. All configuration lives here (URL, auth type, headers, theme, before_action proc, etc.).lib/grape-swagger-rails/engine.rb— Rails Engine. Configures asset precompilation for both Sprockets and Propshaft pipelines.app/controllers/grape_swagger_rails/application_controller.rb— Singleindexaction. Runsoptions.before_action_procin controller context for authorization.app/views/grape_swagger_rails/application/index.html.haml— The entire UI. SerializesGrapeSwaggerRails.optionsas JSON intodata-swagger-options, then JavaScript parses it to initialize SwaggerUIBundle. Handles theme toggling and auth injection via Swagger UI'srequestInterceptor.frontend/grape_swagger_rails/index.ts— TypeScript source for the browser runtime.tsccompiles it toapp/assets/javascripts/grape_swagger_rails/index.js(readable, ES5);esbuildthen minifies that intoindex.min.js(+.map). Both files are checked in so they ship with the gem. The TypeScript interfaceSwaggerPageOptionsis the authoritative schema for options consumed by JS.config/routes.rb— Single root route →ApplicationController#index.lib/tasks/swagger_ui.rake— Rake task that clonesswagger-api/swagger-uiand copies dist files intoapp/assets/.
Key Patterns
Configuration flow: Host app sets options in an initializer → options serialized to JSON in the view → JavaScript reads them at page load.
Auth injection: All authentication (basic, bearer, token, API key) is implemented client-side via Swagger UI's requestInterceptor, not Rails middleware. The interceptor appends headers or query params to every outbound API request.
Before-action authorization: GrapeSwaggerRails.options.before_action { redirect_to '/' unless current_user } — the proc runs in the controller's binding, so it has full access to helpers, current_user, etc.
Multiple spec URLs: Set options.urls (array) instead of options.url to expose a spec selector dropdown. Each entry can be a string URL or { name:, url: } hash. options.urls_primary_name selects the default.
Swagger UI pass-through: options.swagger_ui_config is merged into the SwaggerUIBundle(...) call before gem defaults, allowing any native Swagger UI option to be set. Gem-owned keys (url, requestInterceptor, presets) still take precedence.
Asset pipeline: The engine conditionally handles both Sprockets (config.assets.precompile) and Propshaft. If modifying assets, verify both pipelines work — CI tests both.
Testing Structure
spec/
features/
swagger_spec.rb # Main integration tests (auth types, theme, headers)
grape-swagger-rails_spec.rb # Core functionality and options
welcome_spec.rb # Basic rendering
dummy/ # Minimal Rails app used by all tests
app/api/ # Sample Grape API with swagger docs
The dummy app in spec/dummy/ is the test harness. Integration tests drive a real browser against it.
RuboCop
Config in .rubocop.yml targets Ruby 3.4. Plugins: rubocop-capybara, rubocop-rspec. Overrides tracked in .rubocop_todo.yml.
Compatibility Matrix
- Rails 7.2 / 8.1 × Ruby 3.2–3.4 × grape-swagger 2.1.4 (grape ~> 3.1)
- Rails 7.2 × Ruby 3.2 × grape-swagger 1.6.1 (grape ~> 1.8) — legacy combination
- Ruby 3.1 is excluded from Rails 8 (requires 3.2+)
- grape ~> 1.8 is not tested on Ruby 3.4: Ruby 3.4 tightened
Forwardableto raise on private-method delegation, which breaks Mustermann'snamed_capturesforwarding used by grape-swagger 1.6.1 to introspect routes - Both Sprockets and Propshaft asset pipelines are tested in CI