ユーザーがポートフォリオに記事を投稿する際、youtubeの共有リンクを貼り付け動画を埋め込めるようにする機能を実装しようとして、手こずった事があったので備忘録として残しておきます。
何にハマったのか
既にQiitaに同じような実装をされている方の記事が複数あったため、それを参考にすれば何ら問題なく実装できました。
しかしながら、参考記事は新規投稿に関するもので、投稿の編集(update)の場合については書かれていません。色々と試しましたが自力で実装ができませんでした。
新規投稿の場合
createアクション(新規投稿)での実装方法はこのような感じです。
def create
@post = Post.new(post_params)
url = params[:post][:youtube_url].last(11)
@post.youtube_url = url
end
なぜこのような手段を取っているのか等の詳細は割愛します。以下の記事がとてもわかりやすいです。
railsアプリに投稿されたYouTubeURLを自動的に埋め込み表示させる方法~無理やり編~
編集updateでやってみた(失敗)
新規投稿は上記の方法で実装できましたが、このままでは投稿の編集をする際、
例えば_全く別の動画のURLを貼り付けて更新する_と、"https://~~~"から始まる全ての文字列をデータベースに保存してしまいます。
当然このままではviewで表示した際に動画が正しく埋め込まれません。
「でも理屈は同じだから、updateアクションの前にURLを削ぎ落とす処理を足せばいいんじゃね?」と思って以下のようにやってみました。
※駄目な例です※
def update
@post = Post.find(params[:id])
# ここから
url = params[:post][:youtube_url].last(11)
@post.youtube_url = url # ここまで追加
if @post.update(post_params)
flash[:success] = '更新しました。'
redirect_to @post
else
flash.now[:danger] = '更新に失敗しました。'
render :edit
end
end
ただこれだと駄目でした。更新するとyoutube_urlのカラムにはURLがそのまま全部登録されてしまいます。何でや〜!!
結果わからなかったので、「発想の転換」
情けない話ですが、解決できませんでした。
しかしながら、色々調べていく中で"before_save"というコールバック関数に目をつけました。
「コントローラーじゃなく、モデル側でデータベースに保存する時に削ぎ落とせるのでは?」
Railsチュートリアルにはbefore_saveが使われている?ようですね。私は通っていないので知りませんでした。
before_saveを使うと、saveのメソッドが実行される直前に、指定した処理を行う事ができるようです。
(ちなみにbefore_updateという関数もあり、この場合はupdateの場合のみに実行される為、個別に指定する事もできます)
今回はcreateでもupdateでも「URLを削ぎ落とす」という処理は同じなので、before_saveで一括することにしました。
before_save
class Post < ApplicationRecord
before_save :slugify
def slugify
self.youtube_url = youtube_url.last(11)
end
end
slugify()というメソッドを定義し、その中身の処理としてURLを削ぎ落とす内容を記述しました。
(slugifyという言葉の使い方には誤りがあるかもしれないです。それっぽいワードが使いたかった)
ユーザーがformで入力した内容がsaveメソッドによりDBに保存されるまでは、パラメータとしてはyoutube_urlは"https://~~"の形で送られています。(これはターミナルにて確認できます。)
なので
youtube_url.last(11)
として末尾の11文字だけを取り出し、self.youtube_urlへ再度代入します。
そして、"before_save"によってデータベースへの保存の直前にその関数が呼び出されるようにしました。
不要な処理は削除します(create, updateアクション両方)
url = params[:post][:youtube_url].last(11)
@post.youtube_url = url
この処理はモデルファイルに書いたものと重複するので、削除します。
できた!
無事にURLが削ぎ落とされて、埋め込みが可能になりました。
参考記事
railsアプリに投稿されたYouTubeURLを自動的に埋め込み表示させる方法~無理やり編~
苦しめられてやっと理解できたRailsコールバックの使い方