heroku,Rails,Carrierwave,cloudinaryで画像アップロードを実装

Rails,Carrierwave,cloudinaryで画像アップロードを実装方法です。

f:id:ihatov08:20160906130811j:plain

Gemfileの追加

gem 'carrierwave'
gem 'cloudinary'
$ bundle install

uploaderの修正

開発時はpublic以下にファイルを保存して、cloudinaryは使用しないようにする

  if Rails.env.development?
storage :file
else
include Cloudinary::CarrierWave
end

credential

heroku使用時は下記のようにCLIを使用するか、画面上で追加するだけでOK。

heroku addons:create cloudinary

cloudinaryアドオンを追加するとCLOUDINARY_URL環境変数が追加される。
cloudinary gemはこの環境変数を自動的に読み込むので、コードを変更する必要はない。
cloudinary.ymlを設定する方法が他のブログで紹介されているが、環境変数のほうが簡単かつ、セキュアだ。
環境ごとに切り替えたければ、環境変数を変更すれば良い。

carrierwaveのinitializerの追加

config/initializers/carrierwave.rb

CarrierWave.configure do |config|
config.cache_storage = :file
end

これがないとcloudinary使用時に

Need to implement #cache! if you want to use Cloudinary::CarrierWave::Storage as a cache storage.

のエラーが発生する。

validationエラー時に、画像が表示されない。

carrierwaveのREADMEのとおり、下記のように実装するとvalidationエラー時に画像が表示されない。

<%= image_tag(listing.image.url) if listing.image? %>

対策

対策1:viewを修正する

cloudinaryはレコードが作成されたタイミングで画像がアップロードされるので、validationエラー時は存在しない画像URL
を参照するので、画像が表示されない。

対策は下記のようにcacheされている画像パスを指定した。

      <% if listing.main_image_cache %>
<%= image_tag "/#{listing.main_image.cache_path}" %>
<% else %>
<%= image_tag(listing.main_image.url) if listing.main_image? %>
<% end %>
<%= f.file_field :main_image, class: "form-control filter-input" %>

cacheはpublic以下にされるので、cache_pathで画像のパスを参照している。
先頭にスラッシュをつけないとasset pipelineの対象となりエラーになるので注意が必要。

対策2:urlメソッドをオーバーライドする

viewはそのままにurlメソッドを追加することでも対応できる。

cacheがある場合はcacheのパスを返し、それ以外の場合はCloudinary::CarrierWaveのurlメソッドをsuperで返す
ref:

github.com

class ImageUploader < CarrierWave::Uploader::Base
def url(*args)
if cached?
"/#{cache_path}"
else
super
end
end

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です