[備忘録]メルカリクローンサイト実装におけるApi接続と理解

一昨日卒業したプログラミングスクールにおいて最終課題として実装したメルカリクローンサイトの備忘録を書きます。
私は主にUser登録関係のフロント・バックエンドを担当したので、そこを覚え書きしときます。

# Apiとは
最初は自分も色々調べたのですが、
[Application Programming Interfaceの略。ソフトウェアからOSの機能を利用するための仕様またはインターフェースの総称](https://www.otsuka-shokai.co.jp/words/api.html) -大塚商会
みたいな答えが非常に多く、またこの答えの意味がよくわからないという困った状況でした。

ただgemのREADMEを参考によくわからないまま進め、データの流れをbinding.pryで逐一確認していたら、
もっと初心者に優しい説明が出来るなと感じました。

<img width="793" alt="スクリーンショット 2019-08-04 0.48.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414123/8c4a6014-72c7-7657-72a5-e41a9a685632.png">
それが、これです。
※OmniAuthの例です

①rails上に設置したApiを動かす（link_to "url"みたいに書いて、web上で押す）
②requestがgoogleに飛ぶ（データよこせ！ってね）
③responseが返ってくる（中身にparams型でデータが入ってる）
④予め定義した〜controllerにデータが来るので、それを使ってcreate,update等々好きな処理を書く
⑤終わり

このイメージが付いて、初めてApiの説明文が理解できました。
かなり嬉しかったです。
また今回の件でわからなくても一度動く状態を作って検証すれば難しそうでも理解できるなと自信が付きました。

# OmniAuthについて

railsでOAuth認証（外部アカウントでログインする機能）を利用する際に使うgem
基本的には公式のREADMEを参考にすればすぐ動くようになる。

```omniauth_callbacks_controller.rb
# frozen_string_literal: true

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google_oauth2
      # You need to implement the method below in your model (e.g. app/models/user.rb)
      @user = User.from_omniauth(request.env['omniauth.auth'])
      if @user.persisted?
        flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'
        sign_in_and_redirect @user, event: :authentication
      else
        session['devise.google_data'] = request.env['omniauth.auth'].except(:extra) # Removing extra as it can overflow some session stores
        redirect_to new_user_registration_url, alert: @user.errors.full_messages.join("\n")
      end
  end
end
```

googleのOAuth認証Apiを叩くとデータがここに飛ぶようになっています。
今回は最初の「.from_omniauth()関数」の中でcreate,updateさせるようにして、
絶対ユーザー情報がDB内にある状態を作っています。なのでelseは動かない

```user.rb
class User < ApplicationRecord
  def self.from_omniauth(data)
    user_key = ForeignAccount.where(provider: data.provider, uid: data.uid).first
    # ユーザー情報があるか確認
    if user_key != nil
      already_user = user_key.user
      return already_user if already_user
    #メールアドレスでの登録があれば、関連付け
    elsif User.where(email: data.info.email) != nil
      add_sns_user = User.find_by(email: data.info.email)
      ForeignAccount.create(
                            user_id: add_sns_user.id,
                            provider: data.provider,
                            uid: data.uid,
                            token: data.credentials.token
                            )
      return add_sns_user if add_sns_user
    else
      #そもそもユーザー情報ない場合
      new_user = User.create(
                            nickname: data.info['name'],
                            email: data.info['email'],
                            password: Devise.friendly_token[0,20]
                            )
      ForeignAccount.create(
                            user_id: new_user.id,
                            provider: data.provider,
                            uid: data.uid,
                            token: data.credentials.token
                            )
      return new_user if new_user
    end
  end
```

あとOAuth認証時はForeignAccoutテーブルに別途保存したuid,providerでuserを引っ張ってきて
ログインさせるようにしてます。
こうして見ると簡単ですよね。

以上備忘録でした