はじめに
AMP対応
SEO対策のためAMP対応をしようと思ったのですが、AMPでは画像の縦横の幅を指定する必要があります。
今回はCarrierwaveとMiniMagickを使って画像をアップロードするときに画像の縦横幅も同時に保存し、
また、既存の画像のサイズも取得する処理をしたいと思います。
実装
前提
carrierwave
とminimagick
は既にインストールしているものとします。
また、Article
というモデルがあり、Articleがimage
というカラムを持っていて、下記のようにImageUploader
を使っているとします。
class Article < ApplicationRecord
mount_upload :image, ImageUploader
end
画像サイズの取得
実際に画像を表示するには、
%amp-img{src: @article.image, width: @article.image_width, height: @article.image_height}
のような形で表示させたいので、まずはArticle
モデルにimage_width
とimage_height
というカラムを追加します。
(実際に画像を保存しなくてもMiniMagickを使って画像サイズを取得することはできるのですが、画像を表示するたび、画像の枚数だけサイズを取得する処理が走るのは微妙なのでカラムを作って保存することにしました。)
$ rails g migration AddImageWidthAndImageHeightToArticles
class AddImageWidthAndImageHeightToArticles < ActiveRecord::Migration[5.0]
def change
add_column :articles, :image_width, :integer
add_column :articles, :image_height, :integer
end
end
rails db:migrate
画像サイズを取得し、保存するタイミングはCarrierwaveのafter store
のコールバックのタイミングにし、
save_image_size
というメソッドを走らせるようにします。
class ImageUploader < CarrierWave::Uploader::Base
include Carrierwave::Minimagick
after :store, :save_image_size
def save_image_size(file)
image_sizes = MiniMagick::Image.open(self.url).dimensions
self.model.update(image_width: image_sizes[0], image_height: image_sizes[1])
end
end
これでArticleを保存し、Carrierwaveのstoreが終わったタイミングで画像のサイズが保存されるようになります。
また、既存の画像のサイズも取得し直さないといけないのでその処理も書いておくので、コンソールで走らせるなり、ファイルを作ってruby runner
で走らせるなりしてやってみてください。
処理で何らかのエラーが出たときのために、エラーが出たデータのIDを見えるようにしておく。
Article.where.not(image: nil).find_each do |article|
if article.image_width.blank? || article.image_height.blank?
error_article_ids = []
begin
image_sizes = MiniMagick::Image.open(article.image.url).dimensions
article.update(image_width: image_sizes[0], image_height: image_sizes[1])
rescue
error_article_ids.push(article.id)
end
puts error_article_ids
end
end
まとめ
なんというか、こんなこといちいちしなくていいようにAMPでもよきに計らって画像を表示してほしいなと切に願います。。