【Rails】omniauth-twitterでTwitterログインを実装する流れ

最近[Googleログインの実装](https://qiita.com/kenzoukenzou104809/items/c10a5642afbee93a961a)をやっていて、ついでにTwitterログインも実装しようとしたところ、躓いたのでメモしておきます。


## TwitterAPI準備

[Twitter Developers](https://apps.twitter.com/)

![Twitter_Developers.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348703/65173d04-6eca-a535-19ee-3460f2ff5506.jpeg)

![Twitter_Developers.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348703/1c8a7cc6-5b61-99de-9b0b-72e7ce12900f.jpeg)


## Gemfile編集

```ruby:Gemfile
gem 'omniauth'
gem 'omniauth-twitter'
gem 'devise'
gem 'dotenv-rails' #後で使う
```

```
$ bundle install
$ rails g devise:install
$ rails g devise user
$ rake db:migrate
```

## devise.rbの編集

```ruby:.env
TWITTER_ID='ペースト'
TWITTER_APP_SECRET='ペースト'
```

```ruby:.gitignore
/.env
```

```ruby:config/initializers/devise.rb
config.omniauth :twitter, ENV['TWITTER_ID'], ENV['TWITTER_APP_SECRET']

```


## user.rb編集

```ruby:user.rb
#以下を追記
protected
  def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first

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

  private

  def self.dumy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com" #POINT
  end
```

上記のように作成されるUserについては`self.dumy_email`によってダミーのメールアドレスを生成するようにしています。ここでは`auth.id`と`auth.provider`の組み合わせが一意であることを利用しています。

**Google/Facebookログインの実装では、`email: auth.info.email`でメールアドレスを取得できたのですが、TwitterAPIでは`nil`がかえってきてしまうため、上記のような実装が必要。**


## routes.rb編集

```ruby:routes.rb
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
```

## omniauth_callbacks_controller.rb実装

```ruby:app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
 
  def twitter
    callback_from :twitter
  end

  def callback_from(provider)
    provider = provider.to_s
    @user = User.find_for_oauth(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: provider.capitalize
      sign_in_and_redirect @user, event: :authentication
      session[:user_id] = @user.id #add
    else
      session['devise.#{provider}_data'] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end

```

## ログインリンク実装


```ruby:login_form.html.erb
<%= link_to 'Twitterログイン', user_twitter_omniauth_authorize_path  %>
```

## Herokuデプロイでエラーが出る場合

以下の記事の後半で、`Precompiling assets failed`というエラーが出た際の対処法をかいていますので、よかったらどうぞ。

[【Rails】Googleログイン実装〜Herokuデプロイまでの道のり](https://qiita.com/kenzoukenzou104809/items/c10a5642afbee93a961a#heroku%E3%81%B8%E3%81%AE%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%A7precompiling-assets-failed%E3%81%8C%E5%87%BA%E3%81%9F%E5%A0%B4%E5%90%88)

## heroku run rails db:migrate前にやること！

今回はTwitterAPI情報を`.gitignore`に指定しているので、Heroku側で設定する必要があります。

```
$ heroku config:set TWITTER_ID='ペースト'
$ heroku config:set TWITTER_APP_SECRET='ペースト'
$ heroku run rails db:migrate
```

## 参考リンク

[Devise+OmniAuthでユーザ認証を実装する手順](https://qiita.com/kami_zh/items/94aec2d94a2b4e9a1d0b#devise%E3%81%AE%E5%90%84%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%94%9F%E6%88%90)