実装内容
APIを使わずに記事投稿アプリで、YoutubeやTwitterを記事に埋め込む。URLを入力すると自動で埋め込み用に変換するもの。
実装の流れ
1.モデルにenum
と入力フォームを追加
2.Youtubeを表示させる
3.Twitterを表示させる
1.モデルにenum
と入力フォームを追加
ユーザーが入力した値を保存するためのカラムを用意する。
class Embed < ApplicationRecord
enum embed_type: { youtube: 0, twitter: 1 }
validates :identifier, length: { maximum: 200 }
end
embed_type
でYoutubeかTwitterを選択する。
identifier
でURLを保存する。
入力フォームではYoutubeかTwitterかを選択し、identifier
を入力できるように設定する。
.box-body
= f.input :embed_type, collect: Embed.embed_types_i18n.invert, include_blank: false
= f.input :identifier
2.Youtubeを表示させる
▷Youtube公式 動画と再生リストを埋め込む
埋め込みたいYoutube動画ページで、「共有」→「<> 埋め込む」
を選択すると、埋め込み用のHTMLを用意してくれるので、それをコピーする。
<iframe width="560" height="315" src="https://www.youtube.com/embed/88npQhcm9qk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
上記は実際にHTMLをコピーしてきた内容。
Youtubeの埋め込み用URLは以下の構成になっている。
https://www.youtube.com/embed/動画一意のID
最後の/
までは固定値として設定し、ユーザーの入力したURLのうち、最後の/
以下だけを受け取るようなメソッドを記述する。
def split_id_from_youtube_url
# YoutubeならIDのみ抽出
identifier.split('/').last if youtube?
end
例は以下の通り。
'https://youtu.be/88npQhcm9qk'.split('/')
# => ["https:", "", "youtu.be", "88npQhcm9qk"]
'https://youtu.be/88npQhcm9qk=125'.split('/').last
# => "88npQhcm9qk=125"
実際にview
に落とし込んでいく。
ruby:
embed = local_assigns[:embed]
width = local_assigns[:width] || 853
height = local_assigns[:height] || 480
.embed-youtube
= content_tag 'iframe', nil, width: width, height: height, src: "https://www.youtube.com/embed/#{embed.split_id_from_youtube_url}", \
frameborder: 0, gesture: 'media', allow: 'encrypted-media', allowfullscreen: true
/ ↑Youtube公式に乗っている埋め込み用のHTMLを出力する形にする
/ slimでRubyコードを途中改行する場合は末尾に\(バックスラッシュ)または,(カンマ)をつける
YouTube埋め込み部分に#{embed.split_id_from_youtube_url}
と記入することで、指定した動画の埋め込みを作ることができる。
3.Twitterを表示させる
▷タイムラインを埋め込む方法
貼り付け用に変換してくれる公式ツールがあるので、ここにツイートを貼り付けて埋め込み用HTMLを生成する。
以下実際にHTMLをコピーしていた内容。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Twitter上にいる全猫たちと飼い主さんたち、今日はたくさんの癒しをありがとうございました!<a href="https://twitter.com/hashtag/%E7%8C%AB%E3%81%AE%E6%97%A5?src=hash&ref_src=twsrc%5Etfw">#猫の日</a><br><br>写真は <a href="https://twitter.com/hashtag/Twitter%E7%8C%AB%E3%81%AE%E6%97%A5%E3%82%A2%E3%83%B3%E3%83%90%E3%82%B5%E3%83%80%E3%83%BC?src=hash&ref_src=twsrc%5Etfw">#Twitter猫の日アンバサダー</a> <a href="https://twitter.com/slurmQuEBJUJK3X?ref_src=twsrc%5Etfw">@slurmQuEBJUJK3X</a> さんの猫ちゃんです✨ <a href="https://t.co/QVa21bdv3E">pic.twitter.com/QVa21bdv3E</a></p>— Twitter Japan (@TwitterJP) <a href="https://twitter.com/TwitterJP/status/1496116675858804736?ref_src=twsrc%5Etfw">February 22, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
これもYoutube同様無駄な部分を省く。
<blockquote class="twitter-tweet"> <a href="https://twitter.com/TwitterJP/status/1496116675858804736?ref_src=twsrc%5Etfw">February 22, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
省いたものを、view
に反映させればOK。
.embed-twitter
blockquote.twitter-tweet
a href="#{embed.identifier}"
script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"
#{embed.identifier}
で任意のツイートのURLを埋め込むことができる。
上記rspec
require 'rails_helper'
RSpec.describe 'AdminArticlesEmbeddedMedia', type: :system do
let(:admin) {create(:user, :admin)}
let(:article) {create :article}
describe '記事の埋め込みブロックを追加' do
before do
login(admin)
article
visit edit_admin_article_path(article.uuid)
click_on('ブロックを追加する')
click_on('埋め込み')
click_on('編集')
end
context 'YouTubeを選択しアップロード' do
it 'プレビューした記事にYouTubeが埋め込まれていること', js: true do
select 'YouTube'
fill_in 'ID', with: 'https://youtu.be/dZ2dcC4OnQE'
page.all('.box-footer')[0].click_button('更新する')
#更新ボタンが同じページにいくつかあるとき
click_on('プレビュー')
switch_to_window(windows.last)
expect(current_path).to eq(admin_article_preview_path(article.uuid))
expect(page).to have_selector("iframe[src='https://www.youtube.com/embed/dZ2dcC4OnQE']")
#Youtubeの埋め込みを確認
end
end
context 'Twitterを選択しアップロード' do
it 'プレビューした記事にTwitterが埋め込まれていること', js: true do
select 'Twitter'
fill_in 'ID', with: 'https://twitter.com/_RUNTEQ_/status/1219795644807667712'
page.all('.box-footer')[0].click_button('更新する')
click_on('プレビュー')
switch_to_window(windows.last)
expect(current_path).to eq(admin_article_preview_path(article.uuid))
sleep 1
# 全体テスト実行時に画面遷移が追いつかないので待機
# sleep:プログラムの実行をストップする(秒数)
expect(page).to have_selector(".twitter-tweet")
# embedded_urlだと検証しづらいので固定値で確認
# expect(page).to have_selector("iframe[src='#{embedded_url_twitter}']")
end
end
end
end
参考記事
【Rails】YoutubeとTwitterをAPIを使わずに記事に埋め込む
rails学習 YouTubeとTwitterをローカルで埋め込む