Rails,Carrierwave,cloudinaryで画像アップロードを実装方法です。
目次
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:
class ImageUploader < CarrierWave::Uploader::Base def url(*args) if cached? "/#{cache_path}" else super end end
コメントを残す