Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instance variable not set with redirect

What would cause my instance variable @product to not be set/passed for the redirect. Product is an ActiveModel object, not ActiveRecord. to be more specific, the @product variable is not appearing in the redirect_to(new_services_path) or redirect_to(home_path) pages. As the @product variable need to populate a form in my footer that is on every page.

Application_controller:

class ApplicationController < ActionController::Base 
  before_filter :set_product

  private

  def set_product
    @product ||= Product.new
  end
end

Product_controller:

  def new
  end


 def create
    @product = Product.new(params[:product])

    if  @product.category == "wheels"
      redirect_to(new_services_path) 
    else
      redirect_to(home_path) 
    end
  end

Issue related to this original post.. Passing variables through multiple partials (rails 4)

like image 525
user2012677 Avatar asked Sep 26 '22 12:09

user2012677


2 Answers

Instance variables are not passed on a redirect.

Consequently, you have no @product object at the time you are reaching the before_filter and so you're just creating the new and empty Product object each time.

ActiveModel objects can't persist from session to session, but you can keep the attributes in your session store and use that in your before_filter

def set_product
  @product = Product.new(session[:product]) if session[:product]
  @product ||= Product.new
end

And in your create method you move the form params to the session...

def create
  session[:product] = params[:product]
  set_product 
  if @product.category == 'wheels'
  ---

Notice that we called set_product explicitly in the create method because the session[:product] had been re-established.

In case you're wondering WHY the instance variable is lost... in the create method you are in an instance of ProductController and that instance has it's own instance variables. When you redirect, you are instructing rails to create a NEW instance of some other (or the same) controller, and that brand new controller object, it has no instance variables established.

like image 62
SteveTurczyn Avatar answered Sep 28 '22 05:09

SteveTurczyn


To add to SteveTurczyn's answer, you need to read up about object orientated programming. After I did, all the @instance variable stuff became a lot clearer.

enter image description here

Very good write-up


Ruby is object-orientated, meaning every time you send a request, it has to invoke all the relative objects (classes) for you to interact with:

The duration of this request is called an instance. Redirecting invokes a new request; hence a new instance of your various classes.

This is why you have to invoke new @instance variables each time your users interact with a new action:

#app/controllers/your_controller.rb
class YourController < ApplicationController
   def edit
      @model = Model.find params[:id]
   end

   def update
      @model = Model.find params[:id] #-> new request = new instance
   end
end

--

Thus, when you ask...

@product variable need to populate a form in my footer that is on every page.

You need to remember that this will be invoked every time your actions are rendered. You already do this; the problem is that you're not persisting the data:

#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base 
  before_filter :set_product

  private

  def set_product
    @product ||= Product.new #-> after "create", params[:product] = nil (new instance)
  end
end

@SteveTurczyn got it when he mentioned putting the data into the session. As per the docs...

HTTP is a stateless protocol. Sessions make it stateful.

like image 34
Richard Peck Avatar answered Sep 28 '22 07:09

Richard Peck