OmniAuthでTwitterのプロフ画像を取得する
OmniAuthでTwitterのログインを実装する記事なんかはたくさんあるのですが、 Twitterのアバター画像をOmniAuth経由で取得する記事はあまりなかったので書いていきたいと思います。
前提
前提として、OmniAuthを通じてログインができる状態を作っておきます。 私は以下の記事を参考に実装しました。
- 【Rails】omniauthでGoogle/Twitterログインを実装する手順【キャプチャ付き解説】
- 【Rails4.2.x】omniauth(twitter/facebook/github)実装まとめ
画像アップロードにはActive Storageを使用しています
実装
ログイン機能ができたら、早速画像の取得も実装していきます。
# app/controllers/users/omniauth_callbacks_controller.rb 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 else session["devise.#{provider}_data"] = request.env['omniauth.auth'] redirect_to new_user_registration_url end end # app/models/user.rb class << self def find_for_oauth(auth) provider = auth[:provider] uid = auth[:uid] user_name = auth[:info][:name] image_url = auth[:info][:image] uri = URI.parse(image_url) # パースする必要がある image = uri.open email = User.dummy_email(auth) password = Devise.friendly_token[0, 20] find_or_create_by(provider: provider, uid: uid) do |user| user.name = user_name user.email = email user.password = password user.avatar.attach(io: image, filename: "#{user.name}_profile.png") end end end # app/config/initializers/devise.rb Devise.setup do |config| config.omniauth :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'], :image_size => 'original'
- TwitterのAPIからの情報を取得(ここで画像のURLも取得)
- URLをパースしてimageに挿入
- 一意の値になるproviderとuidの組み合わせでユーザーがいるか確認し、いなければユーザーを作る(この中で画像をアバターとしてアタッチする)
というような流れになっています。
ポイント
ポイントは
- 画像URL等を直で叩く場合は、parseしなければならない
- Twitterのデフォルトの画像サイズではかなり小さいため、画像サイズを設定しなければならない
の2点です。
画像のパース
image_url = auth[:info][:image] uri = URI.parse(image_url) # パースする必要がある image = uri.open
の部分を
image_url = auth[:info][:image] image = open(image_url)
としてしまうと
下記のように、コマンドラインで直接コマンドを叩かれてしまう可能性があります。
open('|/bin/sleep 20;').read #20秒停止するコマンド
Twitterの画像のサイズの設定
image_urlで取得できるurlにある画像は_normalというサフィックス(?)がついていてかなり小さいです。 (000000000000000000_normal.jpgのような感じ)
そのため、オリジナル(設定された時の大きさ)で取得するには app/config/initializers/devise.rbのなかで、
Devise.setup do |config| config.omniauth :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'], :image_size => 'original'
とする必要があります。
これで、Twitterでログイン時にアイコンが取得できるようになりました。