@ variables in Ruby on Rails
title
is a local variable. They only exists within its scope (current block)
@title
is an instance variable - and is available to all methods within the class.
You can read more here:
http://strugglingwithruby.blogspot.dk/2010/03/variables.html
In Ruby on Rails - declaring your variables in your controller as instance variables (@title
) makes them available to your view.
Explanation of the @ variables inside Rails models
To add to the current answers, @instance_variables
are from object orientated programming...
In
object-oriented programming
with classes, aninstance 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 Orientated 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 orientated; it works by giving you a series of objects to load & interact with. The most notable example is with game programming:
The way object orientation 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
Understanding Rails Instance Variables
Instance variables are in the instance class scope. In Ruby on Rails, because the way how that API was built, instance variables are also available in the views.
You need to be aware of that new and create methods are commonly used in different ProductsController
instances.
First request: GET http://localhost:3000/product/new
When you ask for the new
action (I suppose that is a form), Rails API implementation at a given point creates an instance of ProductsController
and sends the new
message to that instance (calls the new method). Then, the instance variable @product is created and available in any method, or in any view that the action renders. At a given point, Rails replies with a web page and the class instance, and all its instance variables, are destroyed (won't be available anymore).
Second request: POST http://localhost:3000/product/create
When you submit the form for database persistence, again a new controller instance is created, and the create
method is called. Because is a new instance, the @product doesn't have any value.
Note, however, that there is a difference between rendering a view (like its happening in the new
action) and a redirect (like you do in the create
action if @product.save
is true). When you render, you remain in the same controller instance, with you redirect, new server request happens, so the previous controller instance is destroyed and a new controller instance is created.
The before action
before_action is called before you actually start executing the action code. In Rails perspective, an action is not a Ruby method. The class method is the definition of that action:
From Rails guides:
A controller is a Ruby class which inherits from ApplicationController
and has methods just like any other class. When your application
receives a request, the routing will determine which controller and
action to run, then Rails creates an instance of that controller and
runs the method with the same name as the action.
The action acts as an entry point determined by the routes. If you call create inside new, it won't trigger that before_action again.
Are @@variables in a Ruby on Rails controller specific to the users session, or are all users going to see the same value?
@@ComputedData is a class variable. All users are going to see the same data, so baaaad idea.
Defining instance variables in rails controllers
In this case, defining instance variable in users#new
, for example, is necessary for it to be accessible in view. Rails uses this specific mechanism to copy all the instance variables defined in controller context to view.
On the other hand, in sessions#create
you only want to redirect the user if sign in is successful and display sign in form otherwise, which - as you see in sessions#new
- doesn't require any instance variables defined. So local variable in this case is sufficient.
Lifecycle of Instance variables in Ruby on Rails
Rails controller is instantiated per request. It means that every time you receive a request all instance variables are nil
and you need to initialize them.
Accessing instance variable in rails and ruby
Use attr_reader
to read the value of an instance variable
class Person
attr_reader :name
def initialize(name)
@name = name
end
end
john = Person.new("John")
john.name #=> "John"
attr_reader
adds a getter method to the class, in this case
def name
@name
end
Hope that helps!
ruby on rails, colon at back or front of variables
What i have understand so far is that
:variable
in ruby, is to say that this variable will not be able to change, which is similar to constant in other language.
I'm not sure if I understand that statement. In Ruby, constants start with an uppercase letter:
Foo = 1
Reassignment generates a warning:
Foo = 1
Foo = 2 #=> warning: already initialized constant Foo
Variables start with a lowercase letter and reassignment doesn't cause a warning (they are supposed to change):
foo = 1
foo = 2 # no warning
Symbols start with a colon:
:a_symbol
:Uppercase_symbol
:"i'm a symbol, too"
They often represent static values, e.g. :get
and :post
. Symbols are memory efficient, because they are created only once - the same symbol literal always returns the same object. Checking if two symbols are equal is a cheap operation.
Both
key:
andmethod:
(...) What does that this represent?
This is an alternate syntax for hashes. You can type it in IRB to see the result:
{ foo: 1, bar: 2 }
#=> {:foo=>1, :bar=>2}
There are double colons inbetween variables? now I am guessing that
Blog:
is one variable, and:Application
is constant.
No, Blog
and Application
are both constants and ::
is the scope resolution operator. It can be used to access nested constants, e.g.:
module Foo
class Bar
BAZ = 123
end
end
Foo::Bar::BAZ #=> 123
Understanding Ruby variables and symbols?
Variables starting with @
are instance variables, "properties" in other languages. Whereas 'classic' variables are local to the scope of their method/block, instance variables are local to a specific instance
of an object, for example:
class Foo
def initialize(bar)
@bar = bar
end
def bar
@bar # the variable is specific to this instance
end
def buzz
buzz = 'buzz' # this variable is not accessible outside of this method
end
end
You may also see variables starting with @@
, which are class variables, and are accessible by every instance of the class and shared with every instance of the subclass. Usage of those variables is usually discouraged, primarily because subclasses share the variable, which can cause a lot of mess.
In Ruby everything is an object, classes are objects (instances of class Class
), so you can also have class instance variables:
class Foo
def self.bar
@bar #we are in class Foo's scope, which is an instance of class Class
end
def self.bar=(bar)
@bar = bar
end
def bar
@bar # Foo.new.bar != Foo.bar
end
end
What you call "variables with a colon" are not variables. They are a particular type of string, called a symbol, that is immutable and optimized for quick identification by the interpreter, in fact, those are stored internally as pointers, so that :this == :this
is a very quick operation.
This property makes them good candidates for hash keys because they offer quick retrieval or for "flags" to pass to a method; Think of them as a sort of loose constant that "stands for" what they say. Their immutability is also dangerous: All symbols ever created never get garbage collected; It's easy to create a memory-leak by creating thousands of symbols, so use them wisely.
UPDATE since ruby 2.2 symbols may be garbage-collected in certain cases (when no reference is kept and no comparison is needed)
Related Topics
Find Out If Current Time Is Between Two Times
To_D to Always Return 2 Decimals Places in Ruby
How to Get the Current Absolute Url in Ruby on Rails
How to Reload the Current Page in Ruby on Rails
Validation for Non-Negative Integers and Decimal Values
How to Convert a Bigdecimal to a 2-Decimal-Place String
Case Statement With Multiple Values in Each 'When' Block
Cannot Load Such File - Zlib Even After Using Rvm Pkg Install Zlib
Is Ruby Pass by Reference or by Value
Why Do Ruby Setters Need "Self." Qualification Within the Class
How to Dynamically Create a Local Variable
Library Not Loaded: /Opt/Local/Lib/Libssl.1.0.0.Dylib (Loaderror)
Spawn a Background Process in Ruby
Measure the Distance Between Two Strings With Ruby
What Is the -≫ (Stab) Operator in Ruby
Backslashes in Single Quoted Strings Vs. Double Quoted Strings