Railsで新規アプリ作ってなんかサービス作ろうと思ったら、大体ログイン機能は作るだろうし、とりあえずBootstrap入れておきたいよねということで、Twitter IDでログイン出来るアプリのひな形を作る手順をメモしておきます。
DeviseとOmniAuthを利用します。
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で使うモジュールの選択
devise :database_authenticatable, :trackable, :omniauthable
OmniAuth用のrouting作成
devise_for :users, controllers: {
omniauth_callbacks: "users/omniauth_callbacks"
}
% mkdir app/controllers/users
% touch app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < ApplicationController
end
twitterのアプリ作成して、API KEYなど取得しておく。
deviseのomniauth設定
config.omniauth :twitter, ENV['APP_ID'], ENV['APP_SECRET']
キーをコードに入れたくないので、環境変数から取るようにした。
開発環境の環境変数はdotenv-railsで管理する。
group :development do
gem 'dotenv-rails'
end
APP_ID=HOGEHOGE
APP_SECRET=HOGEHOGEfu48rueufif
コード管理から外す
.env
Userモデルに、omniauth時に呼ばれるメソッドを作る
Userを返す。(無ければ作る)メソッド作成。
emailとパスワードはとりあえず使わないので、ユニークになる適当な値を突っ込む。
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する。
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。
#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していないとアクセス出来ないようにするには、コントローラに以下のように書けばいいです。
class HomeController < ApplicationController
before_action :authenticate_user!
end
これで、URL直接叩いてアクセスしようとすると、rootのpathへリダイレクトされます。
Bootstrap railsにあてる(余談)
Rails assetsを使ってbootstrap-sassを入れているので bundlerのバージョンを1.8.4以降にする必要があります。
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