# Instance Variable Assumption ## Introduction Classes should not assume that instance variables are set or present outside of the current class definition. Good: ```Ruby class Foo def initialize @bar = :foo end def foo? @bar == :foo end end ``` Good as well: ```Ruby class Foo def foo? bar == :foo end def bar @bar ||= :foo end end ``` Bad: ```Ruby class Foo def go_foo! @bar = :foo end def foo? @bar == :foo end end ``` ## Example Running Reek on: ```Ruby class Dummy def test @ivar end end ``` would report: ```Bash [1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar ``` Note that this example would trigger this smell warning as well: ```Ruby class Parent def initialize(omg) @omg = omg end end class Child < Parent def foo @omg end end ``` The 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: ```Ruby class Parent attr_reader :omg def initialize(omg) @omg = omg end end class Child < Parent def foo omg end end ``` Directly accessing instance variables is considered a smell because it [breaks encapsulation](http://designisrefactoring.com/2015/03/29/organizing-data-self-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: ```Ruby class Parent def initialize(omg) @omg = omg end private attr_reader :omg end class Child < Parent def foo omg end end ``` ## Current Support in Reek An 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. ## Using Instance Variable Assumption in a Rails context In ActiveRecord it seems common to use callbacks like `after_initialize` to initialize instance variables as outlined [here](https://stackoverflow.com/questions/41165520/overriding-applicationrecord-initialize-bad-idea) or [here](http://blog.dalethatcher.com/2008/03/rails-dont-override-initialize-on.html) 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: ```Ruby class Sample < ApplicationRecord after_initialize do @my_var = false end end ``` Since Reek cannot reliably detect that is used in a Rails context we recommend to disable this detector for "app/models" like this: ```Yaml directories: # Your other configuration.... "app/models": InstanceVariableAssumption: enabled: false ``` ## Configuration _Instance Variable Assumption_ supports the [Basic Smell Options](Basic-Smell-Options.md).