Hristo Georgiev
Hristo Georgiev

Reputation: 2519

Not sending a variable to another controller

I have a small problem:

I am trying to send a variable from controller 1 to controller 2 and then send it back to controller 1. Here is the logic:

  1. In order to start making a new model, the user has to sign in.
  2. Guest users must also have access to the path of the new model.
  3. If not logged in, guest users have to be redirected to sign in.
  4. Once logged in, users have to go back to the path they previously tried to access.

I decided to pass the type of the model to the log in screen and then pass it back to the new model action.

The variable type usually comes from the route, so upon redirecting to the login screen, I just pass it over.

businesses_controller.rb:

before_filter :require_login 

def require_login
  unless current_user 
    redirect_to signin_path( :type => params[:type])
  end
end

When I get redirected, the variable gets passed into my url - so far, so good:

/signin?type=ccompany

The problem comes when I try to grab the variable from the URL and use its value to redirect the successfully logged in user back to where he tried to go to:

sessions_controller.rb:

class SessionsController < ApplicationController
before_filter :initialize_type , :only => [:new , :create]
  def new

  end

  def create
   user = User.find_by(email: params[:session][:email].downcase)

   if user && user.authenticate(params[:session][:password])
     sign_in user
     if defined?(@type)

      redirect_to send("new_#{@type}_path")
     else
      redirect_back_or user
     end

   else
     flash.now[:error] = t('sign.invalid')
     render 'new'
   end
  end

  def destroy
    sign_out
    redirect_to root_url
  end

 private
  def initialize_type
    @type = params[:type]
  end
end

When I put the @type variable into my view, its value renders without problems. But when I try to log in, this is the error I get:

undefined method `new__path' for #<SessionsController:0x007f76189d42f8>

enter image description here

I also tried

redirect_to :controller => "businesses" , :action => "new" , :type => params[:type]

But the type symbol passes with no key. I also tried putting a variable there, still doesn't work.

So far, it has only worked when I just write down a string that matches the path, but that is not what I need. I need to pass the value of the params[:type] hash. I've put the value of the variable in the view and it's all good, but when I try to pass it into a function, its value somehow 'disappears'.

How can I make this work?

Upvotes: 0

Views: 80

Answers (2)

Hristo Georgiev
Hristo Georgiev

Reputation: 2519

Ok, I found a workaround.It's a bit clumsy and may cause security issues, but it works. I forced the variable to pass as a session parameter.

I put the received variable as a hidden field in the new session form:

<%= form_for(:session , url: sessions_path ) do |f| %>

 <%= f.label  :email , t('session.email') %>
 <%= f.text_field :email %>


 <%= f.label  :password , t('session.password') %>
 <%= f.password_field :password%>

 <%= f.hidden_field :val , value: @type %> 
  #@type is set in the before filter as a variable passed from another controller

Then, upon submit, I just catched the parameter and put it into its place:

    if user && user.authenticate(params[:session][:password])
 sign_in user
 if defined?(@type)
   params.require(:session).permit(:val)
   @type = params[:session][:val]
  redirect_to send("new_#{@type}_path")
 else
  redirect_back_or user
 end
else
  flash.now[:error] = t('sign.invalid')
  render 'new'
end
end

Now the function works properly. Unfortunately, I have to use the view as a "conduit" that passes a variable. I would be really happy if somebody writes a helper method for this or a better workaround.

Cheers.

Upvotes: 0

BroiSatse
BroiSatse

Reputation: 44715

Problem is:

if defined?(:type)

it always returns true, as a symbol is always defined. What you want is:

if defined?(@type)

however this might add 'unintentional feature' to your code, as nil is well defined in ruby. You should do:

if @type

NOTE:

I need to pass the value of the :type symbol. - symbol has no value. Variables do have values, symbol is a symbol and it is its own value.

After understanding the question:

The above still holds.

You cannot pass instance variable from one action to another. For each request rails instantiate new controller instance and all instance variables are lost. There are number of ways to pass it though.

  1. Create hidden field in your form to hold the value. You need to keep in mind that its value can be overwritten by any internet user with a minimal knowledge of how internet works.

  2. In your new action simple write the value into a session and read it in you create action. Since session is either stored server side or stored in encrypted cookie, there is very small chance anyone can temper with it.

Upvotes: 4

Related Questions