devise gemを使ってtwitter認証の設定

Railsでアプリケーション作る時にユーザー登録部分とか作るの面倒くさくって、ある程度出来上がってて組み込めば使えるってのが欲しかったので探したらdeviseっていう便利プラグインがあったので便利に使おうと使い方を学んだのでメモ

主にここの設定を真似てTwitter認証でユーザー登録が出来るアプリケーションのひな形作成(リンク先はFacebookの認証)
<https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview>

# Rails new

    rails new devise_app
    cd devise_app
    git init
    git add -A
    git commit -m 'first commit'

# devise gemの追加

    vi Gemfile  # devise,omniauth-twitterの追加

```ruby:Gemfile
gem 'devise'
gem 'omniauth-twitter'
```

    bundle install
    git add -A
    git commit -m 'add devise,omniauth-twitter'

# home controller の追加

    rails g controller home index
    vi config/routes.rb  # root "home#index" の追加

```ruby:config/routes.rb
DeviseApp::Application.routes.draw do
  root "home#index"
  get "home/index"
```

    git add -A
    git commit -m 'add controller home'

# devise install

ここまで下準備
ここからdeviseの設定

    rails g devise:install
    vi config/initializers/devise.rb  # config.omniauth :twitterの行追加

```ruby:config/initializers/devise.rb
  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
  config.omniauth :twitter, ENV['TWITTER_CONSUMER_KEY'], ENV['TWITTER_CONSUMER_SECRET'], display: 'popup'
```

こことかでTwitterの認証用キーの取得をするために`Create New App`をしておく。
<https://apps.twitter.com>

作成をした後に`Callback URL`の設定をしておく(とりあえず<http://localhost:3000>でもなんでもいい)設定しないとエラーが出てハマるので。

今回は作成するアプリケーションのログイン用に使うので`Settings`タブの`Allow this application to be used to Sign in with Twitter`のチェックを付けておいた方が、再度ログインしてきたユーザーが簡単便利になるのでチェックしといた方が良いかも。

    export TWITTER_CONSUMER_KEY={`取得したAPI key`}
    export TWITTER_CONSUMER_SECRET={`取得したAPI secret`}
    rails s

これで<http://localhost:3000>にアクセスして`Home#index`が出力されれば今のところ問題ない。
`C-c`してコミットする

    git add -A
    git commit -m 'add devise:install'

# user modelの追加

    rails g model user provider uid
    # rails g devise user とやりたいところだが、今回はtwitter認証のみなので省く。興味あると見てみると良い、オプションでログイン回数や最後にログインした時間、ログインしてきたipとか残せる。

    vi db/migrate/*_create_users.rb # 複数unique追加

```ruby:db/migrate/*_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :provider
      t.string :uid

      t.timestamps
    end
    add_index :users, [:provider, :uid], unique: true
  end
end
```

    rake db:migrate
    git add -A
    git commit -m 'add model user'

# callback時のログイン処理の実装

    mkdir app/controllers/users/
    vi app/controllers/users/omniauth_callbacks_controller.rb

```ruby:app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def twitter
    @user = User.find_or_create_by(user_params)

    if @user.persisted?
      sign_in_and_redirect @user, :event => :authentication
      set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format?
    else
      session["devise.twitter_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  private
  def user_params
    request.env["omniauth.auth"].slice(:provider, :uid).to_h
  end
end
```

    vi config/routes.rb # devise_for行の追加

```ruby:config/routes.rb
DeviseApp::Application.routes.draw do
  root "home#index"
  get "home/index"
  devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
```

    vi app/models/user.rb # devise :omniauthable 追加

```ruby:app/models/user.rb
class User < ActiveRecord::Base
  devise :omniauthable
end
```

    git add -A
    git commit -m 'user create'

# ログイン遷移

    vi app/views/layouts/application.html.erb

```ruby:app/views/layouts/application.html.erb

<% if user_signed_in? %>
    <%= link_to "Sign out", destroy_user_session_path %>
<% else %>
    <%= link_to "Sign in with Twitter", user_omniauth_authorize_path(:twitter) %>
<% end %>

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

```

    vi config/routes.rb # ログアウト処理、sign_outの追加

```ruby:config/routes.rb
DeviseApp::Application.routes.draw do
  root "home#index"
  get "home/index"
  devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
  devise_scope :user do
    get 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session
  end
```

    git add -A
    git commit -m 'sign in twitter'


viewファイル内では以下が

```ruby
user_signed_in?

current_user

user_session
```

controllerでは以下が使えるようになっています

```ruby
before_action :authenticate_user!
```

以上でログイン処理ができると思います。お疲れさまでした。


実際にこの手順で作ったアプリケーションがこちらになります。
<https://github.com/soramugi/devise_app>