はじめに
ポートフォリオにて、YouTubeで自分が登録しているチャンネル一覧を取得する機能を実装しようとした際に、参考になる記事に出会えず、なかなか苦労したので本記事を作成しました。
本記事では登録チャンネルの一覧取得のみを取り上げていますが、応用することでYouTube Data APIのリファレンスで**このパラメータは、適切に承認されたリクエストでのみ使用できます。**という記述のあるフィルタなどを利用することができるかと思います!
環境
Ruby:3.0.2
Rails:6.0.4
1.Google APIでプロジェクトを作成したりする
プロジェクトの作成
①こちらからAPIのダッシュボードに移動します。
②「プロジェクトを作成」から、プロジェクトの作成します。
③「プロジェクト」に任意のプロジェクト名を入力し、「作成」。
OAuth同意画面の編集
①左側のメニューから「OAuth同意画面」を開き、「外部」を選択して「作成」。
②「① OAuth認証画面」では、必須項目にそれぞれ入力後、「保存して次へ」。
③「② スコープ」では、まず「スコープを追加または削除」から、範囲.../auth/userinfo.email
にチェックをつけて「更新」し、「保存して次へ」。
④「③ テストユーザー」では、[+ADD USERS]で自身のメールアドレスを入力して[追加]し、[保存して次へ]。
⑤「④ 概要」はこれまでの内容が表示されるだけなので、これにてOAuth同意画面の編集は完了です。
OAuthクライアントIDの作成
①画面上部の[+ 認証情報を作成]から、[OAuthクライアントID]を選択します。
②[アプリケーションの種類]でウェブアプリケーションを選択する。[名前]は任意のものでOK。
③続けて、「承認済みのリダイレクトURI」の[+ URIを追加]でhttp://localhost:3000/auth/google_oauth2/callback
と入力します。
④[作成]を押すと、クライアントIDとクライアントシークレットが表示されるので、メモ帳などにコピペしておきます。
ライブラリの有効化
左側のメニューから「ライブラリ」を開き、以下のライブラリを検索して、それぞれ有効化しておきます。
- Google+ API
- YouTube Data API v3
2.必要なgemをインストールする
rails new
でアプリケーションを作成したら、以下のgemをGemfileに追加して、bundle install
します。
#環境変数用
gem 'dotenv-rails'
#Googleログイン用
gem 'omniauth-google-oauth2'
gem 'omniauth-rails_csrf_protection'
#YouTubeデータ取得用
gem 'google-apis-youtube_v3'
また、bundle exec rails db:create
でDBを作成しておきましょう。
3.Googleログインの実装
①.env
を作成し、環境変数を記述
GOOGLE_CLIENT_ID='OAuthクライアントID作成時に表示されたクライアントID'
GOOGLE_CLIENT_SECRET='OAuthクライアントID作成時に表示されたクライアントシークレット'
②認証用の設定ファイルを作成
/config/initializers
内に、omniauth.rb
を作成し、以下のように記述します。
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2,
ENV['GOOGLE_CLIENT_ID'],
ENV['GOOGLE_CLIENT_SECRET']
end
③Userモデルを生成
$ bundle exec rails g model User name email avatar token refresh_token
$ bundle exec rails db:migrate
Userモデルの各カラムはstring型としているので、型指定を省いています。
④ログイン周りの処理を実装
bundle exec rails g controller sessions
class SessionsController < ApplicationController
skip_before_action :check_logged_in, only: :create
def create
if user = User.find_or_create_from_auth_hash(auth_hash)
log_in user
end
redirect_to root_path
end
def destroy
log_out
redirect_to root_path
end
private
def auth_hash
request.env['omniauth.auth']
end
end
module SessionsHelper
def current_user
return unless (user_id = session[:user_id])
@current_user ||= User.find_by(id: user_id)
end
def log_in(user)
session[:user_id] = user.id
end
def log_out
session.delete(:user_id)
@current_user = nil
end
end
class ApplicationController < ActionController::Base
include SessionsHelper
before_action :check_logged_in
def check_logged_in
return if current_user
redirect_to root_path
end
end
⑤Home画面周りの実装
bundle exec rails g controller home index
class HomeController < ApplicationController
skip_before_action :check_logged_in, only: :index
def index; end
end
⑥ルーティングを設定
Rails.application.routes.draw do
root 'home#index'
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'log_out', to: 'sessions#destroy', as: 'log_out'
resources :sessions, only: %i[create destroy]
end
⑦Userモデルにメソッドを記述
class User < ApplicationRecord
#クラスメソッドとして定義
class << self
def find_or_create_from_auth_hash(auth_hash)
user_params = user_params_from_auth_hash(auth_hash)
#emailをキーとして検索し、重複するものがあればユーザーを作成・更新しない
find_or_create_by(email: user_params[:email]) do |user|
user.update(user_params)
end
end
private
#googleログイン時に渡されるauth_hashから、必要な情報を各カラムに格納
def user_params_from_auth_hash(auth_hash)
{
name: auth_hash.info.name,
email: auth_hash.info.email,
avatar: auth_hash.info.image,
token: auth_hash.credentials.token,
refresh_token: auth_hash.credentials.refresh_token
}
end
end
token
属性には、登録チャンネルのリストを取得する際に必要なアクセストークンが格納されます。
refresh_token
属性には、上記のアクセストークンを更新する際に必要なリフレッシュトークンが格納されるのですが、本記事では扱いません…
(アクセストークンの有効期限が1時間なので、時限(Rakeタスクなど?)でリフレッシュトークンを用いた更新をしてあげると良いかと思います…)
⑧ビューにログイン・ログアウト用のリンクを作成
<% if current_user %>
<%= image_tag current_user.avatar %>
<%= current_user.name %>さん
<%= link_to "ログアウト", log_out_path %>
<% else %>
<%= link_to "Googleでログイン", "/auth/google_oauth2", method: :post %>
<% end %>
ここまでで、Googleログインの実装は完了です。
なお、ここまでの実装については、こちらの記事を参考にさせていただきました!
4.登録チャンネルのリストを取得する
①モデルを作成する
bundle exec rails g model Subscription
class Subscription < ApplicationRecord
require 'google/apis/youtube_v3'
def channels(user)
service = Google::Apis::YoutubeV3::YouTubeService.new
service.authorization =
Signet::OAuth2::Client.new(
access_token: user.token
)
service.list_subscriptions(:snippet, mine: true, max_results: 10)
end
end
list_subscriptions
メソッドに利用できる引数はこちらで確認できます。
②コントローラーを作成する
bundle exec rails g controller subscriptions index
class SubscriptionsController < ApplicationController
def index
@subscription = Subscription.new
@user = current_user
@subscription_channels = @subscription.channels(@user)
end
end
③ルーティングを追記する
resources :subscriptions, only: %i[index]
④ビューを編集する
<div>
<% if current_user %>
<%= image_tag current_user.image %>
<%= current_user.name %>さん
<%= link_to "ログアウト", log_out_path %>
<% end %>
<div>
<div>
<% @subscription_channels.items.each do |item| %>
<% channel_icon = item.snippet.thumbnails.medium.url %>
<img src='<%= channel_icon %>'>
<p><%= item.snippet.title %></p>
<% end %>
<div>
インスタンス変数(@subscription_channels)に格納された属性から、必要なものを引っ張り出して表示しています。
なお、ここでは、以下の内容を表示させています。
・チャンネルのアイコン(item.snippet.thumbnails.medium.url
)
・チャンネルのタイトル(item.snippet.title
)
⑤seesionsコントローラーのcreateアクションを編集する
def create
if user = User.find_or_create_from_auth_hash(auth_hash)
user.update(token: auth_hash.credentials.token, refresh_token: auth_hash.credentials.refresh_token) # 追記
log_in user
end
redirect_to subscriptions_path #リダイレクト先を変更
end
なお、localhost:3000/subscriptions
で表示される画面は以下のような感じになります。
実際には、channels
メソッド内でlist_subscriptions
に引数としてmax_results: 10
を渡しているので、あと8件ほど(計10件)の登録チャンネルが表示されています。
終わりに
最後まで目を通していただき、ありがとうございました。
ポートフォリオに組み込む前にお試しでやってみたもので、色々といけてない部分も目立つかと思いますが、参考になる部分があれば幸いです。