This is Le Wagon's kick-off roadmap for the lead dev (in charge of setup / deployment / collaboration).
If you don't want to run these steps by hand, check out the wagon_rails gem to generate a new rails app, its github repo and its heroku app with all the specified instructions below (you won't get the Facebook connect setup though).
Create the project locally and on Github
$ rails new YOUR_APP_NAME -T --database=postgresql
$ cd YOUR_APP_NAME
$ git init
$ git add .
$ git commit -m "rails new"
$ hub create
$ git push -u origin master
Make sure you have the relevant ruby and rails version set in the Gemfile
# Gemfile
source 'https://rubygems.org'
ruby "2.2.0"
gem 'rails', '4.2.0'
Commit
$ git add .
$ git commit -m "setting ruby and rails versions"
Create the db locally
$ rake db:create
Add debug gems
# Gemfile
group :development do
gem "better_errors"
gem "binding_of_caller"
gem "quiet_assets"
gem "pry-rails"
gem "pry-byebug"
end
and commit
$ bundle install
$ git add .
$ git commit -m "Adding development gems"
Add front-end gems
# Gemfile
gem 'bootstrap-sass'
gem 'font-awesome-sass'
gem 'simple_form'
Generate simple form Bootstrap 3 initializer
$ bundle install
$ rails generate simple_form:install --bootstrap
Add Bootstrap sprockets directive in application.js
// app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require bootstrap-sprockets
//= require_tree .
Add viewport in layout application.html.erb
<!-- app/views/layouts/application.html.erb -->
<head>
<!-- Add these line for detecting device width -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
</head>
Add dynamic meta tags in your layout
<!-- app/views/layouts/application.html.erb -->
<head>
<title><%= yield(:title) || "Your App name" %></title>
<meta name="description" content="<%= (yield(:description) || "").squish %>">
<!-- [...] -->
</head>
Switch javascript application tag at the end of the body
and set an :after_js
block of code for page-specific javascript code
<!-- app/views/layouts/application.html.erb -->
<body>
<!-- [...] -->
<%= javascript_include_tag 'application' %>
<%= yield(:after_js) %>
</body>
Load our custom LeWagon's stylesheets:
$ rm -rf app/assets/stylesheets
$ curl -L https://github.com/lewagon/rails-stylesheets/archive/master.zip > app/assets/stylesheets.zip
$ cd app/assets && unzip stylesheets.zip && rm stylesheets.zip && mv rails-stylesheets-master stylesheets && cd ../..
And commit
$ git add .
$ git commit -m "Finishing front-end setup"
Make figaro install on master branch (to avoid leaks of API keys in application.yml
!!)
# Gemfile
gem "figaro"
Then add application.yml
in .gitignore
$ bundle install
$ figaro install
$ git add .
$ git commit -m "setting figaro on master branch"
Push your setup on Github
$ git push origin master
Then add your team-mates as collaborators and make them clone the repo!
# Gemfile
gem 'rails_12factor', group: :production
gem 'puma', group: :production
$ bundle install
$ curl -L https://gist.github.com/ssaunier/24bc1c4db955c19e3289/raw/install.sh | bash
$ git add .
$ git commit -m "Prepared for Heroku"
$ heroku create YOUR_APP_NAME --region eu
$ git push heroku master
# Gemfile
gem 'devise'
$ bundle install
$ rails generate devise:install
# config/initializers/devise.rb
# ==> Mailer Configuration
config.mailer_sender = 'contact@yourcompany.com'
Generate user model
$ rails generate devise User
$ rake db:migrate
Get a cool navbar and notices
<!-- app/views/layouts/application.html.erb -->
<%= render 'shared/navbar' %>
<%= render 'shared/notices' %>
<%= yield %>
Create shared/_navbar.html.erb
with our template
And add shared/_notices.html.erb
with Bootstrap alerts
<!-- app/views/shared/_notices.html.erb -->
<% if notice %>
<div class="alert alert-info alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<%= notice %>
</div>
<% end %>
<% if alert %>
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<%= alert %>
</div>
<% end %>
Customize devise views:
$ rails g devise:views
<!-- app/views/devise/registrations/new.html.erb -->
<div class="container">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<h2>Sign up</h2>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<%= f.input :email, required: true, autofocus: true %>
<%= f.input :password, required: true, hint: ("#{@minimum_password_length} characters minimum" if @validatable) %>
<%= f.input :password_confirmation, required: true %>
<%= f.button :submit, "Sign up", class: "btn btn-primary" %>
<% end %>
<%= render "devise/shared/links" %>
</div>
</div>
</div>
<!-- app/views/devise/sessions/new.html.erb -->
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-6 col-sm-offset-3">
<h2>Log in</h2>
<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<%= f.input :email, required: false, autofocus: true %>
<%= f.input :password, required: false %>
<%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %>
<%= f.button :submit, "Log in", class: "btn btn-primary" %>
<% end %>
<%= render "devise/shared/links" %>
</div>
</div>
</div>
Force login on your app controller
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_user!
end
And commit your work
$ git add .
$ git commit -m "Finish devise integration"
# Gemfile
gem 'omniauth-facebook'
$ bundle install
$ figaro install
Create you facebook app and set your development keys in application.yml
development:
FB_ID: "3************1"
FB_SECRET: "4************e"
Configure devise
# config/initializers/devise.rb
Devise.setup do |config|
config.omniauth :facebook, ENV["FB_ID"], ENV["FB_SECRET"], scope: 'email'
end
Change your devise routing to handle omniauth callbacks
# config/routes.rb
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
Change User
model
# app/models/user.rb
class User < ActiveRecord::Base
devise :omniauthable, :omniauth_providers => [ :facebook ]
end
Add facebook fields to users
table
$ rails g migration AddOmniauthToUsers provider uid picture name token token_expiry:datetime
$ rake db:migrate
And set a method on the User
model to record these fields from facebook callbacks
class User < ActiveRecord::Base
def self.find_for_facebook_oauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20] # Fake password for validation
user.name = auth.info.name
user.picture = auth.info.image
user.token = auth.credentials.token
user.token_expiry = Time.at(auth.credentials.expires_at)
end
end
end
Integrate this in your callbacks controller
# app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
user = User.find_for_facebook_oauth(request.env["omniauth.auth"])
if user.persisted?
sign_in_and_redirect user, event: :authentication
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
Change a bit your navbar code
<!-- Somewhere in your navbar -->
<!-- Regular login -->
<li>
<%= link_to "Connexion", new_user_session_path %>
</li>
<!-- Facebook login -->
<li>
<%= link_to "Connect with Facebook", user_omniauth_authorize_path(:facebook) %>
</li>
And insert your facebook profile in navbar
<!-- Somewhere in your navbar -->
<% if user_signed_in? %>
<%= image_tag current_user.picture, class: "img-avatar" %>
<% end %>
Commit your work:
$ git add .
$ git commit -m "adding fb connect"
When pushing on heroku, run the migrations and set the API keys of your production FB app on Heroku
$ git push heroku master
$ heroku run rake db:migrate
$ heroku config:set FB_ID=************ FB_SECRET=*********