いわりょのBlog

IT関連で学んだことを書いていきます。

記事の最初のimgタグを取得してサムネイル画像に使う

HTML文で記事内容を保存している場合、 記事サムネイルを設定したいときの問題


記事投稿システムを作ったときに記事の内容にCkeditorを使用しています。
記事画像はArticleモデルにpictureカラムは作らずに
imgタグでHTML文でパスを直接書き込まれています。

Article.all = title: "テスト", content: "<p><img alt=\"\" src=\"/uploads/ckeditor/pictures/5/c..." ...

content: で画像パスを直接書き込んでいる

↓こちら記事書かれたような内容でリッチテキストエディタを設定しました。
paranishian.hateblo.jp


そのため、Topページなどで記事のサムネイル画像を表示したいときに、
記事モデルのカラムに画像データのみを持っているわけではないので
単純に@article.pictureとビューで書いてサムネを表示することはできません。
@article.contentでそのまま表示させても余計なものまで現れてしまします。

この場合contentカラムから最初のタグを取得して画像を表示させます。

imgタグ取得方法


今回は最初のタグを正規表現とmatchメソッドを使っていきます。

正規表現はこちらの記事を参考に、、、↓↓↓
WordPressで記事内の最初の画像をアイキャッチ代わりに使う方法 | ホームページ制作 福岡のアイドットデザイン

/<img.+src=[\'"]([^\'"]+)[\'"].*>/i

を使用します。

あとはmatchメソッドでArticleのcontentカラムの内容を検索させれば最初の画像を取得できます!

pattern = /<img.+src=[\'"]([^\'"]+)[\'"].*>/i
@article.content.match(pattern)

アプリ開発ではrailsを使っているのでHelperメソッドを作っとくと便利かも

 #記事の最初の画像を読み取りサムネイルにする
    def article_thumb(content)

        pattern = /<img.+src=[\'"]([^\'"]+)[\'"].*>/i
        image = content.match(pattern)
       
        if image

            image[0] #[0]はマッチした部分を表示します
   
  #画像がなけれがデフォルト画像を取得
        else

            image_tag 'defalut.jpg'

        end
    end

使ってみた

例としてTOPニュース3件のサムネイルを表示してみました。
画像取得以外ののViewやrubyの記述は省略しますが、、、

この下記の内容のようなTOPニュース3件の内容があったとします。
HTML文なので複雑に書かれていますが、眺めるとimgタグがちりばめてあるなーぐらいで思ってください。

irb(main)> article1.content
=> "<p><img (中略)/aaa.jpg\" /></p>\n\n<p>テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1テスト1</p>\n"

irb(main)> article2.content
=> "<p><img (中略)/bbb.jpg\" /></p>\n\n<p>&nbsp;</p>\n\n<p>テスト2テスト2テスト2テスト2テスト2テスト2テスト2テスト2テスト2テスト2テスト2テスト2テスト2テスト2テスト2テスト2</p>\n\n<p>&nbsp;</p>\n\n<p><img (中略)/ccc.jpg\" /></p>\n\n<p>&nbsp;</p>\n"

irb(main)> article3.content                  
=> "<p><img (中略)/ddd.jpg\" /></p>\n\n<p><img (中略)/eee.jpg\" /></p>\n\n<p>テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3テスト3</p>\n"

この状態で

_top_news.html.erb

<div class="top-news-content">
 <div class="news-1"
     <%== article_thumb(article1.content) %>
  (中略)
 </div>
 <div class="news-2"
     <%== article_thumb(article2.content) %>
  (中略)
 </div>
  <div class="news-3"
     <%== article_thumb(article3.content) %>
  (中略)
 </div>
</div>

のようにViewにかけば、、、

f:id:Ryo10Leo:20200103141015p:plain

サムネが表示されました!