rails new <app name> --database=postgresql
Using the custom multiple database postgres docker image:
docker run -id --name rails-db -e POSTGRES_MULTIPLE_DATABASES="railyard-dev","railyard-test","railyard-prod" -e POSTGRES_USER=<database user> -e POSTGRES_PASSWORD=<password> -p 5434:5432 db:latest
Needs:
The callbacks are:
http://localhost:3000/users/auth/github/callback
http://localhost:3000/users/auth/twitter/callback
http://localhost:3000/users/auth/google_oauth2/callback
Twitter required extra permissions under the permissions
tab, Check the "request user email" box.
Initial setup:
#/.env
GITHUB_APP_ID=
GITHUB_APP_SECRET=
TWITTER_APP_ID=
TWITTER_APP_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
FACEBOOK_CLIENT_ID=
FACEBOOK_CLIENT_SECRET=
MAILER_DOMAIN=
MAILER_USERNAME=
MAILER_PASSWORD=
PUBLISHABLE_KEY=
SECRET_KEY=
echo "
gem 'rspec-rails'
gem 'devise'
gem 'omniauth-github'
gem 'omniauth-twitter'
gem 'omniauth-google-oauth2'
gem 'omniauth-facebook'
gem 'dotenv'
gem 'activerecord-session_store'
gem 'mailgun-ruby'
gem 'stripe'
gem 'jquery-rails'" >> Gemfile
bundle install
#/config/database.yml
default: &default
adapter: postgresql
encoding: unicode
pool: 5
timeout: 5000
username: worker
password: S0itg0es1
host: 127.0.0.1
port: 5434
development:
<<: *default
database: railyard-dev
test:
<<: *default
database: railyard-test
production:
<<: *default
database: railyard-prod
rails g controller home index
Edit config/routes.rb
:
Rails.application.routes.draw do
root 'home#index'
end
#/app/views/layouts/application.html.erb
<p class="navbar-text pull-right">
<% if user_signed_in? %>
Logged in as <strong><%= current_user.email %></strong>.
<%= link_to 'Edit profile', edit_user_registration_path, :class => 'navbar-link' %> |
<%= link_to "Logout", destroy_user_session_path, method: :delete, :class => 'navbar-link' %>
<% else %>
<%= link_to "Sign up", new_user_registration_path, :class => 'navbar-link' %> |
<%= link_to "Login", new_user_session_path, :class => 'navbar-link' %>
<% end %>
</p>
rails g devise:install
Migrations:
#add_providers
class UpdateUsers < ActiveRecord::Migration[5.2]
def change
add_column(:users, :provider, :string, limit: 50, null: false, default: '')
add_column(:users, :uid, :string, limit: 500, null: false, default: '')
end
end
#create_sessions
class CreateSessions < ActiveRecord::Migration[5.2]
def change
create_table :sessions do |t|
t.string :session_id, null: false
t.text :data
t.timestamps
end
add_index :sessions, :session_id, unique: true
add_index :sessions, :updated_at
end
end
#add_social_fields
class AddSocialToUsers < ActiveRecord::Migration[5.2]
def change
change_table :users do |t|
t.column :name, :string, :default => "None"
end
end
end
Setup:
#/config/initializers/devise.rb
config.omniauth :github, ENV['GITHUB_APP_ID'], ENV['GITHUB_APP_SECRET'], scope: 'user,public_repo'
config.omniauth :twitter, ENV['TWITTER_APP_ID'], ENV['TWITTER_APP_SECRET']
config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], scope: 'userinfo.email,userinfo.profile'
config.omniauth :facebook, ENV['FACEBOOK_CLIENT_ID'], ENV['FACEBOOK_CLIENT_SECRET'], scope: 'public_profile,email'
# Find and change these:
config.sign_out_via = :get
config.mailer_sender = '<mailgun email domain>'
config.parent_mailer = 'ActionMailer::Base'
config.reconfirmable = false
#/config/environments/development.rb
config.action_mailer.raise_delivery_errors = false
config.action_mailer.perform_caching = false
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.mailgun.org',
# port: 587,
domain: ENV['MAILER_DOMAIN'],
authentication: 'plain',
user_name: ENV['MAILER_USERNAME'],
password: ENV['MAILER_PASSWORD']
}
#/config/initialisers/session_store.rb
Rails.application.config.session_store :active_record_store, key: '_devise-omniauth_session'
Models:
#/app/models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable, :trackable, :omniauthable, omniauth_providers: [:github, :twitter]
def self.create_from_provider_data(provider_data)
where(provider: provider_data.provider, uid: provider_data.uid).first_or_create do | user |
user.email = provider_data.info.email
user.password = Devise.friendly_token[0, 20]
user.social_desc = provider_data.info.description
user.social_image = provider_data.info.image
user.social_location = provider_data.info.location
user.social_nickname = provider_data.info.nickname
user.skip_confirmation!
user.save
end
end
end
Controllers:
rails generate controller users/omniauth
#/config/controllers/user/omniauth_controller.rb
class Users::OmniauthController < Devise::RegistrationsController
# github callback
def github
@user = User.create_from_provider_data(request.env['omniauth.auth'])
if @user.persisted?
session[:info] = request.env['omniauth.auth']
sign_in_and_redirect @user
set_flash_message(:notice, :success, kind: 'Github') if is_navigational_format?
else
flash[:error] = 'There was a problem signing you in through Github. Please register or try signing in later.'
redirect_to new_user_registration_url
end
end
# twitter callback
def twitter
@user = User.create_from_provider_data(request.env['omniauth.auth'])
if @user.persisted?
session[:creds] = request.env['omniauth.auth']['extra']['access_token']
sign_in_and_redirect @user
set_flash_message(:notice, :success, kind: 'Twitter') if is_navigational_format?
else
flash[:error] = 'There was a problem signing you in through Twitter. Please register or try signing in later.'
redirect_to new_user_registration_url
end
end
# google callback
def google_oauth2
@user = User.create_from_provider_data(request.env['omniauth.auth'])
if @user.persisted?
sign_in_and_redirect @user
set_flash_message(:notice, :success, kind: 'Google') if is_navigational_format?
else
flash[:error] = 'There was a problem signing you in through Google. Please register or try signing in later.'
redirect_to new_user_registration_url
end
end
# facebook callback
def facebook
@user = User.create_from_provider_data(request.env['omniauth.auth'])
if @user.persisted?
sign_in_and_redirect @user
set_flash_message(:notice, :success, kind: 'Facebook') if is_navigational_format?
else
flash[:error] = 'There was a problem signing you in through Facebook. Please register or try signing in later.'
redirect_to new_user_registration_url
end
end
def failure
flash[:error] = 'There was a problem signing you in. Please register or try signing in later.'
redirect_to new_user_registration_url
end
end
Routes:
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth' }
rails generate scaffold Profile display_name:string location:string bio:text user:references
#/models/User
class User < ApplicationRecord
has_one :profile
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable, :trackable, :omniauthable, omniauth_providers: [:github, :twitter, :google_oauth2, :facebook]
def self.create_from_provider_data(provider_data)
where(provider: provider_data.provider, uid: provider_data.uid).first_or_create do | user |
user.email = provider_data.info.email
user.password = Devise.friendly_token[0, 20]
user.name = provider_data.info.name
user.skip_confirmation!
user.save
end
end
end
#/models/Profile
class Profile < ApplicationRecord
belongs_to :user
validates_associated :user
end
#/controllers/profile
# GET /profiles/new
def new
# @profile = Profile.new
@profile = current_user.build_profile
end
# GET /profiles/1/edit
def edit
@profile = current_user.profile.find(params[:id])
end
# POST /profiles
# POST /profiles.json
def create
# @profile = Profile.new(profile_params)
@profile = current_user.build_profile(profile_params)
respond_to do |format|
if @profile.save
format.html { redirect_to @profile, notice: 'Profile was successfully created.' }
format.json { render :show, status: :created, location: @profile }
else
format.html { render :new }
format.json { render json: @profile.errors, status: :unprocessable_entity }
end
end
end