I’m perplexed as to why I need to selectively refer to an instance variable with "self" inside a case statement inside a class method:
I have a class with an instance method @working_dir:
class FileSystem
attr_accessor :sizes, :working_dir
attr_reader :input
def initialize(input)
@input = input.split("\n")
@sizes = Hash.new(0)
@working_dir = []
end
...
end
I’ve defined a method parse_cmd that performs an operation on @working_dir depending on the outcome of a case statement:
...
def parse_cmd(str)
cmd_arr = str.split(' ')
return unless cmd_arr[1] == 'cd'
case cmd_arr[2]
when '..'
working_dir.pop
when '/'
self.working_dir = ['/']
else
working_dir << cmd_arr[2]
end
end
...
Rubocop/the interpreter yells at me if I exclude the self on self.working_dir = ['/']. Why is this? Why do I need to include it here, but not on other references to @working_dir within the case statement?
>Solution :
Consider a simple example:
irb(main):001:0> class A
irb(main):002:1> attr_accessor :b
irb(main):003:1> def initialize(b)
irb(main):004:2> @b = b
irb(main):005:2> end
irb(main):006:1> def c
irb(main):007:2> b = 42
irb(main):008:2> end
irb(main):009:1> end
=> :c
irb(main):010:0> a = A.new(27)
=> #<A:0x00007f7999088bc0 @b=27>
irb(main):011:0> a.c
=> 42
irb(main):012:0> a.b
=> 27
Calling a.c is assigning 42 to a local variable b, and is not modifying the instance variable @b.
I’d either need to use self.b = 42 or @b = 42 to ensure I am modifying the instance variable.
In your case, you don’t need to use self.working_dir elsewhere because those uses cannot be construed as assigning to a local variable. Because no local variable working_dir exists, the accessor method is used.