作って学ぶRuby on Rails Vol.28ログイン機能を実装しよう!その3


作って学ぶRuby on Rails Vol.28ログイン機能を実装しよう!その3
目次
  1. Google認証実装のつづき

Google認証実装のつづき

Ruby_on_Rails_login-実装-5

でUnknownactionというエラーが表示されているので、Actionを作成していきます。前項

app/controllersディレクトリにomniauth_callbacks_controller.rbというファイル名で新しいControllerを作成して下さい。

Ruby_on_Rails_login-実装-6

作成できたら、内容は下記になります。


class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google_oauth2
  @account = SocialAccount.find_for_google_oauth2(request.env["omniauth.auth"])

  if @account.present?
  # ユーザーをサインイン状態にする
  sign_in(:social_account, @account)
  # 自分の詳細情報ページに遷移する
  redirect_to user_path(@account.user)
  # 認証失敗時
  else
  redirect_to root_path
  end
  end
end

google_oauth2というメソッドを定義するのですが、その中で先ほど作成したSocialAccountというModelのfind_for_google_oauth2というメソッドを実行します。

find_for_google_oauth2メソッドはまだ作成していないので、この時点で実行してもエラーとなりますが、find_for_google_oauth2メソッドの実行結果としては

Googleで認証されたアカウント情報が、@accountに入ることになります。

正しくアカウントが認証されていれば、sign_inメソッドでサインイン(ログイン)状態にします。sign_inメソッドはdeviseが提供する機能です。後述しますが、sign_inを行うことで、social_account_signed_in?というメソッドでそのアカウントがログイン状態かどうかの判定を行うことができるようになります。

sign_inメソッドを実行後、redirect_toメソッドでuser_path(ユーザーの詳細情報ページ)に遷移するようにしています。

つまり、Google認証後、自動的に自分の自己紹介ページに遷移するということになります。

Actionが作成できたので、続いて、config/routes.rbを開き、ルーティングを登録します。


Rails.application.routes.draw do
  devise_for :social_accounts
  root "top#index"
  get "top/profile"
  resources :users
end

現状、上記コードのようになっているかと思います。

下記コードのハイライト部分を追記して、Google認証後に自分のWebアプリケーションに戻ってくる際のルーティングを設定します。


Rails.application.routes.draw do
  devise_for :social_accounts, controllers: {
  omniauth_callbacks: "omniauth_callbacks"
  }
  root "top#index"
  get "top/profile"
  resources :users
end

上記の指定は、Google認証後、omniauth_controller.rbのControllerが呼ばれるようになります。また、その際はomniauthの定義により自動的にgoogle_oauth2というActionが実行されます。

最後に、Modelを編集します。

UserというModelと、SocialAccountというModelの2つを編集するのですが、まずはapp/models/user.rbを開き、UserというModelを編集していきます。


class User < ActiveRecord::Base
  enum gender: { unknown: 0, male: 1, female: 2, other: 9 }

  has_one :social_account

  # ユーザー名による絞り込み
  scope :get_by_name, ->(name) {
  where("name like ?", "%#{name}%")
  }
  # 性別による絞り込み
  scope :get_by_gender, ->(gender) {
  where(gender: gender)
  }
  # 画像の保存設定
  has_attached_file :image,
  styles: { medium: "300x300>", thumb: "200x200>" },
  path: "#{Rails.root}/public/system/:class/image/:id.:style.:extension",
  url: "/system/:class/image/:id.:style.:extension"

  validates_attachment_content_type :image, content_type: /image/

end

上記コードのハイライト部分をUserというModelに追記して下さい。has_oneという記述は、ユーザー情報に対して、Googleアカウントを1つ紐付けるという意味になります。

つまり、1つのGoogleアカウントに対して1人のユーザーのみ作成可能ということになります。

続いて、app/models/social_account.rbを開き、SocialAccountというModelを編集します。


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

  # ユーザー情報に紐づく
  belongs_to :user

  # Google認証結果を取得
  def self.find_for_google_oauth2(auth)
  account = SocialAccount.where(email: auth.info.email).first

  unless account
  # ユーザー情報を作成する
  user = User.create(name: auth.info.name)
  # アカウント情報を作成する
  account = SocialAccount.create(name: auth.info.name,
  user_id: user.id,
  provider: auth.provider,
  uid: auth.uid,
  email: auth.info.email,
  token: auth.credentials.token,
  password: Devise.friendly_token[0, 20])
  end
  account
  end
end

UserというModelにはhas_oneという記述をしましたが、SocialAccountというModelにはbelogs_toという記述があります。これは、直訳すると「属している」という意味です。つまりSocialAccountというModelは、UserというModelに属していることを表します。

先ほど、find_for_google_oauth2というメソッドをActionから呼び出すように記述しましたが、呼び出される側を記述していきます。

まずSocialAccount.whereという記述で、既にアカウント情報が登録されているかを確認します。既に登録されていた場合はそのままアカウント情報を戻り値として返却します。

アカウント情報が未登録だった場合は、新たにUserというModelとSocialAccountというModelを利用してユーザー情報を登録します。

この際、UserというModelに対してはname(ユーザー名)のみ登録し、SocialAccountというModelにはGoogleで認証済みのアカウント情報を登録します。この際、user_idにUserというModelを登録した際に付与されたidを登録します。こうすることで、UserというModelのidと、SocialAccountというModelのuser_idが共通になり同じユーザーとして扱うことができるようになります。

ここで一度、ブラウザで確認してみましょう。

Ruby_on_Rails_login-実装-7

上の図のように複数のアカウントでGoogleにログインしている場合は、ログインするユーザーを選択して下さい。

下の図のように、ユーザーの詳細情報ページに遷移し、自分の名前が表示されていれば成功です。

Ruby_on_Rails_login-実装-8

※xxxxxは各環境により異なります。

上記のURLを参照すると、ユーザーの一覧画面が表示され、今登録したユーザーも一覧に表示されているはずです。また、編集も可能になります。

本項は以上で終了です。

とても難しい作業だったとは思いますが、gemを利用せずに自分でログイン機能を実装するよりははるかに時間はかからないかと思います。

Try ログイン者情報を表示しようTry①下記のコードをViewに記述するとで、ログイン者の情報を表示することができます。任意のViewに追記し、ログイン者情報を確認してみましょう。#自身のemailを表示<%=current_social_account.email%>#自身の名前の表示<%=current_social_account.name%>#自身のユーザーIDの表示①<%=current_social_account.user_id%>#自身のユーザーIDの表示②<%=current_social_account.user.id%>#自身のユーザー性別の表示<%=current_social_account.user.gender%>…②下記のコードをViewに記述するとで、ログイン状態を確認することができます。任意のViewに追記し、ログイン状態を確認してみましょう。

NEXTLESSONログアウト機能を実装しよう!ログアウト機能を実装しよう!

PREVLESSONログイン機能を実装しよう!その2ログイン機能を実装しよう!その2

目次-Ruby&RubyonRailsテキスト目次目次-Ruby&RubyonRailsテキスト目次


関連記事

CodeCampus編集部
この記事を書いた人
CodeCampus編集部
まずは7日間お試し!人気プログラミング講座を無料公開中
オンライン・プログラミングレッスンNo.1のCodeCamp