Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

instance and class variables in rails controller

I'm new to rails and ruby. I was studying the concept of class and instance variables. I understood the difference but when I tried it out using the controller in rails it got me confused. What I did is I declared a class and instance variables outside the class methods:

class BooksController < ApplicationController
  # GET /books
  # GET /books.json

  @@world = "Hello World"
  @insworld = "my hobby"

  def index
    @books = Book.all
    binding.pry

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @books }
    end
  end

end

I was under the impression that @insworld has the value of "my hobby", but when I tried to check the value of @insworld when I was inside the index method, @insworld was returning a nil value. @@world has the value of "Hello World". So what happened here? Aren't they defined in the same class?

like image 586
Finks Avatar asked Sep 05 '25 03:09

Finks


2 Answers

Classes are also objects in Ruby, so they can have their own instance variables which are called class instance variables.

  • @@world is a class variable
  • @insworld is a class instance variable
  • #index is an instance method

When you try to access @insworld in #index, Ruby searches for the instance variable in the A object (meaning A.new) because #index is an instance method.

But you defined @insworld as a class instance variable which means it is defined in the class object itself (meaning A).

The following code demonstrates:

class Hi
  @@a = 1 # class variable
  @b  = 2 # class instance variable

  def initialize
    @c = 3 # instance variable
  end

  def test # instance method, works on objects of class Hi
    puts @@a # => 1
    puts @b  # => nil, there is no instance variable @b
    puts @c  # => 3 # we defined this instance variable in the initializer
  end
end

Hi.class_variables        # => @@a
Hi.instance_variables     # => @b
Hi.new.instance_variables # => @c
# Hi is an object of class Class
# Hi.new is an object of class Hi

Keep in mind that all instance variables return nil if they don't exist.

like image 182
Agis Avatar answered Sep 07 '25 15:09

Agis


When you declare @instworld you are inside BooksController class (i.e. self will return BooksController. Weird thing in ruby is that classes are also objects (the are instances of class Class) hence you in fact declares instance variable @instworld for this particular instance of class Classm not for instance of BooksController.

You can check it really easily by declaring class method:

class A
  # self here returns class A
  @variable = 'class instance variable'
  @@variable = 'class variable'

  def initalize
    # self here returns the instance
    @variable = 'instance variable'
  end

  def self.test_me
    # self here returns class A
    @variable
  end

  def test_me
    # self returns the instance
    @variable
  end

  #class variable is accessible by both class and instance 
  def test_me2
    @@variable
  end

  def self.test_me2
    @@variable
  end
end

A.test_me       #=> 'class instance variable'
A.new.test_me   #=> 'instance variable'
A.test_me2      #=> 'class variable'
A.new.test_me2  #=> 'class variable'
like image 45
BroiSatse Avatar answered Sep 07 '25 16:09

BroiSatse