- name
- code-quality
- description
- Maintain code health and architecture standards when implementing features or refactoring Doorkeeper. Use when adding new classes, modules, configuration options, or when a file is growing large or complex.
# Code Quality & Refactoring
When implementing features or refactoring code in Doorkeeper, use this skill to maintain code health and avoid architectural drift.
## Where New Code Belongs
| Type of code | Location |
|-------------|----------|
| Protocol logic (grant processing, token issuance) | `lib/doorkeeper/oauth/` |
| Request strategy (parsing grant_type → request class) | `lib/doorkeeper/request/` |
| Model behavior (token/grant/application mixins) | `lib/doorkeeper/models/` |
| Model concerns (reusable cross-model behavior) | `lib/doorkeeper/models/concerns/` |
| ORM-specific code (ActiveRecord queries, validations) | `lib/doorkeeper/orm/active_record/` |
| Client authentication methods | `lib/doorkeeper/client_authentication/` |
| Configuration options and validation | `lib/doorkeeper/config.rb`, `lib/doorkeeper/config/` |
| Rails integration (routes, helpers, engine) | `lib/doorkeeper/rails/`, `lib/doorkeeper/engine.rb` |
| Grape integration | `lib/doorkeeper/grape/` |
| Controllers exposed to host apps | `app/controllers/doorkeeper/` |
| Views exposed to host apps | `app/views/doorkeeper/` |
| Generators | `lib/generators/doorkeeper/` |
## Large Files to Watch
Known large files that warrant care when modifying:
- `lib/doorkeeper/config.rb` (~873 lines) — the configuration DSL, complex by necessity
- `lib/doorkeeper/models/access_token_mixin.rb` (~607 lines) — consider if new methods belong in a concern
- `lib/doorkeeper/oauth/pre_authorization.rb` (~264 lines) — validation-heavy, watch for growth
- `lib/doorkeeper/oauth/authorization_code_request.rb` (~249 lines) — dense protocol logic
**When adding to these files:** Consider extracting to a new concern or helper module rather than growing them further. The codebase already uses `lib/doorkeeper/models/concerns/` for model decomposition.
## Configuration Option Pattern
Use the established `option` DSL:
```ruby
# In lib/doorkeeper/config.rb, inside the Builder class:
option :my_new_setting, default: :some_default
# Accessed via:
Doorkeeper.config.my_new_setting
```
Add validation in `lib/doorkeeper/config/validations.rb` if the value has constraints.
## Grant Flow Registration Pattern
```ruby
# In lib/doorkeeper/grant_flow.rb:
Doorkeeper::GrantFlow.register(
:my_flow,
grant_type_matches: "my_grant_type",
grant_type_strategy: Doorkeeper::Request::MyFlow,
)
```
## Client Authentication Method Pattern
```ruby
module Doorkeeper
module ClientAuthentication
class MyMethod < Method
def self.matches_request?(request)
# return true if this method's credentials are present
end
def self.authenticate(request)
Credentials.new(uid, secret)
end
end
end
end
# Registration:
Doorkeeper::ClientAuthentication.register(:my_method, MyMethod)
```
## Validation DSL
The `validate` DSL in `lib/doorkeeper/validations.rb` is the standard pattern for request validation:
```ruby
class MyRequest < Doorkeeper::OAuth::BaseRequest
validate :client, error: Doorkeeper::Errors::InvalidClient
validate :scopes, error: Doorkeeper::Errors::InvalidScope
private
def validate_client
client.present?
end
def validate_scopes
# return true/false
end
end
```
Don't duplicate validation logic in controllers — keep it in request/pre_authorization objects.
## Complexity Guidelines
- **Methods**: Keep under 10 lines. Extract private helpers for clarity.
- **Classes**: Keep under 200 lines. Use concerns for model mixins.
- **Nesting**: Max 2 levels of conditionals. Use guard clauses or early returns.
- **Parameters**: Max 3 positional parameters. Use keyword arguments beyond that.
## Backward Compatibility
Doorkeeper is used by many host applications. Changes must be backward-compatible unless explicitly breaking:
- **New config options**: Always provide a sensible default that preserves existing behavior
- **New database columns**: Always make them optional (nullable) with a migration generator
- **Changed behavior**: Gate behind a config flag when possible
- **Deprecated methods**: Use `ActiveSupport::Deprecation.warn` with a removal version
- **View changes**: Note in UPGRADE.md that hosts with overridden views may need to update
## Verification
After refactoring:
1. Run full spec suite: `bundle exec rake spec`
2. Run RuboCop: `bundle exec rubocop`
3. If you changed public API: check that `spec/dummy/config/initializers/doorkeeper.rb` still works
4. If you extracted code: ensure all original specs still pass without modification
View on GitHub