railsアプリに投稿されたYouTubeURLを自動的に埋め込み表示させる方法~無理やり編~

## 1概要
ユーザーがYouTubeにアップロードされた動画のURLを投稿し、それを自動で埋め込み動画としてそのサイトに表示させたい。これやりたい人地味に多いのでは？
実装しようとして意外と記事がなかったので僕がやったやり方を共有。
今回はrailsアプリに投稿されたYouTubeURLがたとえ埋め込みURLでなくても自動でサイトに埋め込み表示させる方法を紹介します。

```rb:環境
ruby 2.5.6
Rails 6.0.0
```

### こんな感じのものができる予定
![Qiita-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364026/b267067c-c52a-3bae-be59-c4ccbc32d0ca.gif)


### 1.1. YouTubeURLの種類
YouTubeURLは僕がパッと見た感じ3種類のURLが存在します
####  PCでのYouTube閲覧時のURL 一番スタンダード？
https://www.youtube.com/watch?v=DOEk-0MeQbI
![qiita-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364026/54573626-027c-083a-62a9-faf618d10c2a.jpeg)
#### 共有用URL　（スマホで視聴中の動画を友達に共有するときはこれ）
https://youtu.be/DOEk-0MeQbI
![qiita-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364026/517d1da4-9b32-d113-c322-c803b2c1114c.jpeg)
#### 埋め込みURL （これをHTMLに貼り付ければそのページで埋め込み動画になる）
https://www.youtube.com/embed/DOEk-0MeQbI
![qiita-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364026/3be84922-b8e8-ec40-bbaa-103076764084.jpeg)
### 1.2. どう実装するか
この３つのURLには共通して末尾に11桁の数字があります。これはGoogleがYouTubeに投稿された全ての動画に割り振っている通し番号でvideo_idと呼ばれます。
つまり上の2種類のURLが投稿されたら末尾の11桁を取り出し、HTMLに設置した以下の埋め込みURLの末尾にその数字を反映させれば埋め込み動画になるはずです。

埋め込みURLの末尾11桁に投稿されたurlの末尾11桁を代入→　https://www.youtube.com/embed/<11桁のvideo_id>

## 2 実装
### 2.1 事前準備
それではまずここで使うYouTube動画を投稿するだけのサンプルアプリを作っていきます。

```rb
cd 
cd desktop 
rails new YouTubeApps
```

投稿周りの機能をscaffoldを利用して一瞬で作りましょう。

```rb
cd YouTubeApps
rails generate scaffold post body:text youtube_url:string
rails db:migrate
```

これで投稿周りの機能ができたと思います。それではここからpostsテーブルのyoutube_urlカラムにどんなYouTubeURLが投稿されても埋め込みURLに変えていく記述を書いていきます。

### 2.2 本題
それではここからyoutubeURLから末尾のvideo_idのみを取り出し埋め込みURLにする実装をしていくのですが、Postsコントローラーのcreateアクションへrubyのコードを記述して行きます。
以下のように、scaffoldによって作成されたコントローラーのcreateアクションにコードを追記してください。

```rb:posts_controller.rb
  def create
    @post = Post.new(post_params)
     #追記した部分ここから
    url = params[:post][:youtube_url]
    url = url.last(11)
    @post.youtube_url = url
    #ここまで

    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: 'Post was successfully created.' }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end
```
ここで追記した以下の部分について解説をします。

```rb
url = params[:post][:youtube_url]
url = url.last(11)
@post.youtube_url = url
```

### paramsとは
まず一行目のparamsを含む一文について

```rb
url = params[:post][:youtube_url]
```
paramsとはrailsに用意されたgetやpostで送られてきた値を格納するためのメソッドです。
[paramsのわかりやすい解説記事](https://qiita.com/tomoharutsutsumi/items/46e6358acc8b45cd7db1)
ここでは投稿する際にformによってcreateアクションにpostの内容が

```
[:body][:youtube_url]
```
として送られています。

```rb:posts_controller
url = params[:post][:youtube_url]
```
よって、上記のコードにより変数urlに対してparamsに格納している中身であるformによって送られてきた[:youtube_url]の値を格納します。
現在の変数urlの中身は送られてきたurl全文が格納されている状態です。

現在の変数urlの中身

```
https://www.youtube.com/watch?v=DOEk-0MeQbI
```

### lastメソッドについて
ここから二文目のコードで語尾の11桁のvideo_idを取り出します。

```rb
url = url.last(11)
```
rubyの配列にはlastというメソッドがあります。これを呼ぶことで配列に対してその最後の要素を取得することができます。また、(n)の中に引数として0以上の値を渡すことで、最後のn個の要素を取得することができます。

```rb
a=[0,1,2,3]
a.last(2) #=>[2,3]
```
つまりこの

```rb
url = url.last(11)
```
で変数urlに格納されていたyoutube_urlの値のなかで最後の11桁の値のみを取り出し、改めて変数urlに格納するという処理をしています。

最後の三文目

```rb
@post.youtube_url = url
```
ここではviewで使用するインスタンス変数@postへ↑の変数urlの値を格納することでviewで@post.youtube_urlの値を呼び出すとvideo_idの値を返すようにします。

###  viewの処理
viewではposts/showおよびposts/indexページに埋め込みurlを用意しておきます。

```rb:posts/show.html.erb
<p id="notice"><%= notice %></p>

<p>
  <strong>Body:</strong>
  <%= @post.body %>
</p>

<p>
  <strong>Youtube url:</strong>
  <%= @post.youtube_url %>
</p>

<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>
```
上記の<%= @post.youtube_url %>の部分を以下のように書き換えます。

```rb
<iframe width="560" height="315" src="https://www.youtube.com/embed/<%= @post.youtube_url%>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
```

YouTubeの埋め込みurlを用意し末尾のvideo_idが入る部分に@post.youtube_urlの値が入るようにすることで、viewの中でどんなYouTubeURLが来ても埋め込み動画にするようにしています。

posts/index.html.erbも同様に

``` rb:posts/index.html.erb
<% @posts.each do |post| %>
      <tr>
        <td><%= post.body %></td>
        <td><%= post.youtube_url %></td>
        <td><%= link_to 'Show', post %></td>
        <td><%= link_to 'Edit', edit_post_path(post) %></td>
        <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
<% end %>
```

の<%= post.youtube_url %>部分に以下のコードを代入します

```rb
<iframe width="560" height="315" src="https://www.youtube.com/embed/<%=post.youtube_url%>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
```

## これでこのように表示されていれば完璧です。
![Qiita-gif3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364026/82354866-8df9-f7f9-093e-9a08b1ee8f2a.gif)


### 終わり
以上です。少し無理やりですが、YouTubeURLを投稿されたら埋め込み動画にするrailsアプリを作ってみました。

### 終わりに
GeekSalonという大学生限定のプログラミングコミュニティではメンターが精力的に記事をアウトプットしています。
こちらはwebメンターのまこっちゃん
https://qiita.com/makoto15