[ Rails ] Deviseによる3分Facebookログイン(開発初心者向け)

　
Facebookログイン機能、あったら便利ですよね。
でも、クイックスタート参照してもできない...リモートでバグる...などAPIの導入はそれなりに骨が折れます。
ただ、deviseの力を借り、少し仕組みがわかれば、初心者でも環境問わず、3分でできます！

# 事前準備
## Facebook for developpersに登録
## 1.まずアカウント登録しアプリケーションを登録する。
ダッシュボードを参照。自分のアプリケーションの登録を確認。
![スクリーンショット 2017-09-16 20.50.12.png](https://qiita-image-store.s3.amazonaws.com/0/187392/e04e1c4c-e5da-d70b-3124-9e515c55ed88.png)

## 2.サイトURLを登録する。
ローカル環境で動かしたければlocalhost、production環境で動かしたければURLをそのまま貼り付けます。
表示名、アプリアイコンは良きタイミングで。
![スクリーンショット 2017-09-16 20.50.25.png](https://qiita-image-store.s3.amazonaws.com/0/187392/22e76ae9-5765-d267-0c38-130a280d7392.png)

## 3.本番環境への移行
リモートで動かしたいのであれば、追加で以下のように登録ステータスを開発環境から本番環境へ変更しなければなりません
![スクリーンショット 2017-09-16 20.51.48.png](https://qiita-image-store.s3.amazonaws.com/0/187392/adfcc0f8-2a0b-cd81-a915-113eb354f1e0.png)

# コード記述
- local、production共通です。
- devise導入済み、データベース、アプリケーションは生成済みとします。
- devise管理下のmodel,tableはuserと仮定します
- デプロイ先はherokuと仮定します。
- アプリIDとパスワードは環境変数に入れてあげましょう。


## 1.gemをインストールします。

```ruby:Gemfile
gem 'omniauth'
gem 'omniauth-facebook'
```


## 2.usersテーブルに以下のカラムを追加します。

```ruby:AddOmniauthToUser.rb
class AddOmniauthToUsers < ActiveRecord::Migration[5.0]
  def change
    # omniauthプロバイダー情報(今回はFacebook)
    add_column :users, :provider, :string
    # omniauthログイン用インデックス
    add_column :users, :uid, :string
  end
end
```

## 3.deviseの設定ファイルに以下の記述をご自身のAPIキーとともに追記してください。

```ruby:devise.rb
require 'omniauth'
require 'omniauth-facebook'

config.omniauth :facebook,'アプリIDが入ります','app secretが入ります'
```

## 4.デバイスが自動生成してくれるモデルの設定を以下のように追記します。

```ruby:user.rb
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
```
↓

```ruby:user.rb
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,:omniauthable, omniauth_providers: [:facebook]
```
```ruby:user.rb
#Facebookログインへの橋渡し
  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      user.name = auth.info.name
      user.email = auth.info.email
      user.password = Devise.friendly_token[0,20]
      # imageカラムの場合この記述(筆者のUploderはキャリアウェーブ)
      user.remote_image_url = auth.info.image.gsub('http://','https://')
    end
  end
```

## 5.コマンドプロンプトからrails g devise:controllers usersでdevise内部のomniauth controllerを引っ張り出します。
### facebookでのログイン方式を以下のように指定。

```ruby:omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def facebook
    @user = User.from_omniauth(request.env["omniauth.auth"])#ここでモデルに記述した橋渡しメソッドを使用
    if @user.persisted?
      sign_in_and_redirect @user, :event => :authentication 
      set_flash_message(:notice, :success, :kind => "Facebook")  if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end

end
```

## 6.デバイスのコントローラーをカスタマイズしたので、deviseにそれを教えてあげましょう。
### 他のコントローラーを編集する場合にもこの作業は必要になります。

```ruby:route.rb 
devise_for :users,:controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
```

## 7.assets/javascript配下にアプリIDとともに、以下のjsファイルを設置してあげましょう。
### 以下のjsファイルがFacebook SDKとあなたのアプリケーションをつなげます。

```ruby:facebook.js 
$(function(){
  window.fbAsyncInit = function() {
    FB.init({
      appId      : 'あなたのアプリケーションIDが入ります',
      cookie     : true,
      xfbml      : true,
      version    : 'v2.8'
    });
    FB.AppEvents.logPageView();
  };

  (function(d, s, id){
     var js, fjs = d.getElementsByTagName(s)[0];
     if (d.getElementById(id)) {return;}
     js = d.createElement(s); js.id = id;
     js.src = "//connect.facebook.net/en_US/sdk.js";
     fjs.parentNode.insertBefore(js, fjs);
   }(document, 'script', 'facebook-jssdk'));

  function checkLoginState() {
  FB.getLoginStatus(function(response) {
    statusChangeCallback(response);
  });
}

});
```

##　8.実装したい箇所のビューファイルに以下の記述でボタンを設置します。
### ルーティングのprefixはrails routesにてご確認ください。

 ```ruby:実装したい.haml 
= link_to "Facebookでログイン", user_facebook_omniauth_authorize_path, class: "login-button facebook" ,method: :post
```
　
#### 以上で完成です。簡易的ですがこれでFacebookログインが可能となります。　　
#### 不明点や、追記した方がいい部分があればコメントいただければ幸いです。