Railsでyoutubeの動画を埋め込み表示させる方法(編集でも入力したURLを取得できる)


1 概要

 railsでyoutubeの動画を埋め込み表示させたいなと思い、様々な記事を参考にして実装を試みました。ただ、参考記事通りでは自分の思い描いたような実装はできませんでした。それから試行錯誤を繰り返し、バグ等が出ず、編集画面でも入力したURLが生成されるやり方が分かったので、その実装方法を記載します。

1.1 YouTubeURLの種類

 youtubeの動画は11桁の文字列で動画の識別を行っております。その11桁の文字列をyoutubeの埋め込み用のURLに貼り付けてあげれば、railsでも埋め込み動画を表示されるます。

youtubeのURL
https://www.youtube.com/watch?v=0CqFEDzDkIA&t
この文字列で動画の識別を行う  →→ 「0CqFEDzDkIA&t」

ただ、ここに大きな落とし穴があります。
上記URLが生成される条件として、youtubeの動画を0秒から開始する場合のみ、上記のURLが生成されます。
この条件を満たしていないと、さらに長いURLが生成されるので、参考記事 通り作成しても、埋め込み動画が表示されないバグが発生します。

基準を満たしたURLであれば、参考記事でも正しく再生されます

下記の方法でyoutubeのURLを取得すると、動画識別の11文字のコードより長いURLが生成される

- 動画の再生を途中で止めた動画のURL
- 特殊な状況で動画を再生している動画のURL
(例:自身のお気に入り動画の再生画面からURLを取得する等)

(その他にもあるかもしれませんが、どちらにせよURLは長くなる方向で生成されます)

これらを踏まえ、実装の段取りを説明していきます。

2. 実装

著者のバージョン

  • ruby 2.5.1
  • rails 5.2.3
  • mysql 5.7

2.1 事前準備

まず、YouTubeの動画を投稿するだけのサンプルアプリを作っていきます。

ターミナル操作
$ mkdir projects // ディレクトリは各自用意
$ cd projects
$ mkdir sample_app
$ cd sample_app
$ $ rails new youtubetest -d mysql

バージョン指定したい場合は下記のように入力してください
rails -5.2.3- new youtubetest -d mysql

$ rails s

サーバーを起動します。
サーバー立ち上げることができたか確認するため、http://localhost:3000 にアクセスする。いつもの画像が出れば起動は完了です。

2.2 Gem導入

私は、Hamlで書くことが多いので、gem 'haml-rails'を導入します。

gemfile
gem 'haml-rails'

導入後はrailsをたち下げbundle installを行ってください。

2.3 アプリの作成

ルーティングを記述します。

routes.rb
Rails.application.routes.draw do
  root to: 'products#index'
  resources :products, only: [:index, :new, :create,:edit ,:update, :destroy]
end

コントローラーを作成します。

ターミナル
$ rails g controller products

productsコントローラーに以下を追記してください。

class ProductsController < ApplicationController

  def index
    @products = Product.all
  end

  def new
    @product = Product.new
  end

  def create
    product.create(product_params)
    redirect_to root_path
  end

  def destroy
    product = Product.find(params[:id])
    product.destroy
  end

  def edit
    @product = Product.find(params[:id]) 
  end

  def update
    product = Product.find(params[:id])
    product.update(product_params)
  end

  private
  def product_params
    params.require(:product).permit(:name, :youtube_url)
  end
end

モデルを作成します。

ターミナル
$ rails g model product

マイグレーションファイルに以下のように追加して下さい

db/migrate/xxxxxxxxxxxxxx_create_products.rb
class CreatePosts < ActiveRecord::Migration[5.2]
  def change
    create_table :products do |t|
      t.text :name # 追加
      t.string :youtube_url # 追加
      t.timestamps
    end
  end
end

rails:db:migrateをしましょう。

ターミナル
$ rails db:migrate

下準備は終了です
ここからが一番重要な工程になります!!

トップ画面のビューファイルを作ります。
下記コマンド入力してください。

ターミナル
$ touch app/views/products/index.html.haml
$ touch app/views/products/new.html.haml
$ touch app/views/products/edit.html.haml
※ 上から順番に打ち込んでください

トップ画面のビューファイルを作ります。
index.html.hamlに下記のコードを追記してください。

index.html.haml

.contents
  - @products.each do |product|
    .content_post
      = product.name
    .content_post
      %iframe{src: "https://www.youtube.com/embed/#{product.youtube_url[32..42]}",allow: "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture", allowfullscreen: "", frameborder: "0", height: "315", width: "560"}

下記コードは、埋め込みコードの基盤となるコードです。
https://www.youtube.com/embed/
このコードの後ろに、#{post.youtube_url[32..42]} を追記してあげることで、変則的な状態で生成されたURLでも正常に再生できるようになります。

補足説明
 %iframe{src: "https://www.youtube.com/embed/#{product.youtube_url[32..42]}"、以下省略}
# 下記のコードを追記する
"#{product.youtube_url[32..42]}"
# 動画の識別をする11桁の文字列を取得している

続いて、投稿画面と編集画面のviewを作成します。
new.html.hamledit.html.haml`に下記コード追記してください
(ここの工程ではパーシャルテンプレートを用いて大丈夫です)

new.html.haml&edit.html.haml
.new-contents
  .new-contents__content

      = form_with(model: @product, local: true) do |form|
      contents-group
        = form.label :name, "名前"
        = form.text_field :name, placeholder: 'name'

      contents-group
        = form.label :youtube_url, "YouTubeのURL"
        = form.text_field :youtube_url, placeholder: 'youtube_url'
      = f.submit '投稿する'

以上で完成となります!!
少し埋め込みコードに記述を加えるだけで、どんな状態のURL(youtubeに限る)でも動画の埋め込みが正しくでき、動画が再生できると思います。

参考記事

最後に

以上で、「Railsでyoutubeの動画を埋め込み表示させる方法」の説明を終わりたいと思います。間違っている点がありましたらご指摘頂けると助かります。

最後までご覧いただき、ありがとうございました。