September 11th, 2008
Tutorial : Create a login system in Ruby on Rails
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.
-
Username : admin
Password : admin -
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.
- Login Page
- 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















August 20, 2010 at 6:59 am
Nice and easy, thanks for the great tutorial!
August 17, 2010 at 12:47 pm
its complete solution for me…thanx
August 11, 2010 at 11:02 am
Thanks!
Very good for me
July 13, 2010 at 1:00 pm
I'm getting an error 'unitialized constant UserController::USER' I can't workout why this is. Any ideas?
July 13, 2010 at 1:12 pm
just realised my model hadn't generated properly
July 13, 2010 at 1:58 am
Hey, thanks man, best login tutorial so far..
June 24, 2010 at 8:28 pm
Great tutorial, but if anybody is actually looking for a login system, I'd suggest taking a look at one of the many authentication plugins out there – Devise being probably the best one.
June 17, 2010 at 9:31 am
Quick question regarding layouts – the create.js.erb doesn’t seem to reuse the layout from new.html.erb, so any styling is lost if there is an error on login. Any tips on how to get this working?…..
May 6, 2010 at 2:43 pm
Thaaaanks
March 25, 2010 at 5:33 am
thanks! a lot , it was a nice tutorial
it is working fine but after implementation i noticed that by clicking back button of browser it leads us the to loged in page early we have signed out.
January 25, 2010 at 1:56 pm
the best tutorial on the net!
thanks!
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.
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
December 23, 2009 at 10:12 am
ruby script/generate model user –skip-migration
THIS work
December 23, 2009 at 10:08 am
ruby script/generate model user –skip-migrations
> invalid option: –skip-migrations
not work for me…
why?
November 25, 2009 at 8:40 pm
Thanks alot for this great tutorial, no problem at all to modify it to my own script!
November 23, 2009 at 8:09 am
easy instructions – awaiting the blog integration
November 9, 2009 at 7:08 am
Thanx
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.
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?….
August 6, 2009 at 4:14 pm
I had to replace
--skip-migrationswith
--skip-migrationJuly 16, 2009 at 2:43 pm
its gonna be resourceful…I liked it so much…
May 15, 2009 at 8:35 am
CREATE TABLE IF NOT EXISTS
users(idint(11) NOT NULL auto_increment,user_namevarchar(255) default NULL,passwordvarchar(255) default NULL,roleint(11) default NULL,created_atdatetime default NULL,updated_atdatetime 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?
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..
March 30, 2009 at 10:41 pm
this is very helpful. thanks a lot
January 29, 2009 at 12:48 am
thank you alot
November 19, 2008 at 3:16 am
How do you clear the text field and the password field on the login page?
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
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!
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…
July 1, 2009 at 7:59 pm
dasdasd
October 28, 2009 at 10:49 pm
Nice job