rails 公式音楽情報をあれやこれや出来るようにする【Spotify API】

# この記事でできる事

- 楽曲検索
- アーティスト検索
- 楽曲情報表示
- アルバムページ
    - 収録曲の表示
- アーティストページ
    - 発売されているアルバムの表示

楽曲の公式情報がrailsアプリ内で取得できると言う認識で大丈夫です。
railsアプリ内にてプレイリスト追加等の方法は後日書こうと思います。

# 前提条件

- `gem dotenv-rails`にてAPIキーを管理しています。
- Spotify APIのクライアントIDとシークレットIDを取得している

APIを取得していない場合は以下の手順で登録してください。

## Spotify APIの取得方法

### 1.ユーザーアカウントの登録

https://www.spotify.com/jp/

### 2.アカウント登録後ダッシュボードへ。
https://developer.spotify.com/

### 3.APIの発行
- CREATE AN APPをクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/4e909b9b-6e74-faa7-0ebe-cef864e45b59.png)


- アプリケーション名と説明を英語で記載
- Redirect URIsは`localhost:3000`（本番環境の場合はそれに準ずるURI）を記述し、`Add`を押す
- アプリの種類は`Web API`をチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/4bd67894-d6a4-8441-ae57-48dd493f8824.png)

### 4. APIキーの確認
- settingsをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/262fa882-3270-d8fe-c8fd-b4cbb65b8ab3.png)

- View client secretをクリックし、`Client ID`と`Client secret`をコピー（後ほど使います）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/972b1453-910d-d9ca-ffb6-a2e032f11470.png)

※APIキーは誰にも公開しないでください
（上記写真のAPIキーは例です。※削除済み）


# 実装
## 1. rspotifyのインストール
Spotify API のラッパーであるRSpotifyというgemを使って実装します。
Gemfileに以下を追加し、bundle installを実行します。

```rb:Gemfile
gem 'rspotify'
```
```terminal:ターミナル
bundle install
```
## 2.環境変数の設定
先程コピーしたキーを`.env`に追記

```bash:.env
SPOTIFY_CLIENT_ID=Client IDの内容
SPOTIFY_SECRET_ID=Client secretの内容
```
## 3. コントローラの作成
```terminal:ターミナル
rails g controller Songs search show artist album

```
```rb:app/controllers/songs_controller.rb
class SongsController < ApplicationController
  require 'rspotify'
  RSpotify.authenticate(ENV['SPOTIFY_CLIENT_ID'], ENV['SPOTIFY_SECRET_ID'])

  def search
    if params[:search_artist].present?
      @searchartists = RSpotify::Artist.search(params[:search_artist])
    end

    if params[:search_track].present?
      @searchtracks = RSpotify::Track.search(params[:search_track])
    end
  end

  def show
    @track = RSpotify::Track.find(params[:id])
  end

  def artist
    @artist = RSpotify::Artist.find(params[:id])
  end

  def album
    @album = RSpotify::Album.find(params[:id])
  end
end
```

## 4. ルーティングの設定
コントローラを作成した際に自動で記述されているものを削除して、以下を追記
```rb:config/routes.rb
resources :songs do
  collection do
    get "search"
  end
  member do
    get "artist"
    get "album"
  end
end
```

collectionやmemberについて詳しく知りたい人はこちら

https://pikawaka.com/rails/resources#memberとcollection

## 5. ビューの作成
検索フォームと結果表示
```erb:app/views/songs/search.html.erb
<h3>アーティスト名で検索</h3>
<%= form_with url: search_songs_path, method: :get, local: true do |form| %>
  <%= form.text_field :search_artist %>
  <%= form.submit 'アーティスト名検索', name: nil %>
<% end %>

<h3>楽曲名で検索</h3>
<%= form_with url: search_songs_path, method: :get, local: true do |form| %>
  <%= form.text_field :search_track %>
  <%= form.submit '楽曲名検索', name: nil %>
<% end %>

<h1>検索結果</h1>
<div>
  <% if @searchartists.present? %>
    <% @searchartists.each do |artist| %>
      <div>
        <h3><%= link_to artist.name, artist_song_path(artist.id) %></h3>
        <% if artist.images.any? %>
          <%= image_tag(artist.images[0]["url"]) %>
        <% end %>
      </div>
    <% end %>
  <% end %>

  <% if @searchtracks.present? %>
    <% @searchtracks.each do |track| %>
      <div>
        <h3><%= link_to track.name, song_path(track.id) %></h3>
        <p>アーティスト: <%= track.artists.map { |artist| link_to artist.name, artist_song_path(artist.id) }.join(", ") %></p>
        <p>アルバム: <%= link_to track.album.name, album_song_path(track.album.id) %></p>
        <% if track.album.images.any? %>
          <%= image_tag(track.album.images[0]["url"]) %>
        <% end %>
      </div>
    <% end %>
  <% end %>
</div>
```

楽曲詳細ページ
```erb:app/views/songs/show.html.erb
<h1><%= @track.name %></h1>
<p>アーティスト: <%= link_to @track.artists.first.name, artist_song_path(@track.artists.first.id) %></p>
<p>アルバム: <%= link_to @track.album.name, album_song_path(@track.album.id) %></p>
<p>リリース日: <%= @track.album.release_date %></p>
<p>トラック番号: <%= @track.track_number %></p>
<p>長さ: <%= @track.duration_ms / 1000 %> 秒</p>

<% if @track.preview_url.present? %>
  <audio controls>
    <source src="<%= @track.preview_url %>" type="audio/mpeg">
    Your browser does not support the audio element.
  </audio>
<% else %>
  <p>プレビューは利用できません。</p>
<% end %>
```

アルバム詳細ページ
```erb:app/views/songs/album.html.erb
<h1><%= @album.name %></h1>
<p>リリース日: <%= @album.release_date %></p>

<% if @album.images.any? %>
  <%= image_tag(@album.images[0]["url"]) %>
<% end %>

<h2>トラックリスト</h2>
<% @album.tracks.each do |track| %>
  <div>
    <h3><%= link_to track.name, song_path(track.id) %></h3>
    <p>トラックナンバー: <%= track.track_number %></p>
    <% if track.preview_url.present? %>
      <audio controls>
        <source src="<%= track.preview_url %>" type="audio/mpeg">
        Your browser does not support the audio element.
      </audio>
    <% else %>
      <p>プレビューは利用できません。</p>
    <% end %>
  </div>
<% end %>
```

アーティスト詳細ページ
```erb:app/views/songs/artist.html.erb
<h1><%= @artist.name %></h1>
<p>人気度: <%= @artist.popularity %></p>
<p>ジャンル: <%= @artist.genres.join(", ") %></p>

<h2>アルバム</h2>
<% @artist.albums.each do |album| %>
  <div>
    <h3><%= link_to album.name, album_song_path(album.id) %></h3>
    <% if album.images.any? %>
      <%= image_tag(album.images[0]["url"]) %>
    <% end %>
  </div>
<% end %>
```

実装は以上です。
# 参考記事

https://qiita.com/nochifuchi/items/29ac2664fc174a56c4b4

https://qiita.com/kents1002/items/362552906b6438909a7b

https://developer.spotify.com/documentation/web-api

https://github.com/guilhermesad/rspotify