Rails 7.1 -> 8.0 へアップグレードした話

現在開発している『とあるApp』のRailsを7.1 -> 8.0へアップグレードした

その時のメモを残しておく

> ruby: 3.3.5
  rails: 7.1.5 -> 8.0.0

## Railsのアップグレードをして、とりあえず動かすまで

1. Gemfileの更新
    ```diff_ruby
    - gem 'rails', '~> 7.1.0'
    + gem 'rails', '~> 8.0.0'
    ```
    パッチバージョンのみ可変にしている
.
1. `$ bundle update rails`
    1. gem 'annotate'がrails8対応していなかったため、2.6.5に落ちてしまう
        ```
        Resolving dependencies...
        Using minitest 5.25.2 (was 5.25.1)
        Using rackup 2.2.1 (was 2.2.0)
        Using activesupport 8.0.0 (was 7.1.5)
        Using rdoc 6.8.1 (was 6.7.0)
        Using activemodel 8.0.0 (was 7.1.5)
        Using actionview 8.0.0 (was 7.1.5)
        Using activejob 8.0.0 (was 7.1.5)
        Using activerecord 8.0.0 (was 7.1.5)
        Using actionpack 8.0.0 (was 7.1.5)
        Using annotate 2.6.5 (was 3.2.0)     <--- here
        Using actioncable 8.0.0 (was 7.1.5)
        Using activestorage 8.0.0 (was 7.1.5)
        Using actionmailer 8.0.0 (was 7.1.5)
        Using actionmailbox 8.0.0 (was 7.1.5)
        Using railties 8.0.0 (was 7.1.5)
        Using actiontext 8.0.0 (was 7.1.5)
        Using rails 8.0.0 (was 7.1.5)
        Bundle updated!
        ```
        .
    1. gem 'annotate'をforkして annotate.gemspec を書き換える (暫定対応)
        ```diff_ruby
        - s.add_runtime_dependency(%q<activerecord>, ['>= 3.2', '< 8.0'])
        + s.add_runtime_dependency(%q<activerecord>, ['>= 3.2', '< 9.0'])
        ```
        .
    1. forkしたリポジトリを取り込む (本系で対応されたら元に戻そう)
        ```diff_ruby
        - gem 'annotate'
        + gem 'annotate', github: '~~~/annotate_models', branch: 'rails-8'
        ```
        .
    1. 再度 bundle update
        ```
        Resolving dependencies...
        Using uri 1.0.2 (was 1.0.1)
        Using annotate 3.2.0 (was 2.6.5) from https://github.com/~~~/annotate_models.git (at rails-8@1887c06)
        Bundler attempted to update rails but its version stayed the same
        Bundle updated!
        ```
        .
 
1. package.json関連
    1. updateされる差分を確認
    `$ npx -p npm-check-updates  -c "ncu"`
    .
    1. package.jsonの更新
    `$ npx -p npm-check-updates  -c "ncu -u"`
        ```bash
        Upgrading /webapp/package.json
        [====================] 16/16 100%
        
         〜〜〜〜〜〜〜〜
         
         @hotwired/stimulus                          ^3.2.1  →   ^3.2.2
         @hotwired/turbo-rails                       ^7.3.0  →  ^8.0.12

         〜〜〜〜〜〜
         
         echarts                                     ^5.4.3  →   ^5.5.1
         esbuild                                   ^0.17.17  →  ^0.24.0
         sass                                       ^1.62.0  →  ^1.81.0
        
        Run yarn install to install new versions.
        ```
        turbo-railsが8系に。Hotwireの新機能を弄り倒すのが楽しみである。
        .
    1. install
    `$ bin/rails javascript:install`
    .

    1. 使っていたechartsのtheme読み込みで怒られたので対応する
        ```bash
        [watch] build started (change: "package.json")
        ✘ [ERROR] Could not resolve "echarts/theme/dark"
        
            app/javascript/application.js:16:7:
              16 │ import 'echarts/theme/dark';
                 ╵        ~~~~~~~~~~~~~~~~~~~~
        
          Import from "echarts/theme/dark.js" to get the file "node_modules/echarts/theme/dark.js":
        
            app/javascript/application.js:16:26:
              16 │ import 'echarts/theme/dark';
                 │                           ^
                 ╵                           .js
        ```
        ```diff_javascript
        - import 'echarts/theme/dark';
        + import 'echarts/theme/dark.js';
        ```
        .
1. `$ bin/rails app:update`
    1. configファイルやら何やら、いろいろ更新される
    1. 基本は上書きしていくが、差分を見て必要な設定項目を戻していく
    .
1. `config/application.rb`を書き換える
    ```diff_ruby
    -    config.load_defaults 7.1
    +    config.load_defaults 8.0
    ```
    .
1. rspec実行したところ、Undefined method errorが起きる
    ```
    Failure/Error: validates :status, inclusion: { in: statuses.keys }
    
    NameError:
      undefined local variable or method `statuses' for class Term
    ```
    1. 原因はRails7.2で非推奨になったenumのキーワード引数を用いた記法が、Rails8で消失したため
        ```
        DEPRECATION WARNING: Defining enums with keyword arguments is deprecated and will be removed
        in Rails 7.3.
        ```
        .
    1. 適した位置引数表記に書き換える。他のmodelにも横展開
    キーワード引数表記では_で始まっていたオプション名も、位置引数表記では_が不要になるので併せて対応。
    see: https://api.rubyonrails.org/v7.1.3/classes/ActiveRecord/Enum.html
        ```diff_ruby
        -  enum status: { draft: 0, published: 1, expired: 2 }, _prefix: true
        +  enum :status, { draft: 0, published: 1, expired: 2 }, prefix: true
        ```
        .
1. 再びrspec実行したところ、次なるエラーに遭遇
    ```
    Failure/Error: let(:user) { create(:user) }
    
    RuntimeError:
      Could not find a valid mapping for #<User id: 〜〜〜〜
    ```
    1. DeviseのTestHelperでroutesの解決に問題がある模様。
        see: https://github.com/heartcombo/devise/issues/5705

        ```
        # /usr/local/bundle/gems/devise-4.9.4/lib/devise/mapping.rb:46:in `find_scope!'
        # /usr/local/bundle/gems/devise-4.9.4/lib/devise/mailers/helpers.rb:23:in `initialize_from_record'
        # /usr/local/bundle/gems/devise-4.9.4/lib/devise/mailers/helpers.rb:18:in `devise_mail'
        # /usr/local/bundle/gems/devise-4.9.4/app/mailers/devise/mailer.rb:9:in `confirmation_instructions'
        ```
        具体的には、Devise::Mailer内でのpath解決がうまくいっていないようなので、rails_helper.rb へ以下のコードを追記する
        ```diff_ruby
        + ActiveSupport.on_load(:action_mailer) do
        +  Rails.application.reload_routes_unless_loaded
        + end
        ```
        .
1. ALL GREEN! :raised_hands:
    ```
    Finished in 37.3 seconds (files took 3.53 seconds to load)
    ~~~ examples, 0 failures
    ```
    .
1. rails server、無事に起動！
    ```bash
    => Booting Puma
    => Rails 8.0.0 application starting in development 
    => Run `bin/rails server --help` for more startup options
    Puma starting in single mode...
    * Puma version: 6.4.3 (ruby 3.3.5-p100) ("The Eagle of Durango")
    *  Min threads: 5
    *  Max threads: 5
    *  Environment: development
    *          PID: 25
    * Listening on http://0.0.0.0:3000
    ```
## Next Action

まだRailsをアップグレードしただけにすぎないので、新たに追加された様々な機能への対応を進めていきたい。

- StrongParameter周りをparams.expectに置き換える
- Hotwire(Turbo8)で正式版となったmorph周り活用したい
- Solid関連を試したい
- .etc

また、その後の進捗が出次第、記事に残していこうと思う。

---

※ この記事は、AI文章校正ツール「ちゅらいと」で校正されています。