Rails6のアプリをherokuにデプロイしたいよ

herokuへのデプロイに紆余曲曲折折、悩みに悩んだ結果を残しておきたいと思います。

どなたかの救いになれば幸いです。

## 条件

今回私がハマった要因を抜粋しています。

```
m1 big sur 11.5.2

ruby 3.0.0
rails 6.1.4
pg
webpacker 5.0

bootstrap5
carrierwave
rspec
spring-commands-rspec
spring
```

## 前提

1. carrierwaveのdefault_urlで指定した画像を`assets/images`配下に置いている
    1. なおgitignoreで`assets/images`を管理
1. `bin/rspec`コマンドが使えるようにするため`$ bundle exec spring binstub rspec`を実行済

## heroku

herokuへの登録などは良記事がたくさんあるので今回は割愛させて頂きます。

## production環境

デプロイするにあたって以下のファイルを変更しておく必要があります。

`config/environments/productipon.rb`

```rb
## productionモードの時にある程度のクラスがキャッシュ化されて読み込みが早くなる。
config.cache_classes = true
## js, scssをpublic/packs/配下にコンパイルさせる設定。
config.assets.compile = true
```

##　platformによるエラー

兎にも角にもまずはpushしてみようじゃないかということで`$ git push heroku master`を実行。

...以下のログが出てきました。

```
$ git push heroku develop:master

remote:        Your bundle only supports platforms ["arm64-darwin-20"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.
remote:        Bundler Output: Your bundle only supports platforms ["arm64-darwin-20"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.
remote:
remote:  !
remote:  !     Failed to install gems via Bundler.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote:
remote:  !     Push failed
remote: Verifying deploy...
remote:
remote: !       Push rejected to basic-by.
remote:
```

この解決策としては以下のコマンドを実行することでplatformのエラーを回避することに成功。

```
$ bundle lock --add-platform x86_64-linux
```

ちなみに`bundle lock`とは...gemはインストールせずにGemfile.lockファイルだけを更新するためのコマンド

## spring関連のエラー

さて、プラットフォームのエラーが解決したことだし次のプッシュでうまくいくだろうと舐めた指で`$ git push heroku master`を実行すると、次は違うエラーログが発生

```
remote:  !
remote:  !     Could not detect rake tasks
remote:  !     ensure you can run `$ bundle exec rake -P` against your app
remote:  !     and using the production group of your Gemfile.
remote:  !     /tmp/build_02f98366/vendor/ruby-3.0.0/lib/ruby/3.0.0/rubygems/dependency.rb:307:in `to_specs': Could not find 'spring' (= 3.0.0) among 184 total gem(s) (Gem::MissingSpecError)
remote:  !     Checked in 'GEM_PATH=/tmp/build_02f98366/vendor/bundle/ruby/3.0.0' , execute `gem env` for more information
remote:  !     from /tmp/build_02f98366/vendor/ruby-3.0.0/lib/ruby/3.0.0/rubygems/dependency.rb:319:in `to_spec'
remote:  !     from /tmp/build_02f98366/vendor/ruby-3.0.0/lib/ruby/3.0.0/rubygems/core_ext/kernel_gem.rb:62:in `gem'
remote:  !     from /tmp/build_02f98366/bin/spring:14:in `<top (required)>'
remote:  !     from /tmp/build_02f98366/bin/rake:2:in `load'
remote:  !     from /tmp/build_02f98366/bin/rake:2:in `<main>'
remote:  !

remote:  !     Push rejected, failed to compile Ruby app.
remote:
remote:  !     Push failed
remote: Verifying deploy...
remote:
remote: !       Push rejected to peaceful-escarpment-36805.
remote:
To https://git.heroku.com/peaceful-escarpment-36805.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/peaceful-escarpment-36805.git'
```

どうやら、spring関連のエラーが出ているぞと。

今回のエラーを解決するために以下の手順を踏みました。

1. gem `spring-commands-rspec`を削除
1. gem 'spring'を削除
1. `$ bundle exec spring binstub rspe`コマンドを実行する前の状態に戻す

rails6.1以降から`bin/rspec`などの`bin/`操作ができなくなったみたいです。

が、まだ正常デプロイできません...


## Precompiling assets failed

次は以下のようなログが出てきました。

```
remote:        rake aborted!
remote:        Sprockets::ArgumentError: link_tree argument must be a directory
remote:        /tmp/build_ed88c512/app/assets/config/manifest.js:1
remote:        /tmp/build_ed88c512/vendor/bundle/ruby/3.0.0/gems/sprockets-4.0.2/lib/sprockets/directive_processor.rb:389:in `expand_relative_dirname'
remote:        /tmp/build_ed88c512/vendor/bundle/ruby/3.0.0/gems/sprockets-4.0.2/lib/sprockets/directive_processor.rb:341:in `process_link_tree_directive'
remote:        /tmp/build_ed88c512/vendor/bundle/ruby/3.0.0/gems/sprockets-4.0.2/lib/sprockets/directive_processor.rb:189:in `block in process_directives'
remote:        /tmp/build_ed88c512/vendor/bundle/ruby/3.0.0/gems/sprockets-4.0.2/lib/sprockets/directive_processor.rb:187:in `each'
remote:        /tmp/build_ed88c512/vendor/bundle/ruby/3.0.0/gems/sprockets-4.0.2/lib/sprockets/directive_processor.rb:187:in `process_directives'
remote:        /tmp/build_ed88c512/vendor/bundle/ruby/3.0.0/gems/sprockets-4.0
```

`assets/config/manifest.js`がうんたらこうたら言われてるので該当ファイルを見てみることに

```js
//= link_tree ../images
//= link_directory ../stylesheets .css
```

link_treeが参照している`../images`は`assets/images`　は、carrierwaveのdefault_urlで指定した画像を配置しているフォルダなのですが、私はいっそのこと`assets/images`フォルダを使わないように、デフォルト画像の配置を変更することにしました。

1. `//= link_tree ../images`の記述を削除
1. `assets/images`フォルダを丸ごと削除
1. xxx_uploader.rbを編集
    1. 設定した画像を`public/images`配下に配置
    1. gitignoreから`public/images`を外す

xxx_uploader.rb

```rb

def default_url(*args)
  "/images/" + [version_name, '任意の名前.png'].compact.join('_')
end
```

## push!!

以上の修正を行うことで、正常にデプロイすることができました。