How to develop a social network using Ruby on Rails

A tutorial on developing a social networking platform using Ruby on Rails.


TL;DR. Here is the source code on Github and working demo on Heroku.


I am a Rails fanboy. In my opinion Ruby on Rails is one of the best web development frameworks ever developed. I have been using Rails for more than a year and it’s quite exciting to work with it. Web development has become so much fun for me because of it.

For quite some time I have been thinking of writing a blog post on Rails. I am not writing the usual post on “How to develop a blogging platform under 5 minutes using Rails”. I wanna build something awesome and write a tutorial on it. The idea of developing a social networking platform has always excited me. So I am gonna try and build one using Rails.

Let the Hacking begin!

Prerequisites

Here are a few things to consider before we proceed with development —


Start Hacking

To create a new rails app run rails new socify. This will generate the app structure and the Gemfile which contains the default gemset that ships with rails.

Go into the app directory. The first thing we need to do is modify the default gemset. Just use this Gemfile which contains the required gems. To fetch the gems and resolve dependencies we use bundler. Note that we have bundler already installed during setup. Go ahead and type bundle install.

Note: For version control I use Git. You can using replace the default .gitignore with this one.

Run Rails:

The app has nothing so far since we haven’t added anything. Try running rails s and visit localhost:3000. This should display the default landing page that says —

Welcome Aboard. You're Riding Ruby on Rails!

Asset Pipeline:

The Rails Asset pipeline concatenates, minifies and serves the app’s assets. We can add the custom css and js files to the pipeline. First of all rename application.css to application.css.scss since we are going to write our styling in Sass. Also remove turbolinks(Not a big fan of it) from application.js. Include the required assets.

@import "bootstrap-sprockets";
@import "bootstrap";
@import "font-awesome";
@import "jquery.datetimepicker";
@import "*";
//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require bindWithDelay
//= require jquery.datetimepicker
//= require_tree .

The app still points to the welcome aboard page since the root_path is not configured yet. Let’s create a home controller with an action to serve as the landing page. Add a simple Navbar.

shared/_navbar.html.erb
rails g controller home front
Rails.application.routes.draw do
root to: 'home#front'
end

Authentication

And one more thing, Don't Reinvent the Wheel. We will try to follow this throughout the development of this app. So rather than solving a problem that already has an optimal solution we can re-use the solution. Always remember,

Don't Reinvent the Wheel &
Don't Repeat Yourself(DRY)

One such solution to authentication is Devise. Devise provides an excellent authentication mechanism by taking care of user authentication, security and session management. Great! Let’s use it.

Run rails g devise:install. There are a few things to configure after setting devise. Refer Getting started guide.

Things to configure after devise:install

Note: Okay, I got a really weird error which was caused due to a single line in application.rb [link]. Removed and everything works smooth now. Ignore if you are not facing it.

Generate devise user model using rails g devise user. Let’s add a few columns to the model by modifying the migration. Run rake db:migrate to create the users table with the respective fields.

devise_create_users migration

In addition to user validation, authentication & session management devise also handles user confirmation. Just adding :confirmable to user model will do the trick.

class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
end

Note: Don't forget to change config.reconfirmable to false in config/initializers/devise.rb.

Everything in devise works out-of-the-box. Don’t believe me? Try visiting http://localhost:3000/users/sign_in. You might see a form that devise has already generated behind the scenes. And for user sign_up http://localhost:3000/users/sign_up. Is this cool or what!

The real question you would have now is “Can we customize it?”. Of course we can. This generator rails g devise:views copies the default views to our app for us to override. We can use some boilerplate code for the forms. You can check it out here.

Since we are adding new attributes to devise forms we need to tell devise controllers which params to allow. Read more about strong params here.

configure devise permitted params

Posts & Events

Authenticated user needs a way to share content. To generate the basic CRUD for post lets use scaffolding. This will generate the model, controller, views along with the database migration. And since post belongs to the user model we can add a reference to it which will generate the necessary relations.

rails g scaffold post attachment:string content:text user:references
rake db:migrate

Create Post:

To create a new post add the following form to home/index.html.erb and in posts_controller handle it. Really straight forward!

Form to create new post & create action in posts_controller

When we do @post.save rails will automatically validate the post object based on the validations we have written in post model. If there are errors we will pass it along while redirecting.

Carrierwave:

To handle file uploads we can use carrierwave. With carrierwave file uploads are really easy to handle. Generate an uploader class which contains the necessary configuration to handle the file after upload. Now all we need to do is mount the uploader in the model.

rails g uploader avatar
class Post < ActiveRecord::Base
mount_uploader :attachment, AvatarUploader
end

Create Event:

Creating an event is similar to posts. Since they have a title and date we might need a datepicker to select date & time. I am just gonna use the following jQuery plugin https://github.com/xdan/datetimepicker. Add the assets to vendor/assets/ directory and include in application.js and application.css.scss. Format the date in the following format and let Rails take care of the rest.

(document).ready(function(){
$("#event_when").datetimepicker({
maxDate:'0',
format:'Y/m/d H:i'
});
});

Likes & Comments

Since we are building a social networking app it is really important to add likes and comments. I am not going to Reinvent the wheel as stated above. Checkout acts_as_votable and acts_as_commentable.

Likes:

Using acts_as_votable it’s really easy to add likes/votes to a model. The following commands will create votes table to store the likes info. Just add acts_as_votable to a model to make it votable.

rails generate acts_as_votable:migration
rake db:migrate

Generate a controller to handle like & unlike actions.

likes_controller.rb

Comments:

Acts_as_commentable works a bit differently although the setting up is pretty much the same. The following commands will generate comment model along with the migration for it.

rails g comment
rake db:migrate

Add acts_as_commentable to a model to make it commentable. Generate a controller to handle create and delete actions.

comments_controller.rb

Now we are pretty much done with likes and comments. Just add the forms to the views.

likes/_form.html.erb
comments/_form.html.erb

Notice that I am using remote:true, so forms will be submitted using Ajax. Checkout this article on how remote forms work using Ajax http://guides.rubyonrails.org/working_with_javascript_in_rails.html.


Relationships

Now to the most important part of the social app, relations. So far it’s just an app where people can post, like or comment. Adding relationships between users is what makes it a network. Add acts_as_follower. Oh yeah! There is a ruby gem for almost everything. That’s the best part of using rails.

rails generate acts_as_follower
class User < ActiveRecord::Base
acts_as_follower
acts_as_followable
end
follows_controller.rb
follows/_form.html.erb

That’s it. You can now start following any user.


Public Activity

The social app that we are building needs to keep track of more than just posts. If you notice facebook’s newsfeed it shows likes, comments, follows & much more. We will keep track of records using the public_activity gem. Refer the public activity wiki on Github for setting up & displaying activities.

rails g public_activity:migration
rake db:migrate

Add the following to the models you want to track activity, for example models/post.rb. And since the logged in user has created we add current_user as the owner for the tracked resource.

class Post < ActiveRecord::Base
include PublicActivity::Model
tracked only: [:create], owner: Proc.new{ |controller, model| controller.current_user }
end

We will fetch all the activities using PublicActivity::Activity::all in the index action of the home controller. Display the activities on the view using render_activities(@activities) https://github.com/chaps-io/public_activity#displaying-activities.

class HomeController < ApplicationController
respond_to :html, :js
def index
@activities = PublicActivity::Activity.all
end
end
<div id="activities">
<%= render_activities(@activities)%>
<div>

Note: Need to fetch based on whether user is logged in or not, but ok for the time being. Checkout the final code on Github.

Finally we need to create public_activity/model_name/ with views for each action. Checkout views/public_activity/ to see how it is handled. We can add public activity tracking to other activities such comments and events too.


NewsFeed

NewsFeed content differs based on user session. The front action serves as the front-page when user is not logged in. When logged in we show index action that lists activities created by the user’s friends.

But, we are not going to display all the records at once. This will increase the page load when data becomes huge. You guessed it! we will paginate the records using will_paginate.

home_controller.rb

Final Touches

Congratulations! You have built a social networking platform using Ruby on Rails.

Developed a Social network Like a Boss!

But looking at the site the design looks bad and also right now there is no permissions model. So let’s just add permissions and some basic styling so that it looks pretty.


Deploy

I always deploy my Rails app to Heroku.

Deploying a rails app on Heroku is too damn easy. All we have to do is to add a heroku app and push to it using Git. Create a new app on heroku, add rails app and push to heroku master.

heroku login
heroku git:remote -a [appname]
git push heroku master
heroku run rake db:migrate

Since our app sends email for confirmation & password recovery we need to add smtp config to config/environments/production.rb. I am just gonna use sendgrid for this. Also we are uploading media and heroku doesn't store it on the server. There is an addon called Cloudinary which we will use.

I think that’s pretty much it. Everything deployed and looks good.

Socify Landing page.

To populate mock data we will use a rake task under lib/tasks. We will use faker and populator to generate data.

rake fill:data

You may check out the source code on Github (under stable branch int the Repo) and demo deployed on Heroku. If you found this article useful please hit the Recommend button below to help me Spread the word. Cheers!