はじめに
ブログ記事にYouTubeやTwitterなどの埋め込み機能はもはや当たり前です。
URLを入力したら、コンテンツが表示されるように実装していきましょう。
enum用意
Embedモデルのembed_typeカラムにyoutubeとtwitterというenum を設定します。
class Embed < ApplicationRecord
has_one :article_block, as: :blockable, dependent: :destroy
has_one :article, through: :article_block
enum embed_type: { youtube: 0, twitter: 1 }
validates :identifier, length: { maximum: 200 }
end
記事ブロック見出しアイコンをTwitterに対応させる


embed
がyoutube
なのか、twitter
なのか条件分岐させます。 下記で使われているメソッドはembed_type
としてenumを設定しているので使えています。
module ArticleBlockDecorator
def box_header_icon
if sentence?
'<i class="fa fa-edit"></i>'.html_safe
elsif medium?
'<i class="fa fa-image"></i>'.html_safe
elsif embed?
blockable.youtube? ? '<i class="fa fa-youtube-play"></i>'.html_safe : '<i class="fa fa-twitter"></i>'.html_safe # 三項演算子を使ってスッキリ書く
end
end
end
自戒の念を込めて
このようにif
文の中にif
文を作ると、RubocopのLintチェックに引っかかりました。
Metrics/PerceivedComplexity: Perceived complexity for box_header_icon is too high. [8/7]
module ArticleBlockDecorator
def box_header_icon
if sentence?
'<i class="fa fa-edit"></i>'.html_safe
elsif medium?
'<i class="fa fa-image"></i>'.html_safe
elsif embed?
if blockable.embed_type == 'youtube'
'<i class="fa fa-youtube-play"></i>'.html_safe
elsif blockable.embed_type == 'twitter'
'<i class="fa fa-twitter"></i>'.html_safe
end
end
end
end
記事ブロック挿入画面にTwitterアイコンを追加

記事ブロック挿入画面のアイコンを、YouTubeとTwitterが横並びになるようにしましょう。
d-inline-flex
.d-inline-flex
i.fa.fa-youtube-play
i.fa.fa-twitter
'
| 埋め込み
bootstrapで用意されているインラインのFlexコンテナーです。 こちらを使うことで、横並びを実現しています。 ブラウザでは下記のようにレンダリングされています。
<div class="d-inline-flex">
<i class="fa fa-youtube-play"></i>
<i class="fa fa-twitter"></i>
</div>
cssを埋め込む
または直接cssを適用させることもできます。
i.fa.fa-youtube-play(style='display: inline')
i.fa.fa-twitter(style='display: inline')
NG例
下記のようにアイコン自体の階層をインデントで変更するのはhtmlの階層としておかしいでしょう。
i.fa.fa-youtube-play
i.fa.fa-twitter
入力フォーム
simple_formの中で、Youtube
かtwitter
かを選択し、identifier
を入力できるようなフォームにします。
.box-body
= f.input :embed_type, collect: Embed.embed_types_i18n.invert, include_blank: false
= f.input :identifier
Youtube埋め込み表示ファイル
youtube再生画面の「共有」を押した後に表示される埋め込み用URLというのは、以下の構成になっています。
https://www.youtube.com/embed/11桁のID

各動画は / より後ろの文字列により個別に分類されているので、上記のURLを取得後、 / より後ろの文字列を取得し、「任意のYouTubeのID」に代入すると任意のYouTubeが表示されるようになります。
ID抽出メソッド作成
以下のように、/
を区切り文字としてyoutubeのURLを後ろのid
のみを抽出するsplit
メソッドをEmbed
モデル定義しましょう。
def split_id_from_youtube_url
identifier.split('/').last if youtube?
end
embed
に対して、作成したメソッドを実行して下11桁の文字列だけ取り出して表示させましょう。
.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
tweet埋め込み表示ファイル

tweet埋め込みツールは公式にて用意されています。
ここにツイートを貼り付けて埋め込み用HTMLを生成します。
<blockquote class="twitter-tweet">
<p lang="ja" dir="ltr">【ブログ更新】データからも明らか‼️不幸になりたくない人が最重視すべき1つのこと<br><br>普段はお金について情報発信しとるけど、幸福度を決めるのはお金だけじゃないで。<br>
<br>
学歴や収入よりも〇〇の方が、幸福度に影響を与えるんや。<br>
<br>
不幸になる生き方をしてないか確認してな^^
<a href="https://t.co/K1f42WIT0L">https://t.co/K1f42WIT0L</a></p>— 両🦁自由に生きるための知恵を配信中 - リベ大学長 (@freelife_blog)
<a href="https://twitter.com/freelife_blog/status/1461534705292132354?ref_src=twsrc%5Etfw">November 19, 2021</a>
</blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
無駄な部分を省いて、必要な部分だけ残します。
<blockquote class="twitter-tweet">
<a href="https://twitter.com/freelife_blog/status/1461534705292132354?ref_src=twsrc%5Etfw"></a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
slim形式に変換して整えます。
.embed-twitter
blockquote.twitter-tweet
a href="#{embed.identifier}" # tweetのURL部分に、embedのidentifierを入れる
script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"
Rspec
不明な構文
page.all
page.all で要素を全て見つけ出して、インデックスで指定するのがお手軽っぽいです。配列なので、1 が2番目の要素。
page.all(".submit-button")[1].click_button("Submit") # 2番目の要素
page.all(".submit-button")[2].click_button("Submit") # 3番目の要素
js: true
JavaScriptを使用しないと操作できない処理をテストします。
Ajaxを使用した処理や、クリックイベントによるモーダル画面の表示など、JavaScriptなしては実行できない操作がある場合にこのタグをつけます。
sleep 秒数
JavaScriptの処理が完了しないうちにテストが先に進んでしまうとテストが失敗するので、JavaScriptの処理が終わるまでテストを停止します。
コメント