Working on any web application, there is always a need to have user authentication system running in the application. Ruby on Rails is blessed to have a such an active community which always comes up with solutions to rails of any kind. For user authentication there is an awesome plugin called AuthLogic. I have used this plugin in an application I am currently associated with and it works like a charm.
In this post you can find step by step instruction on getting this plugin up and running in your application.
AuthLogic can either be installed as a plugin or as a gem. I would rather go with installing a gem. So from the command line:
After installing the gem, we will be creating a very simple rails application just to test the user authentication functionality via authlogic gem.
So from command line create a new application named user_authentication_demo
C:\>rails user_authentication_demo -d mysql
after the application is created, lets just go ahead and create a dummy controller dummy method in the controller and a dummy view. This is just to have a page up and running where we will be displaying the working of user authentication functionality.
So create a controller by:
C:\user_authentication_demo>ruby script/generate controller home index
You can add some dummy text in your app/views/index.html.erb file just for fun. Working on rails, you got enough time for fun stuffs !
(Make sure you have <%= flash[:notice] %> in there to get the flash messages)
Next open up the config/database.yml find athen replace the entire content here with the following code
development:
host: localhost
adapter: mysql
database: user_authentication_demo_development
port: 3307
username: root
password:
test:
host: localhost
adapter: mysql
production:
host: localhost
adapter: mysql
All I have done is removed unwanted junk of codes from there to keep it straight and simple.
Now if we run the server and go to http://localhost:3000/blog, we will be taken to the dummy page as shown below:
We will be adding the user authentication to the above page. In this page we will be showing "Register","Login" links if the user is not logged in and "Edit Profile","Logout" links if the user is logged in.
Next we need to create Model and Controller for Users. First we will be generating our User Model
C:\user_authentication_demo>ruby script/generate model user
After all the associated files are created, we will edit the migration file at db/migrate/20100103124423_create_users.rb and ad the following codes in it.
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :username
t.string :email
t.string :crypted_password
t.string :password_salt
t.string :persistence_token
t.timestamps
end
end
def self.down
drop_table :users
end
end
AuthLogic can pretty much handle fields called email, crypted_password, password_salt and persistence_token and hence we need not bother much about them So let's go ahead and run rake to create the database tables
C:\user_authentication_demo>rake db:migrate
Next we will have to edit the app/models/user.rb file and add the following codes in it
class User < ActiveRecord::Base
acts_as_authentic
end
This is to add the Authlogic to the class, without which it will be just a standard model class. Our next task is to create users controller. Also we require new and edit views, and hence we will make sure to create them through generators by the following command
C:\user_authentication_demo>ruby script/generate controller users new edit
Next we need to modify config/routes.rb file a bit and add the following line of code
map.resources :users
Now inorder to display the link for "Register" , in all the pages of your application add the following lines in your app/views/layouts/application.html.erb file(If you dont have application.html.erb file, then create it)
<%= link_to "Register", new_user_path %>
<%= yield %>
Next add the following bunch of code in app/controllers/user_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(params[:user])
if @user.save
flash[:notice] = "Registration successful."
redirect_to :controller=>"blog"
else
render :action => 'new'
end
end
def edit
end
end
We will be putting the code for registration in a partial as we will require it for registration as well as editing. So create a patial file in app/views/users/_user.html.erb and add the following codes in it.
<% form_for @user do |form| %>
<%= form.error_messages %>
- <%= form.label :username, "Username" %> <%= form.text_field :username %>
- <%= form.label :email, "Email" %> <%= form.text_field :email %>
- <%= form.label :password, "Password" %> <%= form.password_field :password %>
- <%= form.label :password_confirmation, "Password confirmation" %> <%= form.password_field :password_confirmation %>
- <%= form.submit "Submit" %>
<% end %>
And then add the following code in the app/views/users/new.html.erb to call the partial for registration purpose
<%= render @user %>
Now if we check http://localhost:3000/blog we will see the "register" link and if we click on the link, we will be taken to the registration form. If we click on the register button without entering any details, we will get the validation errors and if we enter valid data and then register we will be redirected to blog page. So far so good. next we will add a "Login" link next to "registration" link to let our users to login to the application. For this we have to create UserSession model to get the current status of our users. From the command line,
C:\user_authentication_demo>ruby script/generate session user_session
This generator will create UserSession model and this model will be just have an empty class. Next we generate controller for the UserSession
C:\user_authentication_demo>ruby script/generate controller UserSessions
And add the following codes within the UserSessions Controller
class UserSessionsController < ApplicationController
def new
@user_session = UserSession.new
end
def create
@user_session = UserSession.new(params[:user_session])
if @user_session.save
flash[:notice] = "Successfully logged in."
redirect_to :controller=>"blog"
else
render :action => 'new'
end
end
def destroy
@user_session = UserSession.find
@user_session.destroy
flash[:notice] = "Successfully logged out."
redirect_to :controller=>"blog"
end
end
Next create a view file in app/views/user_sessions/new.html.erb and add the following codes
<% form_for @user_session do |form| %>
<%= form.error_messages %>
- <%= form.label :username, "Username" %> <%= form.text_field :username %>
- <%= form.label :password, "Password" %> <%= form.password_field :password %>
- <%= form.submit "Submit" %>
<% end %>
We will have to edit the config/routes.rb a bit to add the following codes.
map.login 'login', :controller => 'user_sessions', :action => 'new'
map.logout 'logout', :controller => 'user_sessions', :action => 'destroy'
map.resources :user_sessions
We can also modify our application.rhtml file to add the link for login
<%= link_to "Register", new_user_path %> |
<%= link_to "Log in", login_path %>
Now if we check our blog page along with "Register" link we also ha "Login" link and if we click on "Login", we will be taken to a Login page with fields for username and password. Upon valid username and password entry, we will be taken to blog page with a flash message. On invalid login details, we will end up with validation errors. Our next aim is to write code for logging out and display "Edit Profile" and "Logout" Links for the logged in users. So let us modify the application.rhtml and have the following codes in there:
<% if current_user %>
<%= link_to "Edit profile", edit_user_path(:current) %>
<%= link_to "Logout", logout_path %>
<% else %>
<%= link_to "Register", new_user_path %>
<%= link_to "Log in", login_path %>
<% end %>
<%= yield %>
And also add the following code in the app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
helper_method :current_user
private
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
@current_user = current_user_session && current_user_session.record
end
end
To make the "Edit profile" working modify the user_session controller to
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(params[:user])
if @user.save
flash[:notice] = "Registration successful."
redirect_to :controller=>"blog"
else
render :action => 'new'
end
end
def edit
@user = current_user
end
def update
@user = current_user
if @user.update_attributes(params[:user])
flash[:notice] = "Successfully updated profile."
redirect_to :controller=>"blog"
else
render :action => 'edit'
end
end
end
And then we have to call the form partial by adding the following code within /app/views/users/edit.html.erb
<%= render @user %>
Thats it. We are set to go with our application with this wonderfull gem/plugin for the user authentication functionality.