Kelv
Kelv

Reputation: 81

My session variables won't update (Ruby on Rails)

I'm new to Ruby on Rails, and I'm trying to understand the basics. My application follows the MVC framework and i'm trying to update a session variable from my controller, then access it from my views.

Here's my code in my controller (this is the only place I update the variable):

def testLogin_method
  if(!session[:loggedIn])
    session[:loggedIn] = true;
  else
    session[:loggedIn] = false;
    redirect_to(static_pages_login_url);
  end
end

helper_method :testLogin_method

I call this method when I click the login button in my view using javascript :

function login(){
  <% testLogin_method %>
}

And I call it when I logout :

<li><%= link_to raw('<span class="glyphicon glyphicon-log-out"></span> Log out'), :controller => "static_pages", :action => "testLogin_method" %></li>

My problem is, when I logout, the application does redirect to the login page, but the session[:loggedIn] stays at true. How do I keep it to false?

Edit: How could I toggle a variable session from true to false? The login/logout is just for context, I don't want to actually make an authentification.

P.S. I'm not using Gem Devise, because I just want to understand how the session variables works, this is just an example.

Upvotes: 1

Views: 1340

Answers (2)

max
max

Reputation: 102036

If you want a decent example of how to use sessions consider this example:

# config/routes.rb
resource :session, only: [:new, :create, :destroy]

# app/models/user.rb
class User < ApplicationRecord
  has_secure_password
end

 # app/helpers/session_helper.rb
module SessionHelper
  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

  def user_signed_in?
    current_user.is_a?(User)
  end
end

# app/controllers/session_controller.rb
class SessionController < ApplicationController

  def new
  end

  def create
    reset_session
    @user = User.find_by(params[:email])
    if @user.try(:authenticate, params[:password])
      session[:user_id] = @user.id
      redirect_to :root, success: 'You have been signed in.'
    else
      render :new, error: 'Wrong email or password.'
    end
  end

  def destroy
    reset_session
    flash[:success] = 'You have been signed out.' 
    respond_to do |f|
      f.html { redirect_to :root }
      f.json { head :ok } 
    end
  end
end

This is the simplest possible session based authentication system. Users can log in via POST /session and out through DELETE /session.

When we log users out we call reset_session which nulls the entire session - preventing session fixation attacks.

If we wanted to sign a user out via javascript we would send an ajax request to DELETE /session.

<%= button_to session_path, id: 'logout', method: :delete, remote: { true , type: 'json' } do %>
  <span class="glyphicon glyphicon-log-out"></span> Log out
<% end %>

We then setup an ajax listener to reload the page:

$(document).on('ajax:success', '#logout', function(){
  Turbolinks.clearCache();
  Turbolinks.visit(location.toString());
});

You could update the page in place to change the state between signed in and out - but a better solution is to flush the cache and reload the page. Since otherwise your login/out handler has to keep track of any if user_signed_in? type conditionals on the page.

Upvotes: 1

Ruslan
Ruslan

Reputation: 2009

Does your javascript method work?

Because it that's not how helpers work. It will call the testLogin_method when it renders the page, NOT when javascript executes. Check the source of rendered JS

Helpers are used on the server side to help render the page. On the client side you'll have to make an ajax call from javascript to the testLogin_method

Upvotes: 1

Related Questions