How to resolve reek warnings
Updated January 2026
Reek is a code smell detector for Ruby that helps identify areas of code that may benefit from refactoring. Reek analyzes Ruby code looking for common patterns that suggest poor design or unnecessary complexity. This is different from security-focused tools like Brakeman - Reek focuses on code quality and maintainability.
Reek is run automatically through the CI Code Check workflow. Currently, we only run the DuplicateMethodCall detector to surface potential refactoring opportunities. This documentation will show you how to resolve such warnings.
Reek Warnings
Reek has many code smell detectors: https://github.com/troessner/reek/tree/master/docs
Currently we only run: DuplicateMethodCall
Each warning contains the following attributes:
Smell Type: The category of code smell detected
Message: Description of what was detected
Code: The problematic code pattern
File: Location of the issue
Line: Line number where the issue occurs
Example
# In CI Code Check - Reviewdog Reek Comments on PR
lib/smelly.rb:9: DuplicateMethodCall: Smelly#dup_meth_calls calls 'user.profile' 6 times
lib/smelly.rb:9: DuplicateMethodCall: Smelly#dup_meth_calls calls 'user.profile.name' 6 times
At this point the CI has given us a "duplicate method call" warning, which corresponds with this doc: https://github.com/troessner/reek/blob/master/docs/Duplicate-Method-Call.md
Reek reports issues it finds in your code that suggest opportunities for refactoring. Keep in mind Reek can only analyze code patterns - it doesn't understand business logic or context. There is room for "false positives" - warnings that don't actually indicate a problem in your specific situation.
Steps to Resolve
1. Run Reek locally
bundle exec reek --smell DuplicateMethodCall
2. Identify the warning in the report
lib/my_service.rb:42: DuplicateMethodCall: MyService#process calls 'user.profile.email' 5 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md]
3. Locate the issue in code
def process
if user.profile.email.present?
logger.info("Processing email: #{user.profile.email}")
EmailService.send(user.profile.email, subject, body)
AuditLog.record(user.profile.email, 'email_sent')
NotificationService.notify(user.profile.email)
end
end
At this point we know what the warning is (DuplicateMethodCall) and where it's located (MyService#process:42)
4. Determine why we are getting the warning
user.profile.email is called 5 times in the same method. Each call could potentially:
Execute the same method chain multiple times
Make multiple database queries if not memoized
Make the code harder to read and maintain
5. Evaluate for accuracy and correctness
In this case, we're repeatedly calling user.profile.email which could be extracted to a local variable. This would:
Make the code more readable
Ensure we're working with the same value throughout
Potentially improve performance if the chain isn't memoized
Make future refactoring easier
6. Evaluate for workarounds or alternative approaches
Option 1: Extract to local variable (Recommended)
def process
email = user.profile.email
if email.present?
logger.info("Processing email: #{email}")
EmailService.send(email, subject, body)
AuditLog.record(email, 'email_sent')
NotificationService.notify(email)
end
end
Option 2: Extract to private method
def process
if user_email.present?
logger.info("Processing email: #{user_email}")
EmailService.send(user_email, subject, body)
AuditLog.record(user_email, 'email_sent')
NotificationService.notify(user_email)
end
end
private
def user_email
user.profile.email
end
Option 3: Memoize if appropriate
def process
if user_email.present?
logger.info("Processing email: #{user_email}")
EmailService.send(user_email, subject, body)
AuditLog.record(user_email, 'email_sent')
NotificationService.notify(user_email)
end
end
private
def user_email
@user_email ||= user.profile.email
end
7. Implement the fix
Choose the most appropriate solution based on your context. Generally:
Use local variables for simple cases within a single method
Use private methods for values used across multiple methods
Use memoization when the call is expensive and the value won't change
False Positive Warnings
Let's look at a case where the warning might not indicate a real problem:
def validate_and_process
if params[:email].match?(EMAIL_REGEX) &&
params[:email].length < 255 &&
params[:email].exclude?('@example.com') &&
User.exists?(email: params[:email])
process_email(params[:email])
end
end
Reek warns about params[:email] being called 5 times. However:
params[:email]is already memoized by RailsThe calls are part of a complex validation chain
Extracting to a variable would only marginally improve readability
In this case, you might still want to extract it for clarity:
def validate_and_process
email = params[:email]
if email.match?(EMAIL_REGEX) &&
email.length < 255 &&
email.exclude?('@example.com') &&
User.exists?(email: email)
process_email(email)
end
end
But if the code is performance-critical and the extraction doesn't add clarity, this could be considered a false positive.
When to Ignore Warnings
Currently, we do not have an ignore mechanism configured for Reek warnings. All warnings should be addressed by refactoring the code.
Unlike Brakeman (which has security implications), Reek warnings are about code quality. If you believe a warning is a false positive:
First, consider if there's a simple refactoring that addresses it anyway
Second, discuss with your team if the pattern is intentional and acceptable
Third, document why the pattern is used if it's non-obvious
Remember: Reek is advisory. These warnings suggest potential improvements, but shouldn't block development. Focus on cases where the refactoring genuinely improves code quality.
Why DuplicateMethodCall Matters
Duplicate method calls can indicate:
Performance issues: If the method call is expensive (database query, API call, complex computation)
Consistency issues: The value could change between calls
Readability issues: The intent is clearer with a named variable
Maintenance issues: Changes require updating multiple locations
Even when performance isn't a concern, extracting duplicate calls usually makes code more maintainable and easier to understand.