Click to find out more about our Work
September 11th, 2008

Tutorial : Create a login system in Ruby on Rails

23 Comments

Hello everyone,
In today’s tutorial I`ll teach you how to create a very basic Login System in Ruby on Rails. Welcome to Tutorial : Create a login system in Ruby on Rails. Before proceeding I would suggest you guys to read Tutorial : Create a blog using Ruby on Rails 2. (Part 1 – Relationships) since we will be using this sytem in our application.

Introduction

We will create a very simple standalone login system first, It will check the database for valid users. Then I`ll let you know how to integrate a similar login system in our blog application. First of course the basics.

We would need to design

  • Login page
  • A page which would have to be protected by the login system
  • Function to Check session, if not valid, then redirect to login page.

Demo of the Login System in RoR : Click Here (user:admin,pass:admin)

Step 1 : Create ‘logintest’ Rails app

Ok, Fire up the command prompt window, Lets create our Rails application called ‘logintest‘.

C:\railsappz>rails logintest -d mysql

After creating the Rails application, you`ll notice a new directory called logintest being created. Navigate inside.

Step 2 : Modify the ‘database.yml’ & Create Tables

Since, our authentication system is going to check the backend for valid users, we need to tell it which database to refer, for the same you need to modify the database.yml file. By now, you must have known this procedure, but for those guys who don`t know how to, here is a lowdown. Navigate to C:\railsappz\login\config, inside it you`ll find database.yml

Open it, then modify the code inside. Please put a valid database name, a valid username and password (mysql). If you want to know how to create databases using phpMyAdmin, read here Tutorial : Using phpMyAdmin to manage mySQL

Secondly, we need to create the ‘User’ Table. This table already has some user information.

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL auto_increment,
  `user_name` varchar(255) default NULL,
  `password` varchar(255) default NULL,
  `role` int(11) default NULL,
  `created_at` datetime default NULL,
  `updated_at` datetime default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

INSERT INTO `users` (`id`, `user_name`, `password`, `role`, `created_at`, `updated_at`) VALUES
(1, 'admin', 'admin', 0, NULL, NULL),
(2, 'test', 'test', 1, NULL, NULL);

These are the 2 entries we have entered in our User Table.

  1. Username : admin
    Password : admin
  2. Username : test
    password : test

The following is how MY database.yml looks.

development:
  adapter: mysql
  encoding: utf8
  database: login
  username: root
  password: root
  host: localhost

test:
  adapter: mysql
  encoding: utf8
  database: login
  username: root
  password: root
  host: localhost

production:
  adapter: mysql
  encoding: utf8
  database: login
  username: root
  password: root
  host: localhost

Step 3 : Generate the ‘User’ Model

Creating a model is very important, because for any querying to the database, we need to use a object of this model, similarly to import the form values (login form), we will be using the object of User model.

So we need to tell our app about this mode. Since we are not using database, we`ll skip the database files that normally get created, while creating a model. We`ll use the –skip-migrations option.

C:\railsappz\login>ruby script/generate model user --skip-migrations

Lets move on to creating the User Controller.

Step 4 : Generate the ‘User’ Controller

Now lets create our User Controller. Before creating, Lets do a check on what all we would require, cuz accordingly we have to create our controller.

  1. Login Page
  2. Private Page

So Our controller file will have the login page, private page.

C:\railsappz\login>ruby script/generate controller user login private
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/user
      exists  test/functional/
      create  app/controllers/user_controller.rb
      create  test/functional/user_controller_test.rb
      create  app/helpers/user_helper.rb
      create  app/views/user/login.html.erb
      create  app/views/user/private.html.erb

If you noticed, you`ll see that whatever parameters we specified, view files with the same name are created, i.e login.html.erb, private.html.erb. Basically

Lets decipher the above code,

User – Controller Name
Parameters :

  • login – Creates a empty function inside user_controller.rb and also creates a view file called login.html.erb which will contain our Login Form.
  • private – Creates a empty function inside user_controller.rb and also creates a view file called private.html.erb which will contain the content to be protected using our login system.

Step 5 : Edit the Views, viz: login.html.erb, private.html.erb

Navigate to C:\railsappz\login\app\views\user, open up login.html.erb. Time to create our form. We will be using the ruby helpers.

<% if flash[:notice] %>
<div style="font-family:'Trebuchet MS'; color:#FF0000; font-size:14px;">
<%= flash[:notice] %>
</div>
<% end %>

<!--creates form, exectues the authenticate method when the submit button is clicked-->
<%= form_tag :action=>'authenticate' %>
User name:
<%= text_field("userform", "user_name",:size=>"20" ) %>
Password:
<%= password_field("userform", "password",:size=>"20" )
%>
<input type="submit" value=" LOGIN " />

Save the file, now open up private.html.erb. This will be our protected page. If someone tries to view this page directly he should be redirected to the login page. Only valid users should be able to see this page.

<!--#displays hello (username)-->
hello <strong><%=session[:user_id]%></strong>.

<!--#creates logout link, when the link is clicked, the controller is User and the method executed will be logout.-->
<%= link_to "logout",:controller => "user", :action => "logout" %>

Ok, Now we have defined our view files and used some methods inside them, now its time to define these methods. All methods go inside the controller.

Step 6 : Edit the user_controller.rb

Navigate C:\railsappz\login\app\controllers and open user_controller.rb. You will notice 2 empty methods viz login, private. Let them be the way they are for now, We will be creating 2 methods, first lets create a method to handle our authentication viz authenticate.

def authenticate
		#User.new(params[:userform]) will create a new object of User, retrieve values from the form and store it variable @user.
		@user = User.new(params[:userform])
        #find records with username,password
		valid_user = User.find(:first,:conditions => ["user_name = ? and password = ?",@user.user_name, @user.password])

        #if statement checks whether valid_user exists or not
		if valid_user
        #creates a session with username
			session[:user_id]=valid_user.user_name
        #redirects the user to our private page.
			redirect_to :action => 'private'
		else
			flash[:notice] = "Invalid User/Password"
			redirect_to :action=> 'login'
		end
end

Second method is for to handle the logout. When the logout link will be clicked, this method will be called. As you can see, we will reset the session created during authenticate method and redirect the user to the login page again.

  def logout
	  if session[:user_id]
		  reset_session
		  redirect_to :action=> 'login'
	  end
  end

Now to test the server. Run ruby script/server. You will see the usual Riding on Rails Page.
Point your browser to http://myserver.dev:3000/user/login to see the login page.

If you have followed all the steps properly, you`ll see that the login system is working fine, except for a lil important modifications.

First logout, then Try pointing your browser to http://myserver.dev:3000/user/private, you`ll notice that you are able to view the private page !!!
Lets rectify this problem

Step 7 : Modify the private method in user_controller.rb

Since we just have to protect one page, we can simply use an if statement to check the session and respectively allow or disallow them to view the private page. Remember we had created a private method in user_controller.rb (Our User Controller). So your new private method will look like the following

  def private
 	 if !session[:user_id]
    	redirect_to :action=> 'login'
	end
  end

Voila ! We have secured our private page. Finally

This is how your final User_controller.rb should look

class UserController < ApplicationController
def authenticate
		#User.new(params[:userform]) will create a new object of User, retrieve values from the form and store it variable @user.
		@user = User.new(params[:userform])
        #find records with username,password
		valid_user = User.find(:first,:conditions => ["user_name = ? and password = ?",@user.user_name, @user.password])

        #if statement checks whether valid_user exists or not
		if valid_user
        #creates a session with username
			session[:user_id]=valid_user.user_name
        #redirects the user to our private page.
			redirect_to :action => 'private'
		else
			flash[:notice] = "Invalid User/Password"
			redirect_to :action=> 'login'
		end
end

  def login
  end

  def private
  if !session[:user_id]
	redirect_to :action=> 'login'
	end
  end

  def logout
	  if session[:user_id]
		  reset_session
		  redirect_to :action=> 'login'
	  end
  end

end

Now to test the server again, Re-Run ruby script/server.
Try pointing your browser to http://myserver.dev:3000/user/private, you will see that you will be redirected to the login page (if you previously logged out, else if the session is still valid, you`ll see the private page).

Phew… Well thats about how to design the Login System in Ruby on Rails. If you guys have any problems, as usual you can always post a comment here. I`ll be posting another post on how to integrate this login system in our blog application.

Demo of the Login System in RoR : Click Here (user:admin,pass:admin)

Related Links

Tutorial : Create a blog using Ruby on Rails 2. (Part 1 – Relationships)
Tutorial : Basics on Ruby on Rails 2 Model, Controller and Views and Routing
Tutorial : Developing your First Ruby on Rails 2 Application
Tutorial : Installing Ruby on Rails 2 in Windows Vista/XP

This website uses IntenseDebate comments, but they are not currently loaded because either your browser doesn't support JavaScript, or they didn't load fast enough.

23 Responses to “Tutorial : Create a login system in Ruby on Rails”

  1. anderson
    January 25, 2010 at 1:56 pm

    the best tutorial on the net! :)
    thanks!

  2. Aneresia
    January 5, 2010 at 12:28 pm

    this is very helpful, but what if I want to protect a page with it's own controller, lets say I have disciplina_controller.rb (with index. show, edit) and I want to protect all of them(the page index, show and edit – they all already have listing and other things in the methods), what to do (I'm kinda trying to learn ruby now ) . Hope you understand what I'm trying to say. Thank you.

  3. Radek
    December 30, 2009 at 3:42 pm

    Wait… Are you really doing Rails developement on a Windows machine? Must be a hell xD

    By the way, nice tutorial! Thanks

  4. ROBERTA
    December 23, 2009 at 10:12 am

    ruby script/generate model user –skip-migration
    THIS work :)

  5. roberta
    December 23, 2009 at 10:08 am

    ruby script/generate model user –skip-migrations

    > invalid option: –skip-migrations

    not work for me…
    why?

  6. Alexander LJ
    November 25, 2009 at 8:40 pm

    Thanks alot for this great tutorial, no problem at all to modify it to my own script!

  7. guest
    November 23, 2009 at 8:09 am

    easy instructions – awaiting the blog integration

  8. bibhas
    November 9, 2009 at 7:08 am

    Thanx

  9. Toby Newman
    August 11, 2009 at 3:58 pm

    Excellent page, thank you. So many of the pages about authentication ask you to install plugins or gems or whatever. I don’t feel like I understand what something is doing unless I roll my own.

  10. Nem
    August 11, 2009 at 1:16 pm

    All I get is an error…

    LoadError in UserController#authenticate

    Expected C:/InstantRails/rails_apps/jong/app/models/user.rb to define User

    and now what?….

  11. Toby Newman
    August 6, 2009 at 4:14 pm

    I had to replace
    --skip-migrations
    with
    --skip-migration

  12. James
    July 16, 2009 at 2:43 pm

    its gonna be resourceful…I liked it so much…

  13. a
    May 15, 2009 at 8:35 am

    CREATE TABLE IF NOT EXISTS users (
    id int(11) NOT NULL auto_increment,
    user_name varchar(255) default NULL,
    password varchar(255) default NULL,
    role int(11) default NULL,
    created_at datetime default NULL,
    updated_at datetime default NULL,
    PRIMARY KEY (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

    INSERT INTO users (id, user_name, password, role, created_at, updated_at) VALUES
    (1, ‘admin’, ‘admin’, 0, NULL, NULL),
    (2, ‘test’, ‘test’, 1, NULL, NULL);

    –WHERE I CAN INSERT THIS?

    • Avinash
      July 9, 2009 at 12:42 pm

      for this u will have to type in your command prompt
      => mysql -u root -p
      then it will ask for password..enter that
      then create database as follows
      => create database login;
      then select the database as follows
      => USE login;
      then do as per the above steps..

  14. ryan
    March 30, 2009 at 10:41 pm

    this is very helpful. thanks a lot

  15. dana
    January 29, 2009 at 12:48 am

    thank you alot :)

  16. trand
    November 19, 2008 at 3:16 am

    How do you clear the text field and the password field on the login page?

  17. raj
    October 31, 2008 at 12:27 pm

    Suppose I have 2 role of user one is “admin” and second is “user”, then how can I differenciate the user to in which page to be sent

  18. Irfan
    October 9, 2008 at 9:24 pm

    This will not work with a RESTful compliant Rails Application as /users/login will be translated as ‘login’ being the id of a user!!! Do you have a work around? Like a named route or something?

    Thanks!

  19. dewynn
    September 30, 2008 at 2:06 pm

    who ever make this sample code of login system,you are so great…thanks for the code god blees…

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang=""> <del datetime=""> <em> <i> <p> <q cite=""> <strike> <strong>