Rails6.0でRailsチュートリアル(Rails5.1)を完了させる時に詰まるポイント

# はじめに

Rails入門として非常にメジャーな[Ruby on Rails チュートリアル](https://railstutorial.jp/)ですが、Rails5.1と、3年前のバージョンがベースになっています。
それと比較し、Railsの最新バージョンは記事執筆現在6.0.2です。

マイナーバージョンならまだしも、メジャーバージョンも5→6となっているため、これからRailsを学ぶ方はRails6をベースに学習したいのではないでしょうか。

というわけで、Rails5.1で書かれたチュートリアルを、Rails6.0で動かした際に詰まるポイントをまとめました。
ですが、このページを常に開きながら、詰まった時にすぐに見て…というやり方はあまりオススメしません。
なぜなら詰まった時にこそ、エラーを読んでいろいろ調べることで得られる知識も多いためです。
詰まった際に15分、20分と解決しなかった際に本記事を参照いただけると幸いです。

なお、大前提、AWS Cloud9の構築です。

# ■1章

## sqlite3のバージョンエラー

Cloud9の環境構築時にPlatformデフォルトがAmazon Linuxになっていますが、Ubuntuを選びましょう。
Amazon Linuxを選ぶとRails6入れた際のsqlite3のバージョンが足りず詰まります。

## bundle installとかでなんかコケる

とりあえず

> リスト 1.4: hello_appディレクトリにあるデフォルトのGemfile

はガン無視して、Rails6でアプリケーション作ったまま何も弄らず実行しましょう。

## rails s(server)を実行したけどアプリケーションが動かない

> 図 1.12: アプリケーションをブラウザで開いたときの画面

このスクショをよく見ましょう。
Cloud9の分割ウィンドウでは実行結果が見れず、新規ウィンドウで開かないと見れません。

## rails sでアプリケーション開いたけど謎エラー　To allow requests to xxxxxxxxxx〜〜〜

```
To allow requests to xxxxxxxxxx.cloud9.ap-northeast-1.amazonaws.com, add the following to your environment configuration:
```

Rails6からconfigに自身のhost書かないと弾かれます

```diff:config/application.rb
module HelloApp
  class Application < Rails::Application
...

+    config.hosts << '.amazonaws.com'

...
  end
end
```

書いただけでは即座に反映されないので、rails sをCtrl+Cで一旦止めて、再度rails s実行

## productionのPostgresとdevelopmentのsqlite3

チュートリアルでは
```rb:Gemfile
  gem 'sqlite3', '1.3.13'
```

となっていますが、


```diff
 # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
 gem 'rails', '~> 6.0.2', '>= 6.0.2.1'
-# Use sqlite3 as the database for Active Record
-gem 'sqlite3', '~> 1.4'

...

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
+ # Use sqlite3 as the database for Active Record
+ gem 'sqlite3', '~> 1.4'
end

...


+ group :production do
+  gem 'pg', '0.20.0'
+ end
```

こうなりますね

## herokuでもhost弾かれる

同じくhostが弾かれるので、

```diff:config/application.rb
module HelloApp
  class Application < Rails::Application
...

    config.hosts << '.amazonaws.com'
+   config.hosts << '.herokuapp.com'

...
  end
end
```

# ■2章

最初のGemfile、そしてhost問題は上記と同じ対応で解決


# ■3章

3章でも最初のGemfile、そしてhost問題は1章と同じ対応で解決

## テストが403でコケる

```
Failure:
StaticPagesControllerTest#test_should_get_home [/home/ubuntu/environment/sample_app/test/controllers/static_pages_controller_test.rb:6]:
Expected response to be a <2XX: success>, but was a <403: Forbidden>
```

試しにhostのチェックをしないconfig.hosts.clearを追加すると、コケずに通ります。
ということはやはりここが原因で、test時のhostはamazonaws.comではないためにコケている模様。
Cloud9のaws.amazon.comを追加しても動かないので、testで

```diff:test/controllers/static_pages_controller_test.rb
  test "should get home" do
    get static_pages_home_url
+   p request.host_with_port
    assert_response :success
  end
```

これで実行すると

```
rails test test/controllers/static_pages_controller_test.rb:10

"www.example.com"
```

と出ます。
どうやらtestはwww.example.comで実行される模様。よって

```diff:config/application.rb
module HelloApp
  class Application < Rails::Application
...

    config.hosts << '.amazonaws.com'
    config.hosts << '.herokuapp.com'
+   config.hosts << 'www.example.com'

...
  end
end
```

これでOKです。

```
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
```

## リスト 3.35:付近　app/views/layouts/application.html.erbを直した後にtestがコケる

```
ActionView::Template::Error: The asset "application.js" is not present in the asset pipeline.
```

jsタグの書き方が変わっているので、サンプルそのままコピペだと動かないです。

```diff:app/views/layouts/application.html.erb
-   <%# javascript_include_tag 'application',
-                              'data-turbolinks-track': 'reload' %>
+   <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```

Rails6でrails newした時のデフォルト記述に戻す。これでOK

## minitest reportersがコケる

エラーの最終行をよく読む

```
/home/ubuntu/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:34:in `require': cannot load such file -- minitest/reporters (LoadError)
```

GemfileをRails6でrails newした関係でいじっていなかったことを思い出す。
入れましょう。

```diff:Gemfile
group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of web drivers to run system tests with browsers
  gem 'webdrivers'
+ gem 'minitest',                 '5.10.3'
+ gem 'minitest-reporters',       '1.1.14'
+ gem 'guard',                    '2.13.0'
+ gem 'guard-minitest',           '2.4.4'
end
```

```
$ bundle install
$ rails t
Running via Spring preloader in process 4865
Started with run options --seed 879

  5/5: [==================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.12243s
5 tests, 9 assertions, 0 failures, 0 errors, 0 skips
```
OK。

## Guard入れる時にyum使えない

```
$ sudo yum install -y tmux
sudo: yum: command not found
```

この記事の通りに進めていたらAmazon LinuxではなくUbuntuのはず。
なのでyumではなくapt-get使いましょう

```
$ sudo apt-get install -y tmux
```

## Guardのexecでコケる

```
/home/ubuntu/.rvm/gems/ruby-2.6.3/gems/guard-2.13.0/lib/guard/jobs/pry_wrapper.rb:131:in `_setup': undefined method `file=' for #<Pry::History:0x000055a6b08de940>
Did you mean?  filter (NoMethodError)
```

みたいなエラー。
よく分からなかったのでググったらQiita記事ヒット。
[Ruby on Rails チュートリアル 3章のguardがエラーで失敗する](https://qiita.com/daishinkawa/items/2cc02591361273354bd5)
こちら参考に、Guardのバージョンを最新に上げればOK

```diff:Gemfile
group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of web drivers to run system tests with browsers
  gem 'webdrivers'
  gem 'minitest',                 '5.10.3'
  gem 'minitest-reporters',       '1.1.14'
- gem 'guard',                    '2.13.0'
+ gem 'guard',                    '2.16.2'
  gem 'guard-minitest',           '2.4.4'
end
```

# ■4章

layout編集してjavascriptタグでコケた場合は3章参照

# ■5章

４章と同じく。
layout編集してjavascriptタグでコケた場合は3章参照

## 統合テストでコケる

```
NoMethodError:         NoMethodError: assert_template has been extracted to a gem. To continue using it,
                add `gem 'rails-controller-testing'` to your Gemfile.
```

assert_templateメソッドはGemから取り除かれたよ、使いたければ'rails-controller-testing'をGemfileに追加してくれとのこと。

```diff:Gemfile
+  gem 'rails-controller-testing'
```

# ■6章

## bcryptの追加

rails newした時からgemの追加のみ行っている場合、bcryptがコメントアウトで最初から記載されているはず。
コメントアウト外してbundle installするだけでOKです。

# ■7章

特筆事項無し

# ■8章

jQueryとbootstrapの入れ方が異なる。

こちらの記事を参考に。
[Rails 6 webpack throwing 'Uncaught ReferenceError: $ is not defined'](https://stackoverflow.com/questions/58677275/rails-6-webpack-throwing-uncaught-referenceerror-is-not-defined)

まずはyarnでjquery, bootstrap, popper.jsを入れる

```
$ yarn add jquery bootstrap popper.js
```

```diff:config/webpack/environment.js
const { environment } = require('@rails/webpacker')

+ const webpack = require('webpack')
+ environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
+   $: 'jquery/src/jquery',
+   jQuery: 'jquery/src/jquery',
+   jquery: 'jquery',
+   'window.jQuery': 'jquery',
+   Popper: ['popper.js', 'default']
+ }))

module.exports = environment

```

```diff:app/javascript/packs/application.js
...

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
+ import 'bootstrap';

...
```

これでログインのプルダウンが動く。

# ■9章

特筆事項なし

# ■10章

## 10.7やった後、統合テストがコケる

```
 FAIL["test_invalid_signup_information", UsersSignupTest, 0.87976424199951]
 test_invalid_signup_information#UsersSignupTest (0.88s)
        Expected at least 1 element matching "form[action="/signup"]", found 0..
        Expected 0 to be >= 1.
```


Rails6起因ではありませんが、マジメに1章から9章までの全演習をやっているとリスト10.7までやったところでテストがコケるようになります。
原因はformをpartial化した際、@userのルーティングによって新規登録時にsignup_pathじゃなく、これが適用されてしまうためです。

```
POST /users(.:format) users#create
```

formの飛び先をpartialに渡しましょう。

参考：[Railsチュートリアル第10章10.1.2でtestが通らなかった話](https://qiita.com/shiomarukun/items/12937507b39108336aef)

formの飛び先を指定するため、わかりやすくform_urlという名前にしました。

```diff:app/views/users/_form.html.erb
- <%= form_for(@user) do |f| %>
+ <%= form_for(@user, url: yield(:form_url)) do |f| %>
```

```diff:app/views/users/new.html.erb
+ <% provide(:form_url, signup_path) %>
```

```diff:app/views/users/edit.html.erb
+ <% provide(:form_url, user_path) %>
```

これでintegration testが再び通過するようになります。

## fakerのbundle installがコケる

バージョンが古いのが原因。調べたところ執筆時点で2.11が最新なので変更。

```diff:Gemfile
+ gem 'faker',          '2.11'
```

## will_pagenateが動かない

```
will_pagenate wrong number of arguments (given 0, expected 1)
```

引数1個必要なのに0個だよ、というエラー。
普通に開発している時はソースコードの方を疑うべきですが、Rails Tutorialの表記でソースコード自体が間違っていることは考えづらいです。

ということで、そろそろあたりが付けられるようになるかと思いますが、これもバージョンの関係です。
執筆時点でwill_paginateは3.3.0が最新なので変更。

```diff:Gemfile
+ gem 'will_paginate', '3.3.0'
```

# ■11章

特筆事項なし

# ■12章

特筆事項なし

# ■13章

## リスト13.18のテストがコケる

Rail6特有かどうか分かりませんが、リスト13.15のfixtureでユーザーを指定しないため、以下エラーが起きます。

```
ActiveRecord::NotNullViolation:         ActiveRecord::NotNullViolation: RuntimeError: NOT NULL constraint failed: microposts.user_id
```

```diff:test/fixtures/microposts.yml
orange:
  content: "I just ate an orange!"
  created_at: <%= 10.minutes.ago %>
+ user: one

tau_manifesto:
  content: "Check out the @tauday site by @mhartl: http://tauday.com"
  created_at: <%= 3.years.ago %>
+ user: one

cat_video:
  content: "Sad cats are sad: http://youtu.be/PKffm2uI4dk"
  created_at: <%= 2.hours.ago %>
+ user: one

most_recent:
  content: "Writing a short test"
  created_at: <%= Time.zone.now %>
+ user: one
```

## サンプルデータにマイクロポスト追加で非推奨エラーが大量に出る

```
/home/ubuntu/environment/sample_app/db/seeds.rb:30: Passing `word_count` with the 1st argument of `sentence` is deprecated. Use keyword argument like `sentence(word_count: ...)` instead.

To automatically update from positional arguments to keyword arguments,
install rubocop-faker and run:

rubocop \
  --require rubocop-faker \
  --only Faker/DeprecatedArguments \
  --auto-correct
```

word_count

```diff:db/seeds.rb
...

+ users = User.order(:created_at).take(6)
+ 50.times do
+   content = Faker::Lorem.sentence(word_count: 5)
+   users.each { |user| user.microposts.create!(content: content) }
+ end
```

そのすぐ先にあるfixtureも以下のように。

```yaml:test/fixtures/microposts.yml
...
  content: <%= Faker::Lorem.sentence(word_count: 5) %>
...
```

## 画像入れた後のテストがコケる

テストがうまく動かなくなるケースがあります（これもRails6に限らず、起きるケースがある模様）

```
ERROR["test_should_get_about", StaticPagesControllerTest, 0.012211428000227897]
 test_should_get_about#StaticPagesControllerTest (0.01s)
NameError:         NameError: uninitialized constant #<Class:0x00007f6628771790>::PictureUploader
        Did you mean?  Micropost::Preloader
            app/models/micropost.rb:4:in `<class:Micropost>'
            app/models/micropost.rb:1:in `<main>'

 FAIL["test_content_should_be_at_most_140_characters", MicropostTest, 0.7875548960000742]
 test_content_should_be_at_most_140_characters#MicropostTest (0.79s)
        Expected true to be nil or false
        test/models/micropost_test.rb:26:in `block in <class:MicropostTest>'

 FAIL["test_user_id_should_be_present", MicropostTest, 0.7924731410003005]
 test_user_id_should_be_present#MicropostTest (0.79s)
        Expected true to be nil or false
        test/models/micropost_test.rb:16:in `block in <class:MicropostTest>'

 FAIL["test_content_should_bepresent", MicropostTest, 0.7981856210008118]
 test_content_should_bepresent#MicropostTest (0.80s)
        Expected true to be nil or false
        test/models/micropost_test.rb:21:in `block in <class:MicropostTest>'
```

こちらを参考に解決します。
[Railsチュートリアル中にNameError: uninitialized constant Micropost::PictureUploaderが出た時の対処法](https://qiita.com/yokoyan/items/0f82fc3eede75cd6db55)

springを再起動すれば直ることがある模様です。

```
$ spring stop
$ spring server
```

※参考記事ではspring startとなっていますが、現バージョンではspring serverとなっている模様

## ImageMagickが入れられない

cloud9でUbuntuでやっている場合、yumじゃなくapt-getになります。
単純に置き換えるとImageMagickは無いというエラーになります。apt-getだと小文字のよう。

```
$ sudo apt-get -y install imagemagick
```

これでOKです。

# ■14章

## フォローのAjax化が動かない

開発者ツールのコンソールを見ると

```
uncaught referenceerror $ is not defined 
```

8章の手順に沿って対応すればOK