Wednesday, November 28, 2012

Creating authentication from scratch in Rails 3.1

There are some popular authentication libraries like devise, Authlogic, Restful Authentication, Clearance in Ruby on Rails. But, you can implement of your own as well.

Here, I'm explaining few simple steps to create your own authentication system in Rails 3.1. First, Create Run following commands from command prompt and then copy the codes in the respective files:

Create new rails application
rails new rails3-auth-from-scratch

Generate user model/controller/views
rails g scaffold user first_name:string last_name:string email:string password_digest:string

Migrate database to create users table
rake db:migrate

Generate sessions controller
rails g controller sessions new

Modify user model by following codes in app/models/user.rb
class User < ActiveRecord::Base
  attr_accessible :email, :first_name, :last_name, :password_digest
  has_secure_password

  def name
    "#{first_name} #{last_name}"
  end

  def self.authenticate(email, password)
    find_by_email(email).try(:authenticate, password)
  end
end

Add bcrypt-ruby gem in to Gemfile to encrypt password and run bundle install
gem 'bcrypt-ruby'

Write/Copy following codes in app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery

  def authenticate!
    if !logged_in?
      redirect_to login_url, :alert => "You must login to access that page."
    end
  end

  private

  def logged_in?
    return true if current_user.present?
  end

  def current_user
    @current_user ||= User.find_by_email(session[:email]) if session[:user_id]
  end

  helper_method :current_user, :logged_in?
end

Authentication codes in app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  def new
  end

  def create
    # if the user is found and the user's password authenticates
    if user = User.authenticate(params[:email], params[:password])
      create_user_session(user)
    else
      flash.now.notice = "Invalid email or password"
      render "new"
    end
  end

  def destroy
    reset_session
    redirect_to root_url, :notice => "Logged out!"
  end

  private
  def create_user_session(user)
    session[:email] = user.email
    session[:user_id] = user.id
    redirect_to root_url, :notice => "Logged in!"
  end
end

Copy code snippet for login widget in app/views/sessions/new.html.erb
<%= form_tag sessions_path do %>
    
<%= label_tag :email %>
<%= text_field_tag :email %>
<%= label_tag :password %>
<%= password_field_tag :password %>
<%= submit_tag 'Login', :class => 'btn' %>
<% end %>

Update resources and path information in app/models/user.rb
resources :users
resources :sessions, :only => [:new, :create, :destroy]

get 'logout' => 'sessions#destroy', :as => 'logout'
get 'login' => 'sessions#new', :as => 'login'
get 'signup' => 'users#new', :as => 'signup'
post 'sessions' => 'sessions#create'

root :to => 'users#index'

Now, Run the application and go to "users/new" to create first user. After creating the user add following line at top of app/controllers/users-controller.rb to filter authenticated users:
before_filter :authenticate!

That's it. Now you refresh the browser and see the full functional authentication system.

Click here to checkout the full functional application with user management.

Monday, November 26, 2012

Rename rails3 application

Just published new version of rename gem with following changes:
  • Sanitize new name
  • Search/Replace module name in all files under root and config
  • Change session key
  • Change directory name

Installation
Add this line to your application's Gemfile:
gem 'rename'

Uses
rails g rename:app_to NewName
rails g rename:app_to "New-Name"