Search code examples
rubysessionruby-on-rails-4actioncontroller

Ruby on Rails throws error wihen redirects to root_path or login_path


I made a simple application that interacts with DB and perform CRUD operations in it after authenticating and authorizing a user. It used to work when there was a single table but as soon as I started playing with nested relations and authentication mechanism I get the error. So far I think I have done everything right. Here's the screenshot of the error:

enter image description here

Here's my routes.rb:

Rails.application.routes.draw do
 root to: "todo_lists#index"

   resources :todo_lists do
    resources :todo_items
  end

  resources :sessions, only: [:new, :create, :destroy]
  get "/login" => "sessions#new", as: "login"
  delete "/logout" => "sessions#destroy", as: "logout"
end

My session controller:

    class SessionsController < ApplicationController
      def new
      end

      def create
        @user = User.find_by(username: params[:username])
        @password = params[:password]
      end

      if @user && @user.authenticate(password)
        session[:user_id] = @user.id
        redirect_to root_path, notice: "Logged in successfully"
      else 
        redirect_to login_path, alert: "Invalid Username/Password combination"
      end

      def destroy
        reset_session
        redirect_to login_path, notice: "You have been logged out"
      end
    end

Oh and I modified the ApplicationController so the routes should work nonetheless:

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  before_action :ensure_login
  helper_method :logged_in?, :current_user

  protected
      def ensure_login
        redirect_to login_path unless session[:user_id]
      end

      def logged_in?
        session[:user_id]
      end

      def current_user
        @current_user ||= User.find(session[:user_id])
      end
end

Solution

  • I think the code is not in create method, and root_path is not a class method, is an instance method:

    class SessionsController < ApplicationController
      def new
      end
    
      def create
        @user = User.find_by(username: params[:username])
        @password = params[:password]
      end # <--- here create method finish. Where this end comes from?
    
      if @user && @user.authenticate(password)
        session[:user_id] = @user.id
        # root_path is defined for an instance
        # of a controller, not for the class
        redirect_to root_path, notice: "Logged in successfully"
      else 
        redirect_to login_path, alert: "Invalid Username/Password combination"
      end
    
      def destroy
        reset_session
        redirect_to login_path, notice: "You have been logged out"
      end
    end