Rails + cloudinary + carrier wave 画像アップロードアプリのテスト

# 環境
ruby 2.5
rails 5系
github
heroku

# 準備作業

```zsh
cd ~/Projects/_rails
mkdir test_cloudinary
cd test_cloudinary
bundle init
echo -e "ruby '2.5.0'\ngem 'rails'" >> Gemfile
bundle install --path vendor/bundle --jobs=4
bundle exec rails new -B .

#GemfileがコンフリクトするのでyでOverwrite
y
```
```rb:Gemfile
#gem 'sqlite3'
gem 'sqlite3', group: [:development, :test]
gem 'pg', group: :production
```
```zsh
echo -e "\ngem 'carrierwave'\ngem 'cloudinary'\ngem 'bootstrap-sass'" >> Gemfile

bundle
```
```zsh
echo -e "\n/vendor/bundle\n/.envrc\n/public/uploads/tmp/\n/public/uploads/micropost/image/" >> .gitignore
```
```zsh
git add .
git commit -m "first commit"
```
[Githubでリポジトリを作成](https://github.com/new)してくる
リポジトリ名は「test_cloudinary」

```zsh
git remote add origin https://github.com/hogemax/test_cloudinary.git
git push -u origin master                                           
```

# 構築作業
### アップローダーファイルの作成
```zsh
bundle exec rails g uploader Image
```
```rb:app/uploaders/image_uploader.rb
  include Cloudinary::CarrierWave

  process :convert => 'png' # 画像の保存形式
  process :tags => ['image'] # 保存時に添付されるタグ（管理しやすいように適宜変更しましょう）

  process :resize_to_limit => [700, 700] # 任意でリサイズの制限

  # 保存する画像の種類をサイズ別に設定
  version :standard do
    process :resize_to_fill => [100, 150, :north]
  end

  version :thumb do
    process :resize_to_fit => [50, 50]
  end

  #　「storage :file」　が有効になっているとCloudinaryに画像アップロードできない　↓
  
  # Choose what kind of storage to use for this uploader:
  #storage :file
  # storage :fog
```
>[How to upload images to folders with CarrierWave 
( ※ コメ欄のコードがGoodJob)](https://support.cloudinary.com/hc/en-us/articles/202519922-How-to-upload-images-to-folders-with-CarrierWave)

```rb:
# アップロードした画像ファイルを任意のフォルダに保存する場合は
# 下記のように任意のフォルダ名を指定できる 例：「local_test_cloudinary」

  def public_id
    return "local_test_cloudinary/" + Cloudinary::Utils.random_public_id;
  end
```
フォルダの自動生成機能を利用するにはCloudinaryのセッティングページから`Auto-create folders:` を `Enabled`にしておく必要がある [Cloudinary | Settings - Upload](https://cloudinary.com/console/settings/upload)

---

#### 本番では`Cloudinary`使うけど開発ではローカルに保存する設定、の場合
`Rails.env`とかで切り分けの設定しとく

```rb
if Rails.env.production?
    include Cloudinary::CarrierWave
    # 本番用設定を書く
else
    include CarrierWave::RMagick
    # 開発・テスト用設定を書く
end
```

ちなみに、上記のように開発環境で**RMagick**の**Gem**を利用する場合、（インストール&Gem追加 されてなければ）`imagemagick`のインストールと`Gem（Gemfile）`追加作業を済ませておく

```zsh:
# 「imagemagick」はhomebrewでインストール

# インストールされているか確認
brew list | grep imagemagick

# homebrewでimagemagickを（ver6系で）インストール
brew install imagemagick@6
brew link --force imagemagick@6

# gemの追加
echo -e "gem 'rmagick'" >> Gemfile
bundle
```

>
[bundle install "rmagick" でインストールができない](https://qiita.com/sho012b/items/362abe993248c686fcf4)

---

### 投稿処理（Microposts）の作成
```
bundle exec rails g scaffold Microposts name:string image:string
bundle exec rails db:migrate
```
### Uploaderファイルを関連付け
```rb:app/models/micropost.rb
  mount_uploader :image, ImageUploader
```
### cloudinary設定ファイルの用意
`cloudinary.yml`ファイルの**[ダウンロード](https://cloudinary.com/console/lui/cloudinary.yml)**（多分、**ログイン**が必要）
ファイルは`config`配下に置く。

```zsh:ダウンロードフォルダから直接コピーするコマンド
# 現在位置の確認
pwd
# ***/***/***/test_cloudinary

# プロジェクトディレクトリ(test_cloudinary)内にいる想定で
cp $HOME/Downloads/cloudinary.yml config/cloudinary.yml
```

### 環境変数設定
`※ Gitにあげない場合はこの項目は読み飛ばす。`

事前に[`direnv`](https://qiita.com/ntkgcj/items/125892b4459bc469f7ac)を使えるようにしておく。

**Githubにコミットする場合はコミット前に**`cloudinary.yml`ファイル内の
APIキーなどを**環境変数に置き換え**ておく。（そのままリポジトリにあげちゃうと**マズイ**ので。）

```zsh
direnv edit .
```
```rb:.envrc
#cloudinaryAPI認証用
export CLOUDINARY_CLOUD_NAME="xxxxxxxxxx"
export CLOUDINARY_API_KEY="xxxxxxxxxxxxx"
export CLOUDINARY_API_SECRET="xxxxxxxxxxxxx"
```
で、`cloudinary.yml`ファイルの内容も置き換え。

```yml:config/cloudinary.yml
---
development:
  cloud_name: ENV['CLOUDINARY_CLOUD_NAME']
  api_key: ENV['CLOUDINARY_API_KEY']
  api_secret: ENV['CLOUDINARY_API_SECRET']
  enhance_image_tag: true
  static_image_support: false
production:
  cloud_name: ENV['CLOUDINARY_CLOUD_NAME']
  api_key: ENV['CLOUDINARY_API_KEY']
  api_secret: ENV['CLOUDINARY_API_SECRET']
  enhance_image_tag: true
  static_image_support: true
test:
  cloud_name: ENV['CLOUDINARY_CLOUD_NAME']
  api_key: ENV['CLOUDINARY_API_KEY']
  api_secret: ENV['CLOUDINARY_API_SECRET']
  enhance_image_tag: true
  static_image_support: false
```
>[Developer solution overview | Cloudinary](https://cloudinary.com/documentation/solution_overview#configuration_parameters)

### 各viewファイルの修正

```erb:app/views/microposts/_form.html.erb

  <div class="field">
    <%= form.label :image %>
    <%= image_tag(micropost.image_url(:thumb), :width => 80, :height => 80) %>
    <%= form.file_field :image %>
  </div>
```
```erb:app/views/microposts/index.html.erb
<!-- ↓ これは消す -->
<!--        <td><%= micropost.image %></td> -->

<!-- ↓ こっちを適用（残す） -->
        <td><%= cl_image_tag(micropost.image_url(:thumb), :alt => micropost.name) %></td>
```
```rb:app/views/microposts/show.html.erb
<% if @micropost.image? %>
<p>
  <strong>Image:</strong>
  <!-- 画像表示 --> 
  <%= image_tag(@micropost.image_url, :alt => @micropost.name) %>
</p>
<p>
  <!-- id（URL）確認用 -->
  <%= @micropost.image_url.to_str %>
</p>
<% end %>
```

`strong paramater` を確認。
（おそらくデフォルトで以下内容が入力されてると思う）

```rb:app/controllers/microposts_controller.rb
    def micropost_params
      params.require(:micropost).permit(:name, :image)
    end
```

# その他
### ルーティング設定
```config:config/routes.rb
   root 'microposts#index'
```
### bootstrap(CSS)の反映（やらなくてもいいよ）
```zsh
vim app/assets/stylesheets/custom.css.scss
```

```scss:app/assets/stylesheets/custom.css.scss
@import "bootstrap-sprockets";
@import "bootstrap";
```

## Githubにアップ
開発で動作確認できたらGitに（あげたい人は）あげる

```zsh
git add .
git commit -m "Make Image Upload Function"
git push
```

# ~~アドオン（本番環境用）~~
設定ができていればherokuの`addon(cloudinary)`は入れなくてもいいっぽい

# Herokuにアップする
本番環境（Heroku）にプロジェクトを載せて動かしてみるとか。
作業は下記参考に
[Herokuにプロジェクト載せてサービス公開](https://qiita.com/ntkgcj/items/8e757c9cce9c53705dfe)

既存のサービスに機能追加として画像登録を追加する場合
（もうすでに一度Herokuにプロジェクトが上がっている場合は）

```zsh
git push heroku master
```
でおk

###　環境変数の登録
先ほど設定した`Cloudinary`用の環境変数をHeroku側にコマンドで登録する。

```zsh
heroku config:set CLOUDINARY_CLOUD_NAME=xxxxxxxxxx
heroku config:set CLOUDINARY_API_KEY=xxxxxxxxxx
heroku config:set CLOUDINARY_API_SECRET=xxxxxxxxxx
```

動作確認して見て正常にアップできていればおkでは

# 参考
>[CarrierWave integration | Cloudinary](https://cloudinary.com/documentation/rails_carrierwave)
[Cloudinary + Carrierwave + Heroku + Railsでの画像を手軽に利用する方法](https://qiita.com/GenTamura84/items/38cf899827bba050a21c)
[Using Cloudinary and CarrierWave for Rails Image Uploading](http://www.uberobert.com/rails_cloudinary_carrierwave/)
[How to upload images to folders with CarrierWave ( ※ コメント欄のコードがGoodJobだった)](https://support.cloudinary.com/hc/en-us/articles/202519922-How-to-upload-images-to-folders-with-CarrierWave)
[cloudinary_gem/samples at master · cloudinary/cloudinary_gem · GitHub](https://github.com/cloudinary/cloudinary_gem/tree/master/samples)
[Ruby好き非エンジニアのブログ](http://jyoko.hatenablog.com/?page=1484324472)
[Ckeditorの画像アップロードをCloudinaryに変更する](https://qiita.com/sayama0402/items/26f676156741d6b5ebcd)
[jQueryを使ったCloudinaryのダイレクトアップロード - KayaMemo](http://kayakuguri.github.io/blog/2017/04/11/cloudinary-direct-upload/)
>[マイグレーションを使ったカラムの追加、削除、データ型の変更　[ 自分用メモ ]](https://qiita.com/dawn_628/items/13fa64dc6d600e921ce3)
[Rails の Model 作成時に単数形・複数形の変換がおかしい場合の対処法](https://qiita.com/Salinger/items/c48f999d4d7211f16fce)
[Rails4はattr_accessibleが使えない](https://qiita.com/s_kawa/items/57c6c95b39f961a18453)