Cloudinary + Carrierwave + Heroku + Railsでの画像を手軽に利用する方法

現在、Herokuで利用されているCedarスタックは、画像の保存はできるものの、Herokuを再起動したり、Pushすると保存していた画像が消えてしまいます。
そのため、Herokuのアプリケーション内で画像を保存するためには外部のストレージが必須です。
AWSのS3などもありますが、Herokuと親和性の高いCloudinaryがすごく便利です。
備忘録としてまとめましたので、ご活用ください。

##Heokuへの追加とCloudinaryでの確認

###Herokuへの追加
まずは、Herokuにアドオンを追加します

 ```ruby:console
$heroku addons:add cloudinary:starter
```

または HerokuのdashboardからAdd-onsからCloudinaryを追加して下さい。
 ※最初はStarterで良いと思います。

###Cloudinaryでの確認
1. HerokuのAppからアドオンを追加したアプリを選択しでCloudinaryをクリックしすると、Herokuと連携したCloudinaryのWebサイトが開きます。

2. はじめてCloudinaryのサイトを開くと、あなたはどの言語／フレームワークを利用しますか？のような質問がでてきますので、ここではRuby on Railsを選択します。

3. RoRに関するドキュメントが表示されます。
**Configuration**の項に**download your customized cloudinary.yml configuration file**というリンクから、``cloudinary.yml``をダウンロードしておいてください。

##CloudinaryとCarrierwaveの実装
###もろもろ追加
gemを追加します

```ruby:console
$gem install carrierwave
$gem install cloudinary
```

Gemfileへ追加。ついでにHerokuの環境も追加。

```ruby:gemfile
source 'https://rubygems.org'

gem 'rails', '3.2.8'

gem 'carrierwave'
gem 'cloudinary'

gem 'heroku'

group :test, :development do
	gem 'sqlite3'
end

group :production do
	gem 'pg'
	gem 'thin'
end

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
```

bundle installを実行

```ruby:console
$bundle install
```

###デモアプリ作成
ユーザー名と顔写真を表示するアプリです。

```ruby:console
$rails new coudinary_demo

$cd cloudinary_demo

$rm -f public/index.html

$rails g scaffold User name:string avatar:string remove_avatar:boolean avatar_cache:string

$rake db:migrate
```

``avatar`` は保存する画像を文字列にして保存。
``remove_avatar`` は画像の削除に利用。
``avatar_cache`` は画像のアップロードが失敗時、表示するために利用。


```ruby:config/routes.rb
CloudinaryDemo::Application.routes.draw do
  resources :users
  
  root :to => 'users#index'  
end
```

ブラウザでhttp://localhost:3000にアクセスするとアプリのトップ画面が表示されます。

####avatar_uploader.rbを作成
次に画像のアップローダーを作ります。

```ruby:console
rails g uploader Avatar
```

####avatar_uploader.rbを編集
コメントで色々と入力されていますが、
ざっくり置き換えて下さい。

```ruby:app/avatar_uploader.rb
# encoding: utf-8
class AvatarUploader < CarrierWave::Uploader::Base

  include Cloudinary::CarrierWave

  process :convert => 'png'
  process :tags => ['avatar']
  
  version :standard do
    process :resize_to_fill => [100, 150, :north]
  end
  
  version :thumbnail do
    process :resize_to_fit => [50, 50]
  end

  def public_id
    return model.id ・・・※1
  end
  
end
```

※1 **public_id**でCloudinaryから画像を参照できるので、都合のいい値を設定すれば便利です。UserのAvatarならUser.idが良いと思います。

####user.rbを編集
uploaderとUserモデルを関連付けます。

```ruby:app/models/user.rb
class User < ActiveRecord::Base
  attr_accessible :avatar, :avatar_cache, :name, :remove_avatar
  
  mount_uploader :avatar, AvatarUploader
  
end
```

####database.ymlを追加
忘れないうちにファイルを追加しておきましょう。先ほどダウンロードした、``cloudinary.yml``を``config``フォルダに保存します。``database.yml``と同じ階層です。

####new.html.erbとedit.html.erbの編集
Scaffoldで作成されたviewの``new.html.erb``と``edit.html.erb``は、``_form.html.erb``を共有しているので、``_form.html.erb``を編集します。

```ruby:app/views/_form.html.erb
<%= form_for(@user) do |f| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% @user.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
		<%= image_tag(@user.avatar_url(:thumbnail), :width => 80, :height => 80) %>
		<%= f.file_field :avatar %>
		<%= f.check_box :remove_avatar %> 画像を削除する
		<%= f.hidden_field :avatar_cache %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
```
####index.html.erbとshow.html.erbの編集
index.html.erbは名前だけ表示。

```ruby:app/views/users/index.html.erb
<h1>Listing users</h1>

<table>
  <tr>
    <th>Name</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @users.each do |user| %>
  <tr>
    <td><%= user.name %></td>
    <td><%= link_to 'Show', user %></td>
    <td><%= link_to 'Edit', edit_user_path(user) %></td>
    <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New User', new_user_path %>

```

show.html.erbは名前と画像だけ表示

```ruby:app/views/users/show.html.erb
<p id="notice"><%= notice %></p>

<p>
  <b>Name:</b>
  <%= @user.name %>
</p>

<p>
  <b>Avatar:</b>
  <%= image_tag(@user.avatar_url) %>
</p>


<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>

```

画像のリサイズなどはCloudinaryでいろいろと提供されていますので、試してみて下さい。
http://cloudinary.com/documentation/image_transformations

では、Herokuへpushします。

```ruby:console
$git init  ※gitの初期化 最初だけ
$git add .
$git commit -m 'first commit'
$git push heroku master
```

Herokuを開いてみましょう。

```ruby:console
$heroku open
```

これで、画像の表示、アップロード、削除ができるアプリの完成です。
***
画像リサイズは、Rmagikやminimagikなどを利用したり（私はこれに超絶ハマりました^^;）
画像ストレージは、AWSのS3を利用したりなど、色々とハードルが高いですが、
この方法は比較的手軽に活用できるのではないかと思います。
ぜひぜひお試しください！これが無料で使えるというのがすごいですね。。
***
via http://cloudinary.com/documentation/rails_integration
via https://github.com/jnicklas/carrierwave