| name | antipattern-prevention |
| description | Avoid common Ruby and Rails antipatterns that degrade maintainability and performance. Use when writing new code, reviewing PRs, or refactoring existing code in Doorkeeper. |
Antipattern Prevention
When writing or reviewing code in Doorkeeper, use this skill to avoid common antipatterns that degrade maintainability and performance.
1. Ruby Iteration Instead of SQL
Severity: High
AccessToken.all.select { |t| t.expired? }
ids = AccessToken.pluck(:id).select { |id| id > 100 }
AccessToken.where("id > ?", 100).pluck(:id)
2. Fire and Forget (Missing Error Handling)
Severity: High
def fetch_jwks(uri)
response = Net::HTTP.get(URI(uri))
JSON.parse(response)
rescue
nil
end
def fetch_jwks(uri)
response = http_fetcher.fetch(uri)
JSON.parse(response)
rescue HttpFetcher::FetchError => e
Rails.logger.warn("JWKS fetch failed: #{e.message}")
nil
end
3. Inaudible Failures (Silent Save)
Severity: Medium
token.save
token.save!
unless token.save
handle_error(token.errors)
end
4. Callback Complexity
Severity: High
class AccessToken
after_create :notify_admin, :update_metrics, :send_webhook
end
class AuthorizationCodeRequest
def before_successful_response
find_or_create_access_token(...)
super
end
end
Doorkeeper uses before_successful_response / after_successful_response hooks — this is the correct pattern.
5. Bare Rescue
Severity: High
rescue Exception => e
nil
end
rescue
nil
end
rescue JWT::DecodeError, JWT::ExpiredSignature => e
handle_jwt_error(e)
end
6. String Interpolation in SQL
Severity: Critical (security)
where("token = '#{params[:token]}'")
where(token: params[:token])
where("token = ?", params[:token])
7. String Equality on Secrets
Severity: Critical (security)
token == stored_token
ActiveSupport::SecurityUtils.secure_compare(token, stored_token)
8. Tight Coupling to ActiveRecord
Severity: Medium
Doorkeeper supports multiple ORMs. Protocol logic in lib/doorkeeper/oauth/ should use the model mixin interface:
AccessToken.where(token: value).lock.first
AccessToken.by_token(value)
9. Shotgun Surgery
Severity: Medium
If adding a new token attribute requires editing 8+ files, consider whether the design is right. The custom_attributes pattern shows how to add token attributes generically without shotgun surgery.
10. Monolithic Methods
Severity: Medium
def authorize
validate_client
validate_scopes
validate_redirect_uri
create_grant
generate_response
end
validate :client, error: Errors::InvalidClient
validate :redirect_uri, error: Errors::InvalidRedirectUri
validate :scopes, error: Errors::InvalidScope
Quick Detection Patterns
grep -rn "rescue$" lib/ app/
grep -rn "\.save$" lib/ app/
grep -rn 'where(".*#\{' lib/ app/
grep -rn '== .*token\|== .*secret\|token.* ==' lib/ app/
grep -rn '\.all\.select\|\.all\.map\|\.all\.each' lib/ app/
Verification
After changes:
bundle exec rubocop — catches many antipatterns automatically
bundle exec rspec — ensures behavior hasn't regressed
- Manual review of the diff for the patterns above