Understanding Ruby variables and symbols? - ruby-on-rails

I am having some trouble understanding the syntax of variables and symbols in Ruby. I am reading a book called Agile Web Development with Rails 4. I am trying to learn both Ruby and Rails so that I can build websites.
The books and tutorials I have been reading sometimes have variables with the "#" symbol in front of them, and then some variables do not have the # symbol in front of them. What is the difference between them?
Also, I am getting confused with the colon. Sometimes I see variables where the colon is in the front, such as :order, and then I see variables where the colon is at the end, such as colon:. I do not understand what the colon is doing.
Please help me understand the Ruby syntax.

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)

Variables with an # symbol are instance variables. What this means is that they persist as long as the instance of the class they are declared in persists. So if you have a class called Message and each message has a variable called #subject, when you instantiate a new message it will keep that subject variable in memory as long as the message object itself lives. Now if it did not have the # symbol, once the function it was declared in "went out of scope" aka finished, the variable would be "lost" as the function was complete and the memory was reclaimed by the Ruby VM. There are also "class variables" that are prefaced with two # symbols. This means the variable is shared across all instances of a class.
As for the colon, if it is before a variable that means it is a "symbol", which is usually used as an identifer for hashes and other bits of data in Ruby. If it is at the end of a word that means it is the key portion of a hash identifier in Ruby 1.9+ syntax.

Instance Variables: (#foo = '123') An instance variable is defined and keeps its value throughout the current instance of the request. In the rails mvc paradigm, the most common use of instance variables are used to help communicate data from the controller to the view, and allows you ro define things in one part of the controller and use in another.
class ProjectsController < ApplicationController
before_filter :find_project
def show; end
def update
if #project.update_attributes(params[:project])
...
end
end
private
def find_project
#project = Project.find(params[:id])
end
end
In the above code, you can see that there is a before filter that gets ran before every method. In the above case, we find the current project and save it to an instance variable. And because its an instance method, its able to be access anywhere within this class as well as the views used to render the html.
Local Variables: (foo = '123') Pretty much exactly what the name implies, they are only able to be accessed within the current method (def) of where they are defined.

sometimes have variables with the "#" symbol in front of them, and then some variables do not have the # symbol in front of them.
Variables with the "#" symbol are instance variables,which are not preceded by #,can be constants or local variables or global variables. Read Ruby Programming/Syntax/Variables and Constants.
Sometimes I see variables where the colon is in the front, such as :order
They are called symbols.
and then I see variables where the colon is at the end, such as colon:. I do not understand what the colon is doing.
These probably the Hash syntax(as you give us hints,so I would guess),where keys are symbols. Example : {foo: 1} - this is a Hash.
Also read as you requested :
Normal Variables Vs Instance variable in Ruby, Whats the difference?

Related

Namespacing module method definition

I accidentally came across this piece of code in Ruby's Postgresql gem:
### Convenience alias for PG::Connection.new.
def self::connect( *args )
return PG::Connection.new( *args )
end
I played around a bit and turns out that this thing is used just like a normal module class method (it's called like this: PG.connect). In fact we could instead say def self.connect ( #args ) ... end and it would work just the same.
Since self::whatever is a first for me I'm wondering what exactly does self namespaces in such a context and what is its true purpose in this case. Can anyone help shed some light on this?
:: is the scope resolution operator. So self::connect resolves connect from self. Which means that its equivalent to self.connect. You can see how it works from this very contrived example:
class Foo; end
class Bar
def Foo::baz
"Hello World"
end
end
puts Foo.baz # "Hello World"
Of course we could also just use def Foo.baz to get the exact same result.
Using double colons for method definition is discouraged by the Ruby Style guide:
Do not use :: to define class methods.
# bad
class Foo
def self::some_method
end
end
# good
class Foo
def self.some_method
end
end
Its also not recommended for anything other than referencing constants and constructors:
Use :: only to reference constants (this includes classes and modules)
and constructors (like Array() or Nokogiri::HTML()). Do not use :: for
regular method invocation.
:: is, in some situations, somewhat equivalent to .. (I will leave out a precise definition in which exact situations it is equivalent and to what degree, because I freely admit I don't fully know it myself, nor is it well-documented.)
Here is an example of where :: and . behave differently:
module Foo
def self.Bar
'method'
end
Bar = 'constant'
def self.Qux; end
end
Foo.Bar
#=> 'method'
Foo::Bar
#=> 'constant'
Foo::Bar()
#=> 'method'
Foo.Qux
Foo::Qux
# NameError (uninitialized constant Foo::Qux)
Foo::Qux()
[Note: this is not a perfect example, since this is about the message sending side of things whereas your example is about the method definition side of things. I believe on the method definition side, they are 100% identical since def never defines a constant and thus there is no ambiguity.]
All Style Guides heavily advocate against this usage, from strongly advising against the message sensing part of it to flat out forbidding both usages of it. The main reason for this is the fact that the two behave differently for message sends, and this may lead to confusion. It is also simpler to explain the conceptual difference between method lookup (dynamic, upwards in the inheritance chain) and constant lookup (first static, lexically outward, then dynamic, upwards in the inheritance chain) when not using the same operator for both.
The typical style used by many Rubyists is:
NEVER use :: for singleton method definition, always use ..
ALWAYS use :: for referencing singleton methods in documentation, never use ..
ALWAYS use . for usage examples of message sends (including singleton methods) in documentation, never use ::.
NEVER use :: for message sends (including singleton methods), always use ..
Those last two are sometimes softened to allow for methods that are supposed to return modules or classes, and to allow for methods that act as factories (e.g. Nokogiri::XML) to be invoked via message sends that "look like" constant lookup, (e.g. Nokogiri::XML('<root/>') instead of Nokogiri.XML('<root/>')).
There was a feature request for removing this usage of ::, but it was rejected mostly because of backwards-compatibility concerns.

What is the difference between using local variable or instance variable in an Rails API?

In a common application we use instance variables so that we can access them in our views. But in a Rails api application what would the need be?
Is there any performance difference between using a local or instance variable In this context of Controllers?
I do not understand why rails uses instance variables in the create and index method in an api application generated by scaffold if the variable is not reused
def show
user = User.find(params[:id])
render json: UserSerializer.new(user)
end
def show
#user = User.find(params[:id])
render json: UserSerializer.new(#user)
end
In this exact example, there is no functional difference.
Is there any performance difference? Or is there material performance difference? I do not know the answer to the first question. The answer to the second question, I imagine, is 'no' unless you are doing this at some unimaginably large scale. Even then, it's hard to imagine.
BTW, you could just do:
def show
render json: UserSerializer.new(User.find(params[:id]))
end
In your example, there is no need for a variable, either user or #user.
There is a very clear practical difference in how lexical and instance variables work:
class Thing
def initialize
#ivar = "Hello World"
end
def foo
#ivar
end
end
> Thing.new.foo
=> "Hello World"
Since instance variables are attached to the instance they can be shared among methods of an object without passing by value as typically used by callbacks:
class API::V1::ThingsController < ::ApiController
before_action :set_thing, except: [:create, :index]
def show
respond_with #thing
end
# ...
private
def set_thing
#thing = Thing.find(params[:id])
end
end
This can be immensely useful when considering the convention over configuration focus of rails. Controller IVARs are also available in the view through the view context.
Lexical variables on the other hand only exist in the lexical scope where the are defined (the method, block, proc or lambda):
class Thing
def initialize
lex = "Hello World"
end
def foo
lex
end
end
> Thing.new.foo
NameError: undefined local variable or method `lex' for #<Thing:0x007f87068b5968>
They are preferable when you need a short lived variable with a local scope. Rails also has locals which is actually a hash where you can stuff things when rendering which should not be conflated with the Ruby concept of lexical variables. Rails uses method_missing in the view context to proxy to the locals hash.
The performance difference is most likely extremely negible as both are just variables that are bound to a scope - either the object or a method/block. The lexical variable will recycled by the GC when the scope is closed (the method finishes) though while an instance variable will persist with the object. This is rarely an issue though.
The performance difference will be negligible.
But there's two competing guidelines at work. One is "Always use the weakest construction." Don't use double "quotes" if you can use single 'quotes'. Don't use a regular expression if you can use String#index. Don't use an instance variable if you can use a local variable.
The other guideline is "Design for testing." If you use an instance variable, your test can inspect it with assigns(:user). That rule trumps the "weakest construction" rule. So use an instance variable, and write lots of automated tests!
there is no difference talking about functionality in that example. but creating an instance variable is to let that variable be accesible later, maybe on the view or in another method, in this case, talking about api's (you don't have views), if you do not plan to use #user in another method inside that controller for example, you don't need to create it, with just a local variable, it's enough.
talking about performance, I don't think there will be much differences, at least something noticeable.
And as a comment:
"An instance variable continues to exist for the life of the object that holds it. A local variable exists only within a single method, block or module body."

What does it mean when a variable or method or constants has preceded with an underscore in Ruby?

What does it mean in Ruby when you see methods or variables with an underscore before them like this in Rails
submit_tag _('Enroll')
:notice => _('Update card.')
or
_session_id
Are most of these just conventions, or do they imply a functional difference in the behavior of the variables/methods?
There is no difference in bahavior. It is just convertion.
But let's have a closer look:
_('A string') is actually a method not a variable. The underscore method is defined by Gettext and translates a string.
#_foo is offen used to show other developers that there is something special about the variable, and therefore it should not be used. I saw that pattern a lot for variables that are used to cache values, like:
def expensive_operation
#_expensive_operation ||= begin
# long running code...
end
end
And the underscore is sometimes used to indicate that a variable is not used in a block. Like this:
a_hash.each do |_, value|
# do something with the value, not with the key
end
Those two cases are completely different.
The second looks like it is a local variable (although it might be a method call, it's impossible to tell without the context). Local variables that begin with an underscore will not generate an "unused variable" warning if they are unused, which is why they are used to indicate a variable that is intentionally not used (as opposed to a typo or pogramming error).
The first is a call to a method named _. What this method does, depends on the class of self at that point, you will have to look at the documentation for that class.
In IRb, _ is a method that returns the result of the last expression that was evaluated.

How does scope work in Ruby?

I cannot figure this out as someone who has primarily worked in C.
How is the following code plausible?
if true
hi = "hello"
end
puts hi
I'm used to hi not being in the scope of the puts, so it would error. How does scope in Ruby work. I can't seem to find a clear tutorial explaining it.
And even though that's valid, is it good practice?
In Ruby, there are 5 scopes:
script scope
module scope
class scope
method scope
block scope
Block scopes nest, the other ones don't. Blocks can close over their lexical environment, the other ones can't. (IOW: not only do they nest inside their lexically surrounding environment, i.e. can access variables from their lexically surrounding environment, they can even continue to do so after that surrounding environment ceases to exist.)
Unlike some other languages, Ruby doesn't have a top-level or global scope for local variables. The "biggest" scope is script scope, but that isn't global, it is confined to a single script. (Usually, a script is the same as a file, but there are Ruby implementations that don't use files, so a term like "file scope" would be misleading.)
Local variables are defined from the point on where their definition is parsed, and initialized from the point on that their definition is executed. In between, when they are defined but not initialized, they evaluate to nil.
Consider this slightly modified example:
if false
hi = 'hello'
end
hi
# => nil
# hi is defined here, because its definition was parsed
if true
hi = 'olleh'
end
hi
# => 'olleh'
# hi is initialized here, because its definition was executed
In Ruby we have 4 scopes -
top level scope
def creates a new scope
class creates a new scope
module creates a new scope.
In your case hi is a local variable which has been created in the top level scope. As I said above if doesn't create a new scope, so it is using the default scope, which is top level scope, and hi is created in the top level scope.
Example :
foo = 12
def baz
p foo # undefined local variable or method `foo'
bar = 2
end
bar # undefined local variable or method `bar'
As def creates a completely brand new scope, thus inside baz, that scope has no idea about foo and it objects. Similarly, inside the baz, I have created a new variable bar, but it is not known to the out side the scope of baz, thus top level also objects against bar.

How declare a global variable in ROR3.0 within a function?

hi i m new to ruby on rails please let me know is it possible to declare a variable within the function/method
def fun1
#initialized a global variable
end
def fun2
#access value
end
is it possible get value of a variable declared in fun1 function by fun2 function
To create a truly global variable, use $:
def fun1
$foo = 'bar'
end
def fun2
puts $foo
end
Here $foo is available outside the class instance once fun1 has been called.
As noted in the first comment, this should be used sparingly:
They are dangerous because
they can be written to from anywhere. Overuse of globals can make
isolating bugs difficult; it also tends to indicate that the design of
a program has not been carefully thought out.
What you're probably asking for is an instance variable, which uses #:
def fun1
#foo = 'bar'
end
def fun2
puts #foo
end
Here #foo is available anywhere in the current instance of the class, again once it has been declared by calling fun1.
See for example this on the various variable scopes in ruby.
First of all, it would be better if you could share your actual scenario for what you need to define a global variable from a function. There might be a better, manageable, DRY approach for your solution.
Secondly, apart from the answer from "Thilo", here are few references showing the usage of global variables for rails in different situations. Not just for ruby. You need it for rails right?
https://stackoverflow.com/a/4110947/1160106
https://stackoverflow.com/a/3600860/1160106

Resources