Edited at

Rails4.2.1 + Devise + Twitter 認証 (Bootstrapも入れる)

More than 3 years have passed since last update.

Railsで新規アプリ作ってなんかサービス作ろうと思ったら、大体ログイン機能は作るだろうし、とりあえずBootstrap入れておきたいよねということで、Twitter IDでログイン出来るアプリのひな形を作る手順をメモしておきます。

DeviseとOmniAuthを利用します。


Gemfile

gem 'devise'

gem 'omniauth-twitter'

% bundle install

% rails g devise:install

devise:installで色々指示が出てくる。

1はとりあえずメール飛ばしたりしないのでやらない。

2は言うとおりやる。

3は、後述のBootstrap Generatorでapplication.htmlを生成するのでやらない。

4はRails4なのでやらない。

5もtwitter認証でのログインしか作らないのでやらない。

      create  config/initializers/devise.rb

create config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

1. Ensure you have defined default url options in your environments files. Here
is an example of default_url_options appropriate for a development environment
in config/environments/development.rb:

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

In production, :host should be set to the actual host of your application.

2. Ensure you have defined root_url to *something* in your config/routes.rb.
For example:

root to: "home#index"

3. Ensure you have flash messages in app/views/layouts/application.html.erb.
For example:

<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

4. If you are deploying on Heroku with Rails 3.2 only, you may want to set:

config.assets.initialize_on_precompile = false

On config/application.rb forcing your application to not access the DB
or load models when precompiling your assets.

5. You can copy Devise views (for customization) to your app by running:

rails g devise:views

===============================================================================

home#indexを生成する

% rails g controller home index

モデルを生成して、認証に利用するカラムを追加する。

% rails g devise User

% rails g migration AddOmniauthToUser uid:string provider:string name:string

migrateファイルいじって、indexつける

class AddOmniauthToUser < ActiveRecord::Migration

def change
add_column :users, :uid, :string
add_column :users, :provider, :string
add_column :users, :name, :string

add_index :users, [:uid, :provider], unique: true
end
end

% rake db:create

% rake db:migrate

deviseで使うモジュールの選択


user.rb

  devise :database_authenticatable, :trackable, :omniauthable


OmniAuth用のrouting作成


routes.rb

  devise_for :users, controllers: {

omniauth_callbacks: "users/omniauth_callbacks"
}

% mkdir app/controllers/users

% touch app/controllers/users/omniauth_callbacks_controller.rb


omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < ApplicationController

end


twitterのアプリ作成して、API KEYなど取得しておく。

deviseのomniauth設定


initializers/devise.rb


config.omniauth :twitter, ENV['APP_ID'], ENV['APP_SECRET']


キーをコードに入れたくないので、環境変数から取るようにした。

開発環境の環境変数はdotenv-railsで管理する。


Gemfile

group :development do

gem 'dotenv-rails'
end

APP_ID=HOGEHOGE

APP_SECRET=HOGEHOGEfu48rueufif

コード管理から外す

.env

Userモデルに、omniauth時に呼ばれるメソッドを作る

Userを返す。(無ければ作る)メソッド作成。

emailとパスワードはとりあえず使わないので、ユニークになる適当な値を突っ込む。


user.rb

  def self.find_for_twitter_oauth(auth)

user = User.where(:provider => auth.provider, :uid => auth.uid).first
unless user
user = User.create(name: auth.info.nickname,
provider: auth.provider,
uid: auth.uid,
email: User.create_unique_email,
password: Devise.friendly_token[0,20]
)
end
user
end

def self.create_unique_string
SecureRandom.uuid
end

def self.create_unique_email
User.create_unique_string + "@example.com"
end


omniauthのcallback時の処理。Userを見つけるか、作るかして sign_inする。


omniauth_callbacks_controller.rb

  def twitter

@user = User.find_for_twitter_oauth(request.env["omniauth.auth"])
if @user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Twitter"
sign_in_and_redirect @user, :event => :authentication
else
redirect_to root_path
end
end

sign_inするためのリンクをViewに作る。

下記の余談にて、Bootstrap railsを当てている前提で、一番上のナビゲーションバーに sign_in, sign_outのリンクを作る。

sign_in時は twitter名を出して sign_in 出来ているのを分かるようにする。

9行目くらいからが追加した部分です。これで画面の右上に、Sign in with Twitter とか出ればOK。


application.html.haml

        #navbar.collapse.navbar-collapse

%ul.nav.navbar-nav
%li.active
%a{href: "#"} Home
%li
%a{href: "#about"} About
%li
%a{href: "#contact"} Contact
%ul.nav.navbar-nav.navbar-right
- if user_signed_in?
%li
%a{href: "#"}
= current_user.name
%li
= link_to "Sign out", destroy_user_session_path, :method => :delete
- else
%li
= link_to "Sign in with Twitter", user_omniauth_authorize_path(:twitter)


Sign inしていないとアクセス出来ないようにするには、コントローラに以下のように書けばいいです。


home_controller.rb

class HomeController < ApplicationController

before_action :authenticate_user!
end

これで、URL直接叩いてアクセスしようとすると、rootのpathへリダイレクトされます。


Bootstrap railsにあてる(余談)

Rails assetsを使ってbootstrap-sassを入れているので bundlerのバージョンを1.8.4以降にする必要があります。


Gemfile

gem 'bundler', '>= 1.8.4'

source 'https://rails-assets.org' do
gem 'rails-assets-bootstrap-sass'
end
gem 'bootstrap-generators'

gem 'haml-rails'


% rails g bootstrap:install -e haml

% rm app/views/layouts/application.html.erb