SkillAgentSearch skills...

Reek

Code smell detector for Ruby

Install / Use

/learn @troessner/Reek
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

reek logo

Code smell detector for Ruby

Table of Contents

Overview

  • Downloads
  • Build Status
  • Gem Version
  • Git Tag
  • Licence
  • Inline docs
  • Code Climate

Quickstart

Reek is a tool that examines Ruby classes, modules and methods and reports any Code Smells it finds.

For an excellent introduction to Code Smells and Reek check out this blog post or that one. There is also this talk from RubyConfBY (there is also a slide deck if you prefer that).

Install it via rubygems:

gem install reek

and run it like this:

reek [options] [dir_or_source_file]*

Example

Imagine a source file demo.rb containing:

# Smelly class
class Smelly
  # This will reek of UncommunicativeMethodName
  def x
    y = 10 # This will reek of UncommunicativeVariableName
  end
end

Reek will report the following code smells in this file:

$ reek --no-documentation demo.rb
Inspecting 1 file(s):
S

demo.rb -- 2 warnings:
  [4]:UncommunicativeMethodName: Smelly#x has the name 'x'
  [5]:UncommunicativeVariableName: Smelly#x has the variable name 'y'

Supported Ruby versions

Reek is officially supported for CRuby 3.0 through 3.3 and for JRuby 9.4. Other Ruby implementations (like Rubinius) are not officially supported but should work as well.

Note that, on each Ruby version, Reek will use the parser for that version of Ruby. So, you should always run Reek using one of your project's target Ruby versions.

Fixing Smell Warnings

Reek focuses on high-level code smells, so we can't tell you how to fix warnings in a generic fashion; this is and will always be completely dependent on your domain language and business logic.

That said, an example might help you get going. Have a look at this sample of a Ruby on Rails model (be aware that this is truncated, not working code):

class ShoppingCart < ActiveRecord::Base
  has_many :items

  def gross_price
    items.sum { |item| item.net + item.tax }
  end
end

class Item < ActiveRecord::Base
  belongs_to :shopping_cart
end

Running Reek on this file like this:

reek app/models/shopping_cart.rb

would report:

  [5, 5]:ShoppingCart#gross_price refers to item more than self (FeatureEnvy)

Fixing this is pretty straightforward. Put the gross price calculation for a single item where it belongs, which would be the Item class:

class ShoppingCart < ActiveRecord::Base
  has_many :items

  def gross_price
    items.sum { |item| item.gross_price }
  end
end

class Item < ActiveRecord::Base
  belongs_to :shopping_cart

  def gross_price
    net + tax
  end
end

The Code Smells docs may give you further hints - be sure to check out those first when you have a warning that you don't know how to deal with.

Sources

There are multiple ways you can have Reek work on sources, the most common one just being

reek lib/

If you don't pass any source arguments to Reek it just takes the current working directory as source.

So

reek

is the exact same thing as being explicit:

reek .

Additionally you can pipe code to Reek like this:

echo "class C; def m; end; end" | reek

This would print out:

$stdin -- 3 warnings:
  [1]:C has no descriptive comment (IrresponsibleModule)
  [1]:C has the name 'C' (UncommunicativeModuleName)
  [1]:C#m has the name 'm' (UncommunicativeMethodName)

Code smells

Reek currently includes checks for some aspects of Control Couple, Data Clump, Feature Envy, Large Class, Long Parameter List, Simulated Polymorphism, Too Many Statements, Uncommunicative Name, Unused Parameters and more. See the Code Smells for up to date details of exactly what Reek will check in your code.

Special configuration for controversial detectors:

Unused Private Method is disabled by default because it is kind of controversial which means you have to explicitly activate it in your configuration via

UnusedPrivateMethod:
  enabled: true

Utility Function is a controversial detector as well that can turn out to be really unforgiving. As a consequence, we made it possible to disable it for non-public methods like this:

---
UtilityFunction:
  public_methods_only: true

Configuration

Command-line interface

For a basic overview, run

reek --help

For a summary of those CLI options see Command-Line Options.

Configuration file

Configuration loading

Configuring Reek via a configuration file is by far the most powerful way. Reek expects this filename to be .reek.yml but you can override this via the CLI -c switch (see below).

There are three ways of passing Reek the configuration file:

  1. Using the CLI -c switch (see Command-line interface above)
  2. Having the configuration file either in your current working directory or in a parent directory (more on that later)
  3. Having the configuration file in your home directory

The order in which Reek tries to find such a configuration file is exactly the above: first it checks if we have given it a configuration file explicitly via CLI; then it checks the current working directory for a file and if it can't find one, it traverses up the directories until it hits the root directory; lastly, it checks your home directory.

As soon as Reek detects a configuration file it stops searching immediately, meaning that from Reek's point of view there exists exactly one configuration file and one configuration, regardless of how many *.reek files you might have on your filesystem.

Configuration options

We put a lot of effort into making Reek's configuration as self explanatory as possible so the best way to understand it is by looking at a simple example (e.g. .reek.yml in your project directory):

---

### Generic smell configuration

detectors:
  # You can disable smells completely
  IrresponsibleModule:
    enabled: false

  # You can use filters to silence Reek warnings.
  # Either because you simply disagree with Reek (we are not the police) or
  # because you want to fix this at a later point in time.
  NestedIterators:
    exclude:
      - "MyWorker#self.class_method" # should be refactored
      - "AnotherWorker#instance_method" # should be refactored as well

  # A lot of smells allow fine tuning their configuration. You can look up all available options
  # in the corresponding smell documentation in /docs. In most cases you probably can just go
  # with the defaults as documented in defaults.reek.yml.
  DataClump:
    max_copies: 3
    min_clump_size: 3

### Directory specific configuration

# You can configure smells on a per-directory base.
# E.g. the classic Rails case: controllers smell of NestedIterators (see /docs/Nested-Iterators.md) and
# helpers smell of UtilityFunction (see docs/Utility-Function.md)
#
# Note that we only allow configuration on a directory level, not a file level,
# so all paths have to point to directories.
# A Dir.glob pattern can be used.
directories:
  "web_app/app/controllers":
    NestedIterators:
      enabled: false
  "web_app/app/helpers**":
    UtilityFunction:
      enabled: false
  "web_app/lib/**/test/**":
    UtilityFunction:
      enabled: false

### Excluding directories

# Directories and files below will not be scanned at all
exclude_paths:
  - lib/legacy
  - lib/rake/legacy_tasks
  - lib/smelly.rb

As you see abov

View on GitHub
GitHub Stars4.1k
CategoryDevelopment
Updated2d ago
Forks282

Languages

Ruby

Security Score

100/100

Audited on Mar 26, 2026

No findings