Building Rails Portal (Rails 4.0)

Last updated: Aug 26, 2013.

For question/comments: twitter @indykish, email:

Our website:

Ruby Questions ? :

1.0 How did we build ours ?

It is so simple to create a front end portal using Ruby on Rails. Every start-up would like to have an out of box front-end running quickly with no hassles. Also as their core platform grows, a RESTful API is built which would be interfaced to multi-device front-ends.

We stumbled across ryan bates railcasts which covers pretty much the necessary ingredients you need. Love and salute ryan bates true giveback to the ruby community.

In this blog we would cover putting together a quick front-end to demonstrate to folks using twitter-boostrap 2.3.2 using a local authentication as well a social identity (such as facebook or twitter).

There are two projects that were built.

Launching Soon :

The following was built using the theme Genta

This slideshow requires JavaScript.

After integrating Measure theme, the rails app appears as follows.


After integrating Unicorn – Admin theme, the rails app appears as follows.


All start-ups have a common problem : Cash.

To building a well polished website for a launch, you need designers, and you  got to pay them big $. We did try to list our requirements and look for designers, but nothing worked to our budget/comfort level.

To eliminate this risk, we took a move to use twitter-bootstrap, and buy templates from as we knew the structure of the UI and what would work better. Migration of developer built UI to the theme template was easier.

Again, this will be the UI for our beta launch. Once things get going after a year, based on customers feedback the UI will get tweaked. This saved us a lot of $.

This helped us to focus on customer focused features.  Also the top 3 features were identified and illustrate pictorially by a top class freelance visual designer Saawan

Note: Our start-up team count = 3, with a few open source academy contributions.

1.1 Ruby gotchas for Java programmers.

To startwith, I didn’t like ruby on rails. The fundamental construct Ruby on Rails(RoR) was “conventions over configuration”.

As I started learning it, I dug deep “Ruby Programming Language” first. Then going after Rails was easier and started liking it since getting something quick and you can get support for anything you can think of..

Moral of the story we recommend the same learning focus as you did for J2EE – you need strong core Java (J2SE) skills, as J2EE is built on top of J2SE. The same applies for rails.

Few caveats to watch for when programming in Ruby.

Ruby removes unnecessary cruft: (){};
Parenthesis on method calls are optional; use print “hi”.
Semicolons aren’t needed after each line (crazy, I know).
Use “if then else end” rather than braces.
Parens aren’t needed around the conditions in if-then statements.
Methods automatically return the last line (call return explicitly if needed)
Those Funny Ruby Variables
x = 3 is a local variable for a method or block (gone when the method is done)
@x = 3 is a instance variable owned by each object (it sticks around)
@@x = 3 is a class variable shared by all objects (it sticks around, too).
:hello is a symbol, like a constant string. Useful for indexing hashes. Speaking of which…
dictionary = { :cat => “Goes meow”, :dog => “Barks loud.”} is a hash of key/value pairs. Access elements with dictionary[:cat].
For further refernce, click the link here

1.2 Pre requisite

Install Ruby 2.0 (latest – p247)

As of now we use Ruby 2.0 p247. Click here for the install instructions

Install Eclipse Kepler/Aptana Rubles Studio.

I installed “Eclipse Kepler  – Linux 64 bit version as our IDE (Integrated Development Environment). Click here to download the tar ball.

Install Aptanan Rubles Studio via Eclipse Update Site URL.

Please copy the Update Site URL to your clipboard and then follow the steps listed below to add this URL to your Available Software Sites list. Attempting to access this URL using your web browser will return an Access Denied error.

Install Ruby on Rails in Ubuntu 13.04.

Follow the instruction in sudobits blog. Thank you sudobit for the nice installer script.

How to install ruby on rails in Ubuntu 13.04 LTS = > link.

Let us create a ruby on rails app now. For the impatient 🙂 the source code is available in

2.0 Steps to create a Rails App called – “nilavu

First we need a web application in Rails to start with.

2.1 Create a directory ‘code‘ under your home.

$ mkdir code

2.2 Generate a new rails application named ‘nilavu

$ rails new nilavu

A whole big tree is auto generated as follows. 

├── app 
│   ├── controllers 
│   │   └── application_controller.rb 
│   ├── helpers 
│   │   └── application_helper.rb 
│   ├── mailers 
│   ├── models 
│   └── views 
│   └── layouts 
│   └── application.html.erb 
├── config │   
│   └── routes.rb 
├── Gemfile 
├── Rakefile 
├── README.rdoc 
├── test 
│   ├── fixtures 
│   ├── functional 
│   ├── integration 
│   ├── performance 
│   │   └── browsing_test.rb 
│   ├── test_helper.rb 
│   └── unit 
└── .... there are more files.

3.0 Hack the front end quickly.

  • Authentication
  • Landing Page
  • Footer/Header

We need to be able to attach authentication which are the typical uses cases you see when you pull your web site through.

A good amount of reference is available on the web. I salute Ryan Bates for his work on, it rocks !.

Authentication using omniauth – Part 1

Authentication using omniauth – Part 2

Github – OmniAuth

How to use omniauth to authenticate users.

We’ll go ahead and install the following gems.

3.1 Install twitter-bootstrap (2.3.2)

Soon we’ll migrate to bootstrap 3.0 as we are waiting for our themes to get migrated.

We’ll edit the Gemfile and include the following line.

gem 'twitter-bootstrap-rails'

We’ll run bootstrap as follows.

$ bundle update

$ rails g bootstrap:install

The bootstrap command produces a console output as follows.

insert app/assets/javascripts/application.js
create app/assets/javascripts/
create app/assets/stylesheets/bootstrap_and_overrides.css.less
gsub app/assets/stylesheets/application.css
gsub app/assets/stylesheets/application.css

The current version of twitter-bootstrap-rails has a few caveats to use glphicons and such. Read the
documentation from here.

If you need to customize the color of your navbar in twitter-bootstrap => link
3.2 Install omniauth

We’ll edit the Gemfile and include the following line.

gem 'omniauth'

gem 'omniauth-facebook'

gem 'omniauth-twitter'
$ bundle update

Now we’ll register with and and receive our secret keys and update the appropriate “CONSUMER_KEY, CONSUMER_SECRET” for twitter and “APP_ID, APP_SECRET” for facebook in omniauth.rb file.

Login to and click Apps.

Since we have created a key already, in this case we click Edit Settings.

Now pay attention to Login to a “App Domains” and “Site URL” and feed the appropriate value. In our case this is our local id or


Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, "CONSUMER_KEY", "CONSUMER_SECRET"
provider :facebook, "APP_ID", "APP_SECRET"

3.3 Let us start setting up the title “foo” by editing the application.html.erb.
Notice that the <body> contains a yield tag. yield identifies a section to be inserted from views. To learn more about yield, refer

 <%= stylesheet_link_tag "application", :media => "all" %>
 <%= javascript_include_tag "application" %>
 <%= csrf_meta_tags %></pre>
<div class="container">
<%= yield %></div>

3.4 Hmm, before we get to this application, let’s make the root url load our home page instead of the default Rails index file:

All you need to do is

$ rm public/index.html 

3.5 Generate a controller “home” containing an action “index”.

rails generate controller home index

The gem – high_voltage was used to setup static pages eg: Home, Getting started.

We need to wire the routes to say, when somebody comes to our home page, then route them to the index.

Edit routes.rb


Cloudauth::Application.routes.draw do
root :to => 'home#index'

3.6 We are set to all set to beautify the homepage.  

Let us edit the application.html.erb

    <!--[if lt IE 9]>
    <script src="" type="text/javascript">
    <%= stylesheet_link_tag    "application", :media => "all" %>
    <%= javascript_include_tag "application" %>
    <%= csrf_meta_tags %>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
          <a class="brand" href="#">megam</a>
<div class="nav-collapse">
<ul class="nav">
                <%= link_to "Products", products_path %></li>
                <%= link_to "About", products_path %></li>
                <%= link_to "Contact Us", products_path %></li>
<div class="container">
<div class="row">
<div class="span10">
<div class="row">
<div class="span6">
              blah..blah. level 2</div>
<div class="span6">
              b;aj...blah...blah.. level3</div>
      <%= yield %></div>
<div class="navbar navbar-fixed-bottom">
<div class="container">
        <a class="brand" href="#">megam</a>
<div class="nav-collapse"></div>

If you receive an error as below, then change
products_path in “<%= link_to “Products”, products_path %>” to #

NameError in Home#index

Showing /home/rammukund/code/cloudauth/app/views/layouts/application.html.erb where line #23 raised:

undefined local variable or method `products_path' for #<#:0x00000005301560>

You will see the screen as shown in 3.11 on fixing the error

3.7 Our application.html.erb is cluttered. Let us move the header stuff to _header.html.erb

<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
 <a class="brand" href="#">megam</a>
<div class="nav-collapse">
<ul class="nav">
	<li><%= link_to "Products", '#' %></li>
	<li><%= link_to "About", '#' %></li>
	<li><%= link_to "Contact Us", '#' %></li>

3.8 Let us move the footer stuff to _footer.html.erb

<div class="navbar navbar-fixed-bottom"><nav>
 © megam 2012
<ul class="nav pull-right">
	<li><%= link_to "About", '#' %></li>
	<li><%= link_to "Contact", '#' %></li>

3.9 Let us move the IE9 fix to _shim.html.erb

!--[if lt IE 9]>
<script type="text/javascript" src=""></script>

3.10 Our cleaned up application.html.erb

<%= full_title(yield(:title)) %>
		<%= stylesheet_link_tag    "application", :media => "all" %>
		<%= javascript_include_tag "application" %>
		<%= csrf_meta_tags %>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<%= render 'layouts/shim' %>

		<%= render 'layouts/header' %></pre>
<div class="container">
			<% flash.each do |key, value| %>
<div class="alert alert-error">
				<%= value %></div>
<div class="alert alert-<%= key %>"></div>
			<% end %>

			<%= yield %></div>

<hr />


		<%= render 'layouts/footer' %>

We found that during our “Measure Theme” integration, it is advisable to remove the
“<div class=”container”>” from application.html.erb.
3.11 Screenshot so far


4.0 Steps to wire Identity.

We wanted to use the following identity mechanisms.

Public local identity :This is the identity that you sigin as is associated with that <website> only.

Social identity : This is asking a <website> to trust the identity of facebook, twitter or any others.

To model and support the above, our information would be stored as follows.

├── Users : has many identities 
│   ├── Identity - belongs to Users 
│   │   ├── provider 
│   │   ├── name   
│   │   ├── emailid 

Generate a controller “sessions” containing an action “create”.

$ rails generate controller sessions create

Remember that the Social Identity will be handled by omniauth. Hence we would like to print the “omniauth.auth” hash to startwith.

def create
raise request.env["omniauth.auth"].to_yaml

Now edit routes.rb to add route for a callback when a session is created.


Cloudauth::Application.routes.draw do

root :to => 'home#index'

match '/auth/:provider/callback', :to => 'sessions#create'


Generate a controller “users” containing an action “new”

$ rails g controller Users new

We’ll go ahead create the required models.

$ rails g model user email:string password_hash:string password_salt:string

$ rake db:migrate

$ rails g model identity provider:string uid:string name:string

$ rake db:migrate

$ rails g controller identities

For more information on association read the Rails guide on association =>
4.1 Screenshot so far

Screenshot – signup


Screenshot – signin


Screenshot – signed out

Where do you want to wish to take your user.

In our case we built a dash board for the user to setup cloud identity.


The provisioning of instance based on the app platform  are automated using chef, using our custom scala cloud bridge  which uses Amazon EC2, ELB, Autoscaling and CloudWatch.

5.0 Steps to tweak migrations

We found having need to add a column or nuke a column in a table.This section provides insights on it.

Add a column name in Users table.

$ rails generate migration AddNameToUsers name:string

invoke active_record

create db/migrate/20120319163837_add_name_to_users.rb
$ rake db:migrate VERSION=20120319163837

== AddNameToUsers: migrating
-- add_column(:users, :name, :string)
->> 0.0006s

<span style="font-family: Liberation Serif, serif;">== AddNameToUsers: migrated (0.0007s) ======================================== </span>

To verify the database,

sqlite> .schema
CREATE TABLE "identities" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "provider" varchar(255), "uid" varchar(255), "name" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL);
CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "email" varchar(255), "password_hash" varchar(255), "password_salt" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, "name" varchar(255));
CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version");

To verify the migration status, the status basically shows the migrations that were run and their version(timestamp)

$ rake db:migrate:status

database: db/development.sqlite3

 Status   Migration ID    Migration Name
   up     20120316143814  ********** NO FILE **********
   up     20120316144326  ********** NO FILE **********
   up     20120319153913  Create users
   up     20120319154255  Create identities
   up     20120319163837  Add name to users

If the migration name is of the form “AddXXXToYYY” or “RemoveXXXFromYYY” and is followed by a list of column names and types then a migration containing the appropriate add_column and remove_column statements will be created.

The following migration removes user_id column from User table, removes users_id column from identities and adds an user_id to Identities table.

$ rails generate migration RemoveUserIdToUsers user_id:string
      invoke  active_record
      create    db/migrate/20120517020208_remove_user_id_to_users.rb
$ rails generate migration RemoveUsersIdToIdentities users_id:string
      invoke  active_record
      create    db/migrate/20120517023130_remove_users_id_to_identities.rb
$ rails generate migration AddUserIdToIdentities user_id:string
      invoke  active_record
      create    db/migrate/20120517023154_add_user_id_to_identities.rb
$ rake db:migrate
==  RemoveUserIdToUsers: migrating ============================================
-- remove_column(:users, :user_id)
   -> 0.0255s
==  RemoveUserIdToUsers: migrated (0.0256s) ===================================

==  RemoveUsersIdToIdentities: migrating ======================================
-- remove_column(:identities, :users_id)
   -> 0.0119s
==  RemoveUsersIdToIdentities: migrated (0.0121s) =============================

==  AddUserIdToIdentities: migrating ==========================================
-- add_column(:identities, :user_id, :string)
   -> 0.0005s
==  AddUserIdToIdentities: migrated (0.0006s) =================================

The addition and deletion of columns where bit tricky to me, that is the reason, I have covered the screen shots of every step.

For more information on migration Rails guide on migration =>

The table were moved to postgresSQL. Read our blog on “How to setup postgresSQL”.  DynamoDB was explored and we use that for some of our work.

6.0 Session controller changes

6.1 Authentication check for local identity (or) social identity.

Now omniauth includes a strategy to handle the local authentication which is called omniauth-identity as seen in railcasts – 304″.There are minor UI Look and Feel issues which cropped up during it usage.

We will go with authentication from scratch, (I don’t love too much auto handling as seen in omniauth-identity sometime).
Refer ryan’s railcast – 250 was which we implemented it the user model.

In the sessions controller if the “omniauth.auth” hash doesnot exists then we perform a local authentication.
If the “omniauth.auth” hash exists which means that the user attempted to authenticate using social identity such as facebook or twitter .. then we stick the verify the user in Identity model. At the end of successful authentication we stick the in session.

# verify if an omniauth.auth hash exists, if not consider it as a locally registered user.
    auth = request.env['omniauth.auth']
    # Find an identity here
      @identity = Identity.find_from_omniauth(auth)

      if @identity.nil?
        # If no identity was found, create a brand new one here
        @identity = Identity.create_from_omniauth(auth)
      # SQLLite doesn't support t.references and foreign key association. this is't needed if t.references is used in MySQL
      # Load the corresponding user and associate it in identity
        @user = User.find_by_id(@identity.user_id)
          logger.debug "Found user with id #{@identity.user_id}"
        @identity.user = @user
          raise RecordNotFound, "Invalid user. Oops this might be a system error ! Inform the administrator."

7.0 Troubleshooting

7.1 When connecting with facebook If you receive oauth 191 exception

To resolve this issue, type

$ ifconfig

Figure out the ipaddress, and in our case its, and include it in the
Site Url = (or) localhost:3000 and App Domain = (or) localhost in facebook pic as shown in section 3.2.

7.2 After authenticating, when the session tries to store stuff, if you receive a missing attribute exception

 Processing by SessionsController#create as HTML
  Parameters: {"code"=>"AQD6Nq-f6Qu9NXSc30KJ18BHjQE27Q5cWhPFxXrsHcE4BNilBsT8xhzbejAJjmrejalkfPKh4Jo12MyUHv1Qm91Mvm9kbrAKVmFJtXFTGtT8YHiCC0Vp62xEUHacfqkKM-A-fTHOaEJLyA1ZTSHVxntBLB4StBMjc24XglShWMTXJwIpPGefFisVM05mQv64uoo", "provider"=>"facebook"}
  Identity Load (0.1ms)  SELECT "identities".* FROM "identities" WHERE "identities"."provider" = 'facebook' AND "identities"."uid" = '100000174830089' LIMIT 1
   (0.1ms)  begin transaction
  User Exists (0.1ms)  SELECT 1 FROM "users" WHERE "users"."email" = '' LIMIT 1
   (0.0ms)  rollback transaction
Completed 500 Internal Server Error in 179ms

ActiveModel::MissingAttributeError (can't write unknown attribute `user_id'):
  app/models/identity.rb:9:in `create_from_omniauth'
  app/controllers/sessions_controller.rb:12:in `create'

7.3 The table structure for SQLlite is as follows. It doesn’t support foreign key.

 sqlite> .schema
CREATE TABLE "identities" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "users_id" integer, "provider" varchar(255), "uid" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);
CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "email" varchar(255), "password_hash" varchar(255), "password_salt" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, "name" varchar(255));

To resolve this problem, in the Identity model code, when a create is done ensure that :users_id => user[‘id’] is saved. This is due to the fact that SQLLite doesn’t offer foreign key support.

7.4 If you received a validation failed on password.

ActiveRecord::RecordInvalid in SessionsController#create

Validation failed: Password can't be blank

Rails.root: /home/rammukund/code/megam/identity/idportal
Application Trace | Framework Trace | Full Trace

app/models/identity.rb:11:in `create_from_omniauth'
app/controllers/sessions_controller.rb:13:in `create'

To resolve this problem change! to => false).

8.0 Finally : How to upload our project to Github.

Now caveat – Git is not a “centralized” source control as svn, cvs etc. It is distributed.
We have go to run through three scenarios.

Committing your initial code in Github.

Update the change code into Github.

Merge your project team mate’s source code.

8.1 Initial commit of our project in Github

We will create an account in Github. Follow the instructions as in the link here.

Let us set the user name and email in our local. To do that run the following commands.

$ git config --global "Kishorekumar Neelamegam"
$ git config --global ""

After you have setup a Github account, create a new repository.Type a repository name to your hearts content.

In this case I have typed “identityprov” 

Let us prepare for a local commit.

$ cd code\cloudauth
Update .gitignore which you can use to ignore files when you commit stuff in Github.

$ git init
Initialized empty Git repository in /home/ram/code/cloudauth/.git/
$ git add .

$ git commit
[master (root-commit) 07f9d36] Initial version of the identity provider portal for authentication.
 99 files changed, 1701 insertions(+)
 create mode 100644 .project
 create mode 100644 Gemfile
....several other files

Now our code is committed in the local system. We got to commit it in Github.

$ git remote add origin

$ git push -u origin master
ERROR: Hi indykish, it's GitHub. We're doing an SSH key audit.
Please visit
to approve this key so we know it's safe.
Fingerprint: 17:05:47:da:0d:7d:ae:bd:ce:85:bd:04:21:e1:0c:f9
fatal: The remote end hung up unexpectedly

This being our first commit, a verification of the figureprint is needed. Login to Github and verify the fingerprint.

Once the fingerprint is verified as shown in the picture below, the push happens successfully.Let us push the changes to Github.

$ git push -u origin master
Counting objects: 131, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (119/119), done.
Writing objects: 100% (131/131), 47.78 KiB, done.
Total 131 (delta 10), reused 0 (delta 0)
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

8.2 Well we want to update and send out updates to Github

Now that we have pushed the changes to Github ( Let us clone a copy in our local system. This may not be required since we already have a copy. This is more for your team mates or folks who wish to fork.

$ git clone
Cloning into 'identityprov'...
remote: Counting objects: 131, done.
Resolving deltas: 100% (10/10), done.

$ git remote add upstream

$ git fetch upstream
[new branch]      master     -> upstream/master

$ git merge upstream/master

$ git push origin master

For queries on fork refer this link

We tested and made sure it worked in facebook, local auth. twitter should work ok..

8.3 As the project’s maintainer, How do you merge your team/forked changes ?
As noted before, git goes by every repository is independent, yes its truly distributed. The steps are explained below. We need to associate remote forked repository.

  1. Let us say in our case my team mate prasads had forked our identityprov.git repository.
  2. “origin” shall point to indykish/indentityprov.git
  3. git remote -v => shows the remote repositories.
  4. A remote reference to is added by the name of prasad remote
  5. Let us commit indykish local changes in the local git
  6. Let us now fetch and merge the work areas of into our(indykish) local git
  7. If there are conflicts, we need to resolve them manually. When the conflicting files are opened the file has visible illustrations stating what needs to be resolved.
  8. Once the conflicts are resolved we’ll push all the local git changes of indykish to

The picture illustrates the steps followed by the actual git commands.

$ git remote add prasad

$ git remote -v
origin (fetch)
origin (push)
prasad (fetch)
prasad (push)
upstream (fetch)
upstream (push)

$ git add .

$ git commit

 13 files changed, 16 insertions(+), 66 deletions(-)
 delete mode 100644 config/initializers/omniauth.rb~

$ git fetch prasad
remote: Counting objects: 119, done.
   b422458..5b3c47b  master     -> prasad/master

$ git merge prasad/master
CONFLICT (content): Merge conflict in app/controllers/sessions_controller.rb
Auto-merging Gemfile.lock
CONFLICT (content): Merge conflict in Gemfile.lock
Automatic merge failed; fix conflicts and then commit the result.

$ git add .

$ git commit[master 3b146ba] Merge remote-tracking branch 'prasad/master'

$ git push -u origin master
Counting objects: 148, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (104/104), done.
Writing objects: 100% (106/106), 291.59 KiB, done.
Total 106 (delta 55), reused 0 (delta 0)
   b422458..3b146ba  master -> master
Branch master set up to track remote branch master from origin.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s