【Rails】gem'RSpotify'を利用し、SpotifyAPIからアーティスト情報を取得する検索機能を作成する

#概要
Railsアプリケーションにて、SpotifyAPIを利用し、検索機能を実装します。
SpotifyAPIのラッパーであるRSpotifyというgemを利用する方法になります。


#SpotifyAPIへアプリの登録

SpotifyAPIを利用するにはアカウントを作成し、デベロッパー用のダッシュボードで連携するアプリを登録する必要があります。
アプリを登録すればAPIへアクセスするためのIDが取得できます。

ユーザーアカウントの登録を行う。
https://www.spotify.com/jp/

アカウント作成完了後にデベロッパー用のダッシュボードへ。
https://developer.spotify.com/


"CREATE AN APP"をクリック。
アプリケーション名とアプリケーションの説明を英語で記載し、
アプリの種類は何かをチェックしてください。
商用かどうかが確認されますので、いずれかを選択。
今回はNoを選択しました。

作成完了すれば、
"CLIENT ID"と"CLIENT SECRET ID"が発行されます。
"CLIENT SECRET ID"は"SHOW CLIENT SECRET"をクリックすれば確認できますね。

#Rspotifyを用意する

今回はSpotify API のラッパーであるRSpotifyというgemを使って実装します。

**ラッパーとは**

>プログラミングやソフトウェア開発の分野では、ソフトウェアやプログラム部品などが提供するクラスや関数、データ型などを本来とは異なる環境や方法で利用できるようにしたものをラッパーという。対象の種類に応じて「ラッパー関数」「ラッパークラス」「ラッパーライブラリ」などという。元の機能を包み、覆い隠す役割を果たすためにこのように呼ばれる。

>ラッパーが作成・提供される理由は様々で、元のクラスなどがそのままでは利用できない別の環境で利用できるようにしたり、煩雑な仕様や設定などを隠蔽したり自動化したりしてシンプルな手順で利用できるようにしたり、別の機能を追加したりするのに使われる。

>出典：IT用語辞典（http://e-words.jp/w/%E3%83%A9%E3%83%83%E3%83%91%E3%83%BC.html）


この辺の理解は合っているかわからないのですが、簡単にいうと元々の機能（今回はSpotifyAPI）のデータ参照ができるように仲介役であるラッパー（今回はRSpotify）を挟んであげるということだと認識します。

通常はRuby言語でSpotifyAPIのデータを参照することはできないのに、Rsporifyを使うことでRuby言語で参照できるようになるのです。

##RSpotify導入方法
RSpotifyを導入していきます。

◆RSpotifyのGithub
https://github.com/guilhermesad/rspotify

```ruby

gem 'rspotify'
gem 'dotenv-rails'
```

```
$ bundle install
```

.envファイルで環境変数を保管するために`'dotenv-rails’`も入れておきます。
今回はMusicモデル内に検索機能を加えていくとして書いていきます。

RspotifyのREADMEに記載されている通り、
`rspotify`を読み込むと、`search`メソッドを使ってSpotifyAPIのデータを参照することができます。
READMEは'Arctic Monkeys'で検索した場合の例を記載してくれています。

```ruby

require 'rspotify'

artists = RSpotify::Artist.search('Arctic Monkeys')

arctic_monkeys = artists.first
arctic_monkeys.popularity      #=> 74
arctic_monkeys.genres          #=> ["Alternative Pop/Rock", "Indie", ...]
arctic_monkeys.top_tracks(:US) #=> (Track array)

albums = arctic_monkeys.albums
albums.first.name #=> "AM"

am = albums.first
am.release_date      #=> "2013-09-10"
am.images            #=> (Image array)
am.available_markets #=> ["AR", "BO", "BR", ...]

tracks = am.tracks
tracks.first.name #=> "Do I Wanna Know?"

do_i_wanna_know = tracks.first
do_i_wanna_know.duration_ms  #=> 272386
do_i_wanna_know.track_number #=> 1
do_i_wanna_know.preview_url  #=> "https://p.scdn.co/mp3-preview/<id>"

playlists = RSpotify::Playlist.search('Indie')
playlists.first.name #=> "The Indie Mix"

# You can search within other types too
albums = RSpotify::Album.search('The Wall')
tracks = RSpotify::Track.search('Thriller')
```


#フォームにアーティスト名を入力して検索できるようにする
searchメソッドを利用して、自由にアーティスト名を検索できるように実装していきます。



```musics_controller.rb

class MusicsController < ApplicationController
  require 'rspotify'
  RSpotify.authenticate(ENV['SPOTIFY_CLIENT_ID'], ENV['SPOTIFY_SECRET_ID'])

  def search
    @musics = Music.all
    if params[:search].present?
    @searchartists = RSpotify::Artist.search(params[:search])
    end
  end
```

<br>
envファイルには初めに取得したIDを記載します。

```env
SPOTIFY_CLIENT_ID="自分のCLIENT ID"
SPOTIFY_SECRET_ID="自分のCLIENT SECRET ID"
```

<br>
検索して受け取ったアーティスト情報から、アーティスト名とアーティスト写真を取得して表示させたいと思います。
viewディレクトリにsearch.html.erbファイルを作成して実装します。

```musics/search.html.erb
<h3>アーティスト名で検索</h3>
<%= form_with url: search_artist_boards_path, method: :get, local: true do |form| %>
<%= form.text_field :search %>
<%= form.submit 'アーティスト名検索', name: nil %>
<% end %>


<h1>検索結果</h1>
<div>
  <% if @searchartists.present? %>
    <% @searchartists.each do |searchartist| %>
      <div>
        <h3><%= searchartist.name %></h3>
          <% if searchartist.images.any?%>
            <%image = searchartist.images[1]%>
            <%= image_tag(image["url"])%>
          <%else%>
            <%= image_tag("default.jpg")%>
          <%end%>
      </div>
```

Searchアクションを呼び出し、アーティスト情報が取得できれば同じ画面にリダイレクトし、検索結果が表示されるようにしています。
`method: :get,`を記述しないとpostが飛び、createアクションが呼び出されてしまいます。
`"default.jpg"`はアーティスト写真が存在していなかった場合に表示させる用の画像です。
imagesディレクトリに保存して呼び出しています。

<br>
実際データはこんな感じで取得できます。
あいまい検索なので、２件該当しています。
＠imagesはサイズが３種類あるため、中間のサイズを表示させるようにimages[1]としているわけです。


```terminal

[#<RSpotify::Artist:0x00007f8865cd5808 @followers={"href"=>nil, "total"=>8919915}, @genres=["garage rock", "modern rock", "permanent wave", "rock", "sheffield indie"],
 @images=[{"height"=>640, "url"=>"https://i.scdn.co/image/ed0552e9746ed2bbf04ae4bcb5525700ca31522d", "width"=>640},
 {"height"=>320, "url"=>"https://i.scdn.co/image/b435e99aa7f1e27db56b6a4dc9df85e5636b22d6", "width"=>320},
 {"height"=>160, "url"=>"https://i.scdn.co/image/73c4e49abed008fe0c5e4f1437b8b486c7670ecd", "width"=>160}],
 @name="Arctic Monkeys", @popularity=86, @top_tracks={}, @external_urls={"spotify"=>"https://open.spotify.com/artist/7Ln80lUS6He07XvHI8qqHH"},
 @href="https://api.spotify.com/v1/artists/7Ln80lUS6He07XvHI8qqHH", @id="7Ln80lUS6He07XvHI8qqHH", @type="artist", @uri="spotify:artist:7Ln80lUS6He07XvHI8qqHH">,
 #<RSpotify::Artist:0x00007f8865cd5790 @followers={"href"=>nil, "total"=>177}, @genres=[],
 @images=[{"height"=>640, "url"=>"https://i.scdn.co/image/ab67616d0000b27388ccc49d173ca3f4c5ea5a82", "width"=>640},
 {"height"=>300, "url"=>"https://i.scdn.co/image/ab67616d00001e0288ccc49d173ca3f4c5ea5a82", "width"=>300},
 {"height"=>64, "url"=>"https://i.scdn.co/image/ab67616d0000485188ccc49d173ca3f4c5ea5a82", "width"=>64}],
 @name="Arctic Monkeys Tribute Band", @popularity=4, @top_tracks={}, @external_urls={"spotify"=>"https://open.spotify.com/artist/2hv9oBOxgWSFnZJPW6UL58"},
 @href="https://api.spotify.com/v1/artists/2hv9oBOxgWSFnZJPW6UL58", @id="2hv9oBOxgWSFnZJPW6UL58", @type="artist", @uri="spotify:artist:2hv9oBOxgWSFnZJPW6UL58">]
```

<br>
Searchアクションはresourcesでは自動で生成されないので、新しく作成する必要があります。
MusicコントローラーでSearchアクションが呼び出せるように、ルーティング設定を行います。

```routes.rb
Rails.application.routes.draw do
  resources :musics do
       collection {get "search"}
  end
end
```

独自ルーティングを作成するのは
memberとcollectionの２つの方法がありますが、
memberの場合はroutingにidが必要になり、
Collectionの場合はidは不要になります。
今回は検索機能でid付与は不要ですのでcollectionでルーティング設定しています。


これでアーティスト名を自由に検索できるようになりました！
RSpotifyを利用することでめちゃくちゃ簡単に実装できました。

searchの方法含めて、色々なデータ取得の方法は公式リファレンスに記載があります。
https://developer.spotify.com/documentation/web-api/reference/albums/

検索デモもできるので便利です。