5

I've worked through a few Rails applications which are using @ attribute variables (which are already attr_accessible) in the models. I was having a tough time getting information on this but from what I gather name and @name are the same thing in a model but im probably incorrect on this.

How do these @ variables work and why would one ever use the @ symbol variables?

Weston Ganger
  • 6,324
  • 4
  • 41
  • 39

6 Answers6

7

To add to the current answers, @instance_variables are from object oriented programming...

In object-oriented programming with classes, an instance variable is a variable defined in a class (i.e. a member variable), for which each instantiated object of the class has a separate copy, or instance.


OOP

"Normal" programming has variables as pieces of data -- strings, integers etc. These are independent & can only interact as part of other functions, depending on their scope.

Object Oriented programming (OOP) can treat variables as pieces of editable data (known as classes). These classes can be invoked, edited and most importantly interacted...

#app/models/product.rb
class Product < ActiveRecord::Base
  #-> class
end

def new
   @product = Product.new #-> creating a new instance of the class
end

Ruby/Rails is object oriented; it works by giving you a series of objects to load & interact with. The most notable example is with game programming:

enter image description here

The way object orienting works is to invoke/initialize an instance of a class (in our case Product), allowing you to manipulate it.

Class instances hold the object in memory, allowing you to perform actions on the class itself. To do this, you'd store the instance of the class in a variable, allowing you to interact with the variable itself:

@product = Product.new
@product.save

--

Instance variables are only valid within the context of the class:

# app/controllers/products_controller.rb
class ProductsController < ApplicationController
  def show
    @product = Product.new #-> @product only available within ProductsController
  end
end

The controllers in Rails are classes, invoked through a rack request:

Request > Rack > Routes > ProductsController.new(request).show > Response

If you want your @instance_variable available in all methods of the class, it has to be at instance level...

# app/controllers/products_controller.rb
class ProductsController < ApplicationController
  def show
    @product = Product.new
    product_save
  end

  private

  def product_save
    @product.save #-> @product available in instance of ProductsController class
  end
end

The most common use for @instance_variables are to store / manipulate instance-centric data. A good example (for our Product example) could be the stock level:

#app/models/product.rb
class Product < ActiveRecord::Base
  def stock
     @qty / @orders
  end
end

Because you can use getter/setter methods within Ruby, you can define the instance values of a class, accessing them through other instance data:

@product = Product.find x
@product.stock #-> outputs stock value for that product
Ben
  • 54,723
  • 49
  • 178
  • 224
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
3

"@" in front of the name signifies that it is an instance variable of the model class, which is different than a simple ruby variable name. Instance (@) variables can be used in the front-end (views).

For example, you can instantiate a variable @book which is a specific instance of the Book class (which is the model). So when you use @book, you are referring to that specific book you created, rather than the overall class.

There is also a difference in the methods you can call on instance versus class variables.


  • It is quite strange to me. If creating an instance variable(starting with `@`) from model and access it from view layer. To be honest, it is a horrible design and hard to manage with. You have to be a great reason to create an instance variable from model. Could you show some example? Why not from controller? – new2cpp Feb 15 '18 at 13:15
2

Variables beginning with @ are instance variables, in short they allow other methods of the same class to use them. For example,

class Something
  def a_method(name)
    @i_variable = name
    normal_variable = "hey"
  end

  def another_method
    @i_variable.reverse #can be seen here and used
    normal_variable  #cannot be seen here and cannot be used, throws an error
  end
end

In Rails, I believe instance variables are important because they are visible across the Model, View, Controller parts of the application.

Sagar Pandya
  • 9,323
  • 2
  • 24
  • 35
2

Variables that start with @ are instance variables. This means that belong to an instance of a class. So if I had the following class:

class Dog 
    def initialize(name, breed)
        @name = name
        @breed = breed
    end 
end 

Everytime I create a Dog, I need to give it a name and a breed.

fido = Dog.new("Fido", "Dalmation")

Because I created instance variables from the name and breed I can get this information from fido.

fido.name => "Fido"

fido.breed => "Dalmation" 
Sara Fuerst
  • 5,688
  • 8
  • 43
  • 86
1

If you do this:

def foo
  thing = "value"
end

foo
puts thing

You will get

NameError: undefined local variable or method `thing' for main:Object

If you do this:

def foo
  @thing = "value"
end

foo
puts @thing

You will get "value"

You see, @variables are visible to the whole class you are operating on, in this case the model.

The @variables are also used a lot in controllers, like this:

def hello
  @current_user_name = User.find(params[:user_id]).name
end
# and in the view:
Hello, <%= @current_user_name %>

Because if you didn't use @, you would have made a local variable and that is not accessible by the view.

Kimmo Lehto
  • 5,910
  • 1
  • 23
  • 32
0

A var with @ is an instance private variable. A var without @ is a local method variable.

A variable with @ can be accessed on an object's level if the object has a method returning a value of or setting a value to it being attr_accessor, attr_reader or def.

Incerteza
  • 32,326
  • 47
  • 154
  • 261