1

I am new to Ruby language. I understand that

@@count: Class variables
@name: Instance variables
my_string: Local variables

I keep the above in mind. However, I found one Ruby code like this:

class HBaseController < ApplicationController
...
  def result
    conn = OkHbase::Connection.new(host: 'localhost', port: 9090, auto_connect: true)
  ...
  end
end

'conn' confuses me a lot.

Is 'conn' a instance variable, or local variable? And what is the scope of 'conn'?

2
  • It looks like you answered your own question. What aspect of conn makes you think it's not a local variable? Commented May 3, 2014 at 0:06
  • Because this variable is in a instance. It seems that a local variable in a instance and an instance variable have the same scope, existing in the scope of an instance, what is the difference if I change 'conn' to '@conn'?Or my question could be what the difference is between a local variable in an instance and an instance variable? Commented May 3, 2014 at 11:30

4 Answers 4

4

I try to explain it with a little example:

class MyClass
  def meth
    conn = 1
  end
  def result
    conn
  end
end

x = MyClass.new
p x.result #-> test.rb:6:in `result': undefined local variable or method `conn'

conn is unknown. Let's try to call meth before:

class MyClass
  def meth
    conn = 1
  end
  def result
    conn
  end
end

x = MyClass.new
x.meth      # try to create conn
p x.result  #-> test.rb:6:in `result': undefined local variable or method `conn' 

Same result. So conn is no instance variable. You define a local variable in meth but it is unknown outside.

Let's try the same with instance variables:

class MyClass
  def meth
    @conn = 1
  end
  def result
    @conn
  end
end

x = MyClass.new
p x.result  #-> nil (no value assigned (*), but is is existing)
x.meth      # initialze @conn with a value
p x.result  #-> 1

With the usage of accessor-methods you define implicit an instance variable:

class MyClass
  attr_reader :conn
  def meth
    conn = 1
  end
  def result
    conn
  end
end

x = MyClass.new
p x.result  #-> nil (no value assigned (*), but is is existing)
x.meth      #   define conn with a value
p x.result  #-> nil - the instance variable is not changed, a locale variable was used

In method result the conn is the reader method conn. In the method meth it is a locale variable (this can be confusing, because now you have a variable with the same name as a variable.

If you want to change the conn-value in the meth-method you must define a setter and use self.conn:

class MyClass
  attr_reader :conn
  attr_writer :conn
  def meth
    self.conn = 1
  end
  def result
    conn
  end
end

x = MyClass.new
p x.result  #-> nil (not defined yet, but is is existing)
x.meth      #   define conn with a value
p x.result  #-> 1

You can replace attr_reader and attr_writer with attr_accessor.

(*) Remark: I wrote no value assigned - this is not really correct, nil is also a value.

Sign up to request clarification or add additional context in comments.

3 Comments

the accessor examples might be even more clear if the getter and setter methods were explicitly written out, allowing you can see the instance variables are instead of hidden inside of the accessor.
@jstim: I modified my example.
I was thinking of writing them explicitly. I edited it, but feel free to roll it back.
1

conn is a local variable (local variables start with a lower case letter or an underscore)

It contains an instance of OkHbase::Connection

Presumably the code that was omitted ... uses that object. Because it's a local variable, once the result method is ended, the local variable will no longer be accessible and the object will be cleared from memory.

(Of course, it's possible the omitted code assigned the object in conn to an instance variable or passed it into some other method that has stored it elsewhere)

Comments

1

In this case, conn is local variable.

EDIT:

conn would be a instance variable if you had it written like

@conn = OkHbase::Connection.new(host: 'localhost', port: 9090, auto_connect: true)

Comments

0

conn is local to the method result

Blocks create a new scope, as do methods and class declarations. Interestingly, if statements do not create a new local scope, so variables you declare inside of an if statement is available outside.

$ irb
1.9.3-p484 :001 > if true
1.9.3-p484 :002?>   foo = 1
1.9.3-p484 :003?>   end
 => 1 
1.9.3-p484 :004 > foo
 => 1 
1.9.3-p484 :005 > 1.times do
1.9.3-p484 :006 >     bar = 1
1.9.3-p484 :007?>   end
 => 1 
1.9.3-p484 :008 > bar
NameError: undefined local variable or method `bar' for main:Object
    from (irb):8
    from irb:12:in `<main>'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.