RailsでYouTube Data APIを使って曲の検索機能を実装する

## **1. はじめに**

最近、Youtube Data APIを使用してみたので、備忘録として記事にまとめました。
Youtube Data APIを使用して曲名とアーティスト名での検索、YouTubeのサムネイル表示を実装しています。

また、プログラミング学習中の身であるため、技術的な内容に誤りを含んでいる可能性があります。
おかしな記述がありましたらコメント等で教えていただけたらと思います。

## **2. 実行環境**

この記事は以下の実行環境で動作確認しました。

- Ruby 3.1.4
- Rails 7.0.6

## 3. YouTube Data APIキーの取得

まず、YouTube Data APIを使用するためにAPIキーを取得する必要があります。

以下の手順で取得できます。

1. [Google Developers Console](https://console.developers.google.com/)にアクセス
2. プロジェクトを作成
3. [YouTube Data API v3](https://console.cloud.google.com/apis/library/youtube.googleapis.com?hl=ja&project=seisyun-song-youtube)を有効化
4. 認証情報を作成してAPIキーを取得

取得したAPIキーは、`.env`ファイルに記載します。

```
YOUTUBE_API_KEY='YOUR_API_KEY_HERE'
```

## 4. 検索機能の実装

### **サービスクラスの作成**

`YoutubeSearchService`クラスを作成し、検索クエリをYouTube APIに送信するロジックを実装します。

```ruby
class YoutubeSearchService
  require 'net/http'
  require 'json'

  def initialize(keyword)
    @keyword = keyword
    @api_key = ENV['YOUTUBE_API_KEY']
  end

  def search
    base_url = 'https://www.googleapis.com/youtube/v3/search'
    params = {
      key: @api_key,
      q: @keyword,
      type: 'video',
      maxResults: 20,
      part: 'snippet'
    }
    uri = URI(base_url)
    uri.query = URI.encode_www_form(params)
    response = Net::HTTP.get_response(uri)
    json = JSON.parse(response.body)

    results = json['items'].map do |item|
      {
        title: item['snippet']['title'],
        artist: item['snippet']['channelTitle'],
        youtube_url: "https://www.youtube.com/watch?v=#{item['id']['videoId']}"
      }
    end
  end
end
```

**`initialize`** メソッドでは、検索のキーワードを初期化し、環境変数からAPIキーを読み込みます。**`@keyword`** は検索する曲名やアーティスト名などのキーワードで、**`@api_key`** は環境変数からYouTube Data APIのAPIキーを取得します。

**`search`** メソッドでは、YouTube APIへのリクエストを組み立て、結果をパースして必要な情報を返します。**`base_url`** はYouTube Data APIの検索エンドポイントのURLで、**`params`** はリクエストに必要なパラメータ（APIキー、クエリ、動画タイプ、最大結果数など）です。**`uri`** で **`base_url`** と **`params`** を組み合わせて完全なURIを作成し、**`response`** でAPIからの応答を取得します。**`json`** で応答のJSONをパースし、**`results`** で必要なデータ（タイトル、アーティスト、YouTube URL）を抽出し、配列として返します。

### **コントローラーの設定**

`SongsController`の`search`アクションで上記のサービスクラスを使用します。

```ruby
def search
  keyword = params[:keyword]
  @results = YoutubeSearchService.new(keyword).search
  render :new
end
```

- `keyword`：検索フォームから入力されたキーワードを取得します。
- `@results`：サービスクラスを使用して検索結果を取得します。

### **ビューの設定**

検索結果を表示するためのビューファイル`new.html.erb`を設定します。結果の表示部分のコードは次のようになります。

```html
<h1 class="text-2xl mb-4 text-center">曲を検索！</h1>

<!-- 検索フォーム -->
<div class="flex justify-center">
  <%= form_with url: search_songs_path, method: :get, local: true do |f| %>
    <div class="flex items-center">
      <%= f.text_field :keyword, placeholder: "曲名やアーティスト名を入力" %>
      <%= f.submit "検索" %>
    </div>
  <% end %>
</div>

<!-- 検索結果 -->
<% if @results.present? %>
  <div>
    <h3 class="text-xl mt-6">検索結果</h3>
    <ul>
      <% @results.each do |result| %>
        <li class="flex space-x-4">
          <a href="<%= result[:youtube_url] %>" target="_blank" rel="noopener noreferrer">
            <img src="https://img.youtube.com/vi/<%= youtube_video_id(result[:youtube_url]) %>/0.jpg" alt="<%= result[:title] %> Thumbnail">
          </a>
          <div class="flex-grow flex flex-col w-0">
            <div class="truncate text-lg flex-grow w-full">
              <%= result[:title] %>
            </div>
            <div class="text-sm text-gray-600">
              <%= result[:artist] %>
            </div>
          </div>
        </li>
      <% end %>
    </ul>
  </div>
<% end %>
```

- **検索フォーム**: `form_with`ヘルパーを使用して検索フォームを作成。このフォームは、`search_songs_path`にGETリクエストを送信します。
- **テキストフィールド**: `f.text_field`を使用して、ユーザーが検索キーワードを入力できるテキストフィールドを作成します。
- **検索結果**: `@results`が存在する場合、検索結果を表示します。各結果は、YouTubeのサムネイル、タイトル、アーティスト名とともにリスト形式で表示されます。
- **YouTubeサムネイル**: YouTubeの動画IDを使用して、サムネイル画像のURLを生成します。このURLは、各動画のサムネイルを表示するために使用されます。

## 5. 参考文献

https://developers.google.com/youtube/v3?hl=ja

https://console.cloud.google.com/apis/library/youtube.googleapis.com?hl=ja&project=seisyun-song-youtube