Build Instagram by Ruby on Rails (Part 1)

I’ll guide you step by step learning Ruby on Rails through building the Instagram application.

Luan Nguyen
Dec 3, 2018 · 14 min read

What’ll you learn after complete this project?

Table of Contents:

Tech Stacks

Back-end:

Front-end:

MVC (Model — View — Controller) in Ruby on Rails

Request-Response Cycle in Rails

Source: https://www.codecademy.com

Create New Rails Application

Install Rails:

gem install rails -v 5.2.1
rails --version=> Rails 5.2.1

Install PostgreSQL:

brew install postgresql
brew services start postgresql

Create a new Rails application

rails new instagram --version=5.2.1
cd instagram
bundle install
rails server

Create Homepage

rails g controller Home index
create  app/controllers/home_controller.rb
route get 'home/index'
invoke erb
create app/views/home
create app/views/home/index.html.erb
invoke test_unit
create test/controllers/home_controller_test.rb
invoke helper
create app/helpers/home_helper.rb
invoke test_unit
invoke assets
invoke coffee
create app/assets/javascripts/home.coffee
invoke scss
create app/assets/stylesheets/home.scss
<h1>This is my home page</h1>
Rails.application.routes.draw do
get 'home/index'
# For details on the DSL available within this file, see
http://guides.rubyonrails.org/routing.html
end
Rails.application.routes.draw do
get 'home/index'
root to: ‘home#index’
end
rails routes

Using PostgreSQL in Rails application

gem ‘pg’
default: &default
adapter: postgresql
pool: <%= ENV.fetch(“RAILS_MAX_THREADS”) { 5 } %>
timeout: 5000
development:
<<: *default
database: development_instagram
test:
<<: *default
database: test_instagram
production:
<<: *default
database: production_instagram
rails db:create>> Created database ‘development_instagram’
>> Created database ‘test_instagram’

Installing Bootstrap for Rails application

gem ‘bootstrap’, ‘~> 4.1.1’
@import "bootstrap";
gem 'jquery-rails'
//= require jquery3
//= require popper
//= require bootstrap

Layout application

Using Awesome Icon

gem 'font-awesome-rails'
@import "font-awesome";
app/assets/stylesheets/application.scss

Users: Sign Up — Sign In — Sign Out

Installing devise gem

gem 'devise'
rails generate devise:install

Set up the default URL options for the Devise mailer

config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

Generate User model

rails generate devise User
invoke active_record
create db/migrate/20180722043305_devise_create_users.rb
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
insert app/models/user.rb
route devise_for :users
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

Add sign in / sign out links

<a><i class=”fa fa-user”></i></a>
Sign In view
Sign Up view

Create User Profile Page

Add columns to User

rails g migration AddMoreFieldsToUsers username:string name:string website:string bio:text phone:integer gender:string
rails db:migrate== 20180813140820 AddMoreFieldsToUsers: migrating =============================— add_column(:users, :username, :string)-> 0.0333s— add_column(:users, :name, :string)-> 0.0006s== 20180813140820 AddMoreFieldsToUsers: migrated (0.0363s) ====================

Create User Controller

rails generate controller Users
class UsersController < ApplicationController
end
class UsersController < ApplicationController
def show
end
end
Rails.application.routes.draw do  ...  resources :users, only: [:show]end

Update User profile link in Navigation bar

Navigation bar
<!-- app/views/layouts/application.html.erb --><% if user_signed_in? %>
<a href=”<%= user_path(current_user)%>”>
<i class=”fa fa-user”></i>
</a>

<% else %>
<a href=”<%= new_user_session_path%>”>
<i class=”fa fa-sign-in”></i>
</a>
<% end %>

Create UI for User profile page

Mockup for Basic information section
# app/views/users/show.html.erb<div class="profile row">
<div class="col-md-4 avatar">
<!-- LEFT: AVATAR HERE -->
</div>
<div class="col-md-8 basic-info">
<!-- RIGHT: USER INFORMATION HERE -->
</div>
</div>
views/users/show.html.erb
@import "users";
Section 1: Basic information of User
<div class="user-tabs">
<a class="tab active" href="">
<i class="fa fa-th"></i>
POSTS
</a>
<a class="tab" href="">
<i class="fa fa-tv"></i>
IGTV
</a>
<a class="tab" href="">
<i class="fa fa-bookmark"></i>
SAVED
</a>
<a class="tab" href="">
<i class="fa fa-tag"></i>
TAGGED
</a>
</div>
.user-tabs{
border-top: 1px solid #efefef;
display: flex;
justify-content: center;
a.tab{
height: 35px;
margin-right: 50px;
line-height: 45px;
color: #999;
font-size: 12px;
font-weight: 500;
text-align: center;
i{
padding-right: 1px;
}
&:hover{
text-decoration: none;
}
}
a.active{
border-top: 1px solid #262626;
color: #262626;
}
}
<div class="user-images">
<div class="wrapper">
<img src="your_image_url">
</div>
<div class="wrapper">
<img src="your_image_url">
</div>
<div class="wrapper">
<img src="your_image_url">
</div>
</div>
.user-images{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 0 20px;
.wrapper{
width: 280px;
height: 280px;
margin: 15px;
img{
width: 100%;
border-radius: 4%;
}
}
}
User Profile page

Edit/Update User

Edit profile page

Step 1: Add Edit profile page

class UsersController < ApplicationController
...
def editend
end
resources :users, only: [:show, :edit]
rake routes 
...
...
edit_user GET /users/:id/edit(.:format) users#edit
<a class="edit-profile" href="<%= edit_user_path(current_user) %>">
<button>Edit Profile</button>
</a>

Step 2: Layout Edit profile page

The layout of Edit profile page.
<div class="user-edit-page">
<div class="actions">
<!-- Left column -->
</div>

<div class="details">
<!-- Right column -->
</div>
</div>
.user-edit-page{
display: flex;
margin-top: 60px;
min-height: 500px;

.actions{
width: 220px;
border: 1px solid #dbdbdb;
}
.details{
flex: 1;
border: 1px solid #dbdbdb;
border-left:none;
}
}

Step 3: Add navigation to the left of the page

.actions{
width: 220px;
border: 1px solid #dbdbdb;
.nav-link{
font-size: 14px;
background-color: white;
color: black;
border-radius: 0;
padding: 12px 0 12px 30px;
&:hover{
cursor: pointer;
}
}
.nav-pills .nav-link.active{
border-left: 2px solid;
font-weight: 600;
}
}
The Left of Edit profile page

Step 4: Add Form edit user to right of the page

def edit
@user = User.find(params[:id])
end
Form Edit User
.form-edit-user{
padding: 30px 100px 10px 50px;
.form-group, input{
font-size: 14px;
color: black;
}
input, textarea{
border: 1px solid #efefef;
}
.col-form-label{
text-align: right;
font-weight: 600;
}
.avatar{
height: 38px;
width: 38px;
border-radius: 50%;
}
.username{
font-size: 20px;
line-height: 22px;
margin-bottom: 0;
}
.change-photo{
color: #3897f0;
text-decoration: none;
font-size: 13px;
}
input[type='submit']{
color: white;
}
}
resources :users, only: [:show, :edit, :update]
def update
current_user.update(params[:user])
redirect_to current_user
end
Forbidden Attributes Error
params.require(:user).permit(:username, :name, :website, :bio, :email, :phone, :gender)
def update
current_user.update(user_params)
redirect_to current_user
end
privatedef user_params
params.require(:user).permit(:username, :name, :website,
:bio, :email, :phone, :gender)
end
<div class="col-md-8 basic-info">
<div class="user-wrapper">
<h2 class="username"><%= current_user.username %></h2>
...
</div>
... <h2 class="name"><%= current_user.name %></h2>
<%=link_to current_user.website, current_user.website, class: 'website' %>
</div>

Conclusion

Related posts:

References:

Luanotes

Sharing about Ruby on Rails, Design Pattern, Clean Code…

Luanotes

Sharing about Ruby on Rails, Design Pattern, Clean Code, Performance, Scalability.

Luan Nguyen

Written by

🚀 Software Engineer at ITviec — Interested in Ruby, Python, Design Pattern, Clean Code, TDD, Performance, Scalability — https://fullstackrubyonrails.com

Luanotes

Sharing about Ruby on Rails, Design Pattern, Clean Code, Performance, Scalability.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store