Classes should not assume that instance variables are set or present outside of the current class definition.
Good:
class Foo
def initialize
@bar = :foo
end
def foo?
@bar == :foo
end
endGood as well:
class Foo
def foo?
bar == :foo
end
def bar
@bar ||= :foo
end
endBad:
class Foo
def go_foo!
@bar = :foo
end
def foo?
@bar == :foo
end
endRunning Reek on:
class Dummy
def test
@ivar
end
endwould report:
[1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivarNote that this example would trigger this smell warning as well:
class Parent
def initialize(omg)
@omg = omg
end
end
class Child < Parent
def foo
@omg
end
endThe way to address the smell warning is that you should create an attr_reader to use @omg in the subclass and not access @omg directly like this:
class Parent
attr_reader :omg
def initialize(omg)
@omg = omg
end
end
class Child < Parent
def foo
omg
end
endDirectly accessing instance variables is considered a smell because it breaks encapsulation and makes it harder to reason about code.
If you don't want to expose those methods as public API just make them private like this:
class Parent
def initialize(omg)
@omg = omg
end
private
attr_reader :omg
end
class Child < Parent
def foo
omg
end
endAn instance variable must:
- be set in the constructor
- or be accessed through a method with lazy initialization / memoization.
If not, Instance Variable Assumption will be reported.
In ActiveRecord it seems common to use callbacks like after_initialize to initialize instance variables as
outlined here
or here
instead of overriding the initialize method.
If an instance variable is initialized in such a callback Reek will report it correspondingly.
This would smell for instance:
class Sample < ApplicationRecord
after_initialize do
@my_var = false
end
endSince Reek cannot reliably detect that is used in a Rails context we recommend to disable this detector for "app/models" like this:
directories:
# Your other configuration....
"app/models":
InstanceVariableAssumption:
enabled: falseInstance Variable Assumption supports the Basic Smell Options.