Understanding Rails Instance Variables

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.

What is the scope of an instance variable in a Rails controller?

An instance variable in a Rails controller is used in two ways:

  • It is available within instance methods of that controller (including superclass instance methods), just like any other Ruby instance variable.
  • When a Rails controller action renders a view, the controller's instance variables are copied (shallowly) to the view instance. (The view instance is the value of self within a template.) Controller instance variables defined at the time an action renders are therefore effectively available within that action's view. View helpers are just modules which are extended by the view instance, so controller instance variables are effectively available within view helper methods too.

    Note that although controller instance variables are copied to the view, instance variables defined in the view are not copied back to the controller. That's not something you'd normally need to have happen because rendering the view is normally the last thing done in a controller action. And local variables defined in a view are available throughout the view, so there's no reason at all to define an instance variable in a view.

An instance variable in a given controller is not available within other controllers, within other controllers' views, or within any models at all.

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.

Ruby on Rails, Instance variables is persisting through multiple requests

What Alex said in the comments is correct:

The current_transaction_batch_id method is a class method. By setting the instance_variable @current_transaction_batch_id within it, you are setting it on the class, not the instance of the class. By memoizing it you are keeping it unchanged. The class is only loaded once and kept between requests, therefore the value never changes.

You'll need to change your code, so you are working on the instance, not the class:

  def current_transaction_batch_id
@current_transaction_batch_id ||= SecureRandom.hex
end

How are parameters sent when I use instance variables in form_for in rails

The form_for helper creates a form from a model object. If you've set up your Rails app in the conventional way, you will have (it appears) a file called app/models/missed_call_flow.rb that begins by defining class MissedCallFlow.

This file defines the model. It is the source of the params[:missed_call_flow] name, because it is the convention in Rails to name this data structure for the model.

As a generalization in programming, the variable name should not impact the functioning of the program. The fact that you have named your variable @flow is ignored by the inner workings of your program. It is a convenience to the programmer to be able to name your variable whatever you want.

I wonder if you are not seeing the model name you expect because missed_call_flow represents a join table between two other tables with models named missed_call and flow. You might be assigning an instance of this MissedCallFlow class to the variable @flow by mistake.



Related Topics



Leave a reply



Submit