Skip to main content
Skip table of contents

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

CODE
# 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

CODE
bundle exec reek --smell DuplicateMethodCall

2. Identify the warning in the report

CODE
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

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)

CODE
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

CODE
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

CODE
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:

CODE
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:

  1. params[:email] is already memoized by Rails

  2. The calls are part of a complex validation chain

  3. Extracting to a variable would only marginally improve readability

In this case, you might still want to extract it for clarity:

CODE
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:

  1. First, consider if there's a simple refactoring that addresses it anyway

  2. Second, discuss with your team if the pattern is intentional and acceptable

  3. 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.

Additional Resources

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.