Rails5×Carrierwave×RMagick×Cloudinary→"App Crashed"!

###Herokuに画像を上げるストレージにCloudinaryを使おう！
[以前の記事](https://qiita.com/shiroux/items/ac80cdb40949193a1750)の続きになります。
Carrierwave×RMagickの設定ではHerokuのストレージを指定していない為、Amazon S3などのストレージサービスの利用を検討。そこで今回はCloudinaryを使うことに。

###Cloudinaryを追加
[Cloudinary + Carrierwave + Heroku + Railsでの画像を手軽に利用する方法](https://qiita.com/GenTamura84/items/38cf899827bba050a21c#cloudinary%E3%81%A8carrierwave%E3%81%AE%E5%AE%9F%E8%A3%85)を参考に設定を記述。
そして問題が発生。

>```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
>```

uploader.rbファイルの設定である。RMagickを使ってやっとのことで画像リサイズが可能になったのに、ストレージとして追加しようとしているCloudinaryの方にもリサイズ機能が備わっているではありませんか。
ちなみに`include Cloudinary::CarrierWave`と記述するだけでは

```terminal
NoMethodError in ItemsController#create
undefined method `tags' for #<ImagesUploader:0x00007fdd88a15690>
```
このようなエラーが帰って来ます。解決策が全く検索にHitしなかったのですが、

```ruby
if Rails.env.production?
```
を追記することで解決します。

###Cloudinary × Carrierwave×RMagick
[Rails + cloudinary + carrier wave 画像アップロードアプリのテスト](https://qiita.com/ntkgcj/items/6ca19c9decf929714970)を参考に条件分岐を追加

```images.uploader.rb
class ImagesUploader < CarrierWave::Uploader::Base
  if Rails.env.production?
    include Cloudinary::CarrierWave
    process :convert => 'png'
    process :tags => ['image']

    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
    end

  else
    include CarrierWave::RMagick
    process resize_to_fill: [128,128]
    storage :file
    # アップロードファイルの保存先ディレクトリは上書き可能
    # 下記はデフォルトの保存先
    def store_dir
      "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
    end
    # アップロード可能な拡張子のリスト
    def extension_white_list
      %w(jpg jpeg gif png)
    end
  end
end
```

続いてview _form.html.erbの設定なのですが

```erb
<%= image_tag(micropost.image_url(:thumb), :width => 80, :height => 80) %>
```

この記述が`nil location`や`no method error`など、`image_tag`あるいは`.image_url`という記述では画像を認識することが出来なかったので、元のRMgick設定の際に利用した、`form.file_field`で代用。

```erb
<div class="field">
    <%= form.label :image %>
    <%= form.file_field :image %>
    <%= form.file_field :image, id: :items_image_path %>
  </div>
```

###ローカル環境では問題なく動く
`rails s`でサーバーを立ち上げて試しに画像をUpして問題なく動作することを確認。
`git push heroku master`　Herokuにデプロイしてあとは本番環境の動作確認が取れれば終了だー！


###Heroku Open App

```
Application error
An error occurred in the application and your page could not be served. 
If you are the application owner, check your logs for details. 
You can do this from the Heroku CLI with the command
```

なるほど。何が問題だったのかlogsで確認。すると

```terminal

 /app/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.3.1/lib/bootsnap/load_path_cache/core_ext/active_support.rb:53:in `block in load_missing_constant': uninitialized constant ImagesUploader::Cloudinary (NameError)
```

なるほど。
ローカル環境でRMagickの設定をコメントアウトしてCloudinaryのみにして画像アップロード機能を実装した時と全く同じエラーがここで発生。

###解決策１
[carrierwaveで NameError uninitialized-constantのようなメッセージが出た場合](https://qiita.com/h5y1m141@github/items/97e1941086c7f9f229ac)を参考に

```ruby
  config.autoload_paths += Dir[Rails.root.join('app', 'uploaders')]
```
の記述を追加。
果たして効果はなく、"App Crashed!"

###解決策２
[Rubyでのハマりポイント](https://qiita.com/ikedahidenori/items/66c2ea4d2c5205d809f0#nameerror---uninitialized-constant-objectsomething)を参考に、そもそもuninitialize constantとは`定義されてません！`だし、単純な解決策の方が当たるのではないかと

```ruby
class ImagesUploader < CarrierWave::Uploader::Base #Imageに変更
```
他にも複数形で記述されているImagesの設定を全てImageに変えてデプロイ。
当然のごとく効果はなく、"App Crashed"
というよりコントローラーには他にも複数形で設定していて、今まで問題が起きていない箇所がある上に、そもそもCloudinaryを追加する前は問題なく動いていたのだから、Cloudinaryにまつわる箇所である筈...

###それもその筈・・・。
自己解決。なんと、Gemfileに `gem Cloudinary`の記述が無かった。
あっけなかった。。。
同時に複数のrailsアプリを編集していたことが原因で見落としていました。
これは酷い、お騒がせいたしました。

###本番環境実行結果

```terminal
FATAL -- : [ee52ee38-f67f-4625-9af4-753a42b3d4c4]
NameError (undefined local variable or method `image' for #<ItemsController:0x00000000060d8c88>):
app/controllers/items_controller.rb:78:in `item_params'
app/controllers/items_controller.rb:28:in `create'

```
エラー。
ローカルでRmagick×Carrierwaveを用いる場合は問題なく動くコードが、Cloudinary×Carriewwaveで問題を発生。
controller側での定義がなされていないとのことではあるが、参考サイトの方にコントローラーメソッドの記述は見当たらない..
挙げ句の果てにLocal環境で画像のUPを試すと同じエラーが出現。
Cloudinaryを追加したことで一体どうなってしまったんだ・・・。

###原因究明
まず `git status`で変更したファイルを洗い出し
次に`git checkout --ファイル名`で全ての変更を取り消す。
改めてリンク先のチュートリアルに沿って設定を実行。

最終的に判明したのがuploaderにあるこの記述がエラーの原因であった

```images.uploader.rb
class ImagesUploader < CarrierWave::Uploader::Base
  if Rails.env.production?
    include Cloudinary::CarrierWave
    process :convert => 'png'
    process :tags => ['image']

    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
    end

  else　#←この記述が不要
    include CarrierWave::RMagick
    process resize_to_fill: [128,128]
    storage :file
    # アップロードファイルの保存先ディレクトリは上書き可能
    # 下記はデフォルトの保存先
    def store_dir
      "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
    end
    # アップロード可能な拡張子のリスト
    def extension_white_list
      %w(jpg jpeg gif png)
    end
  end
end
```

`include CarrierWave::RMagick`と`include Cloudinary::CarrierWave`は条件分岐で分けないと共存出来ないと勘違いしていた。この記述を書き換えて以下のようにする。

###最終解決コード
```images.uploader.rb
class ImagesUploader < CarrierWave::Uploader::Base
    include Cloudinary::CarrierWave if Rails.env.production?
    include CarrierWave::RMagick
    process resize_to_fill: [128,128]
    storage :file
    # アップロードファイルの保存先ディレクトリは上書き可能
    # 下記はデフォルトの保存先
    def store_dir
      "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
    end
    # アップロード可能な拡張子のリスト
    def extension_white_list
      %w(jpg jpeg gif png)
    end
  end
end
```
これで無事画像アップロード機能を実装することが出来ました。