学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

Rails6.1 | 民泊予約アプリ作成 | 25 | Facebook認証

↓↓クリックして頂けると励みになります。


24 | Google Maps】 << 【ホーム】 >> 【26 | Google認証



ユーザーは既にFacebookアカウントを持っていることが多いため、新しいウェブサイトやアプリケーションに登録やログインする際に新しい資格情報を作成する必要がなく、手間が省けます。
これにより、ユーザーエクスペリエンスが向上し、新規ユーザー獲得が容易になります。
また、Facebook認証を使用することで、ユーザーは簡単にウェブサイトやアプリケーション上のコンテンツをFacebookにシェアできます。
これにより、コンテンツが広まり、新しいユーザーが誘致される可能性が高まります。


まずはFacebook for Developersでアカウントを作成しなければなりません。
developers.facebook.com


アカウント、アプリの作成は以下の手順でお願いします。
mrradiology.hatenablog.jp


GemFileに以下の記述を追加します。


記述追加 GemFile(65行目)

gem 'omniauth', '~> 2.1', '>= 2.1.1'
gem 'omniauth-facebook', '~> 9.0'



コマンド
bundle


ユーザテーブルにプロバイダー認証のカラムを追加します。


コマンド(2つ)
rails g migration AddFacebookColumsToUser provider:string uid:string image:string


rails db:migrate


「config\initializers\devise.rb」に以下の記述を追加します。


記述追加 config\initializers\devise.rb(314行目)
「アプリID」と「app secret」はご自分のものを入れて下さい。

  # アプリIDとシークレットはご自分のものを入れてください。
  config.omniauth :facebook, "ご自分のアプリID", "ご自分のシークレット", 
                   scope: 'email', 
                   info_fields: 'email,name',
                   image_size: 'large'



「app\models\user.rb」ファイルに以下の記述を追加します。


1. 記述追加 app\models\user.rb(15行目)

  def self.from_omniauth(auth)
    user = User.where(email: auth.info.email).first

    if user
      return user
    else
      where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
        user.email = auth.info.email
        user.password = Devise.friendly_token[0, 20]
        user.full_name = auth.info.name   # ユーザーモデルに名前があると仮定
        user.image = auth.info.image # ユーザーモデルに画像があると仮定

        user.uid = auth.uid
        user.provider = auth.provider

      end
    end
  end



2.13行目に「, :omniauthable」の記述も追加しています。
カンマを忘れないようにして下さい。

, :omniauthable



記述追加 app\models\user.rb

class User < ApplicationRecord

  has_many :rooms

  has_one_attached :avatar

  validates :full_name, presence: true, length: {maximum: 50}

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :confirmable, :omniauthable

  def self.from_omniauth(auth)
    user = User.where(email: auth.info.email).first

    if user
      return user
    else
      where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
        user.email = auth.info.email
        user.password = Devise.friendly_token[0, 20]
        user.full_name = auth.info.name   # ユーザーモデルに名前があると仮定
        user.image = auth.info.image # ユーザーモデルに画像があると仮定

        user.uid = auth.uid
        user.provider = auth.provider
      end
    end
  end
  
end



「app\controllers」フォルダに「omniauth_callbacks_controller.rb」ファイルを新規作成して下さい。


app\controllers\omniauth_callbacks_controller.rb(新規作成したファイル)

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
    def facebook
 
      @user = User.from_omniauth(request.env["omniauth.auth"])
  
      if @user.persisted?
        sign_in_and_redirect @user, event: :authentication # @userがアクティブ化されていない場合
        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



「config/initializers」フォルダに、「omniauth.rb」ファイルを新規作成します。


新規作成 【config/initializers/omniauth.rb】

Rails.application.config.middleware.use OmniAuth::Builder do
  OmniAuth.config.allowed_request_methods = [:post, :get]
end



ルートを追加します。


「config\routes.rb」ファイルの記述を以下のように追加更新します。
「omniauth_callbacks: 'omniauth_callbacks'」の記述を追加しています。


追加更新 config\routes.rb(31行目)

 devise_for :users, 
              path: '', 
              path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'},
              controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'}



記述追加 【config/routes.rb】

Rails.application.routes.draw do

  # ルートを app\views\pages\home.html.erb に設定
  root 'pages#home'

  # get
  get '/dashboard', to: 'users#dashboard'
  get 'pages/home'
  get '/users/:id', to: 'users#show', as: 'user'

  # post
  post '/users/edit', to: 'users#update'

  resources :rooms, except: [:edit] do
    member do
      get 'listing'
      get 'pricing'
      get 'description'
      get 'photo_upload'
      get 'amenities'
      get 'location'
      delete :delete_photo
      post :upload_photo
    end
  end

  # device
  devise_for :users, 
              path: '', 
              path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'},
              controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'}
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end



アバター画像用のヘルパーを編集します。
FaceBookで登録してあるアバターの画像を表示させるようにしています。
「app/helpers/application_helper.rb」6行目

        elsif user.image?
            user.image



記述追加 【app/helpers/application_helper.rb】6行目

module ApplicationHelper

    def avatar_url(user)
        if user.avatar.attached?
            url_for(user.avatar)
        elsif user.image?
            user.image
        else
            ActionController::Base.helpers.asset_path('icon_default_avatar.jpg')
        end
    end    

    def room_cover(room)
        if room.photos.attached?
            url_for(room.photos[0])
        else
            ActionController::Base.helpers.asset_path('blank.jpg')
        end
    end

end



「Facebookでログイン」ボタンをつけます。


「app\views\devise\sessions\new.html.erb」ファイルに以下の記述を追加します。

         <div>
            <%= link_to user_facebook_omniauth_authorize_path, class: "btn btn-primary w-100" do %>
            <i class="fa-brands fa-facebook"></i><span style="margin-left: 1rem;">Facebookでログイン</span>
          <% end %>   
          </div>    



記述追加 app\views\devise\sessions\new.html.erb

<div class="container">
  <div class="row gx-5">
    <div class="col">
      <div class="card w-100 mb-3">
        <div class="card-body">
          <h5 class="card-title text-danger h3"><strong><span class="ttl">ログイン</span></strong></h5>
          <p class="card-text">作成したアカウントでログインしてください。</p>

          <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
      
            <div class="mb-5 mt-5">

            <div class="mb-5">
              <label for="exampleInputEmail1" class="ttl">Eメールアドレス</label>
              <%= f.email_field :email, autofocus: true, placeholder: "Eメールアドレス", class: "form-control" %>
              <div id="emailHelp" class="form-text">あなたのメールは他の誰とも共有しません。</div>
            </div>

            <div class="mb-5">
              <label for="exampleInputEmail1" class="ttl">パスワード</label>
              <%= f.password_field :password, autocomplete: "off", placeholder: "パスワード", class: "form-control" %>
              <div id="emailHelp" class="form-text">登録した6文字以上のパスワード入力が必要です。</div>
            </div>          

            <% if devise_mapping.rememberable? %>
            <div class="field mb-5">
              <%= f.check_box :remember_me %>
              ログインを保持
            </div>
            <% end %>
            
            <%= f.submit "ログイン", class: "btn btn-danger w-100" %>

          <% end %>

          <div class="mt-4">
            <%= render "devise/shared/links" %>
          </div>

        </div>
      </div>
    </div>

    <div class="col">
      <div class="card w-100 mb-5">
        <div class="card-body">
          <h5 class="card-title text-dark h6">下記サービスアカウントでのログインはこちら</h5>
          <div>
            <%= link_to user_facebook_omniauth_authorize_path, class: "btn btn-primary w-100" do %>
            <i class="fa-brands fa-facebook"></i><span style="margin-left: 1rem;">Facebookでログイン</span>
          <% end %>   
          </div>     
      
        </div>
      </div>        
    </div>

  </div>
</div>



「app\views\devise\registrations\new.html.erb」ファイルにも以下の記述を追加します。

         <div>
            <%= link_to user_facebook_omniauth_authorize_path, class: "btn btn-primary w-100" do %>
            <i class="fa-brands fa-facebook"></i><span style="margin-left: 1rem;">Facebookで新規登録</span>
          <% end %>   
          </div>    



記述追加 app\views\devise\registrations\new.html.erb

<div class="container px-4 mt-4">
  <div class="row gx-5">
    <div class="col">

      <div class="card w-100 mb-3">
        <div class="card-body">
          <h5 class="card-title text-danger h3"><strong><span>新規登録</span></strong></h5>
          <p class="card-text"><strong>ユーザー登録おねがいしやす</p>

          <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
      
            <div class="mb-5 mt-5">
              <label for="exampleInputEmail1">氏名</label>
              <%= f.text_field :full_name, autofocus: true, placeholder: "氏名", class: "form-control" %>
              <div id="emailHelp" class="form-text">氏名を必ず登録しましょ</div>
            </div>

            <div class="mb-5">
              <label for="exampleInputEmail1">Eメールアドレス</label>
              <%= f.email_field :email, autofocus: true, placeholder: "Eメールアドレス", class: "form-control" %>
              <div id="emailHelp" class="form-text">メルアドは絶対</div>
            </div>

            <div class="mb-3">
              <label for="exampleInputEmail1" class="ttl">パスワード</label>
              <%= f.password_field :password, autocomplete: "off", placeholder: "パスワード", class: "form-control" %>
              <div id="emailHelp" class="form-text">強力なセキュリティを確保するために、最低でも6文字以上のパスワードが必要です。</div>
            </div>          

            <div class="mb-5">
              <label for="exampleInputEmail1" class="ttl">パスワード確認</label>
              <%= f.password_field :password_confirmation, autocomplete: "off", placeholder: "パスワード確認", class: "form-control" %>
              <div id="emailHelp" class="form-text">パスワード確認: 確認のため、入力したパスワードをもう一度入力してください。同じパスワードを入力する必要があります。</div>
            </div>
            

              <%= f.submit "登録", class: "btn btn-danger w-100" %>

          <% end %>

          <div class="mt-4">
            <%= render "devise/shared/links" %>
          </div>

        </div>
      </div>
    
      <!--  SNS認証 -->
      <div class="card w-100 mb-5">
        <div class="card-body">
          <h5 class="card-title text-dark h6">下記サービスアカウントでの登録はこちら</h5>
          <div>
            <%= link_to user_facebook_omniauth_authorize_path, class: "btn btn-primary w-100" do %>
              <i class="fa-brands fa-facebook"></i><span style="margin-left: 1rem;">Facebookで新規登録</span>
            <% end %>   
          </div>    
      </div>    

    </div>

  </div>
</div>


もしFacebookアカウントのメールアドレスがこのテストサイトで登録したメールアドレスと重複している場合は一度「Postico」でユーザを削除してからテストしてください。

ユーザ削除
ユーザ削除



ブラウザ確認
http://localhost:3000/register

PCレイアウト
PCレイアウト


モバイルレイアウト
モバイルレイアウト



Facebook認証でログインするとプロバイダカラムにデータが格納されます。
メールでのアカウント有効化も必要です。
動作を確認してください。

Facebook認証成功
Facebook認証成功



24 | Google Maps】 << 【ホーム】 >> 【26 | Google認証


↓↓クリックして頂けると励みになります。

YAE C5 CLINIC(札幌美容クリニック)

関連記事(外部サイト)