Repository: rubyforgood/human-essentials
Pull request #5046: Upgrade to Rails 8
Author: login: coalest
Created: 2025-02-27T18:07:53Z | Merged: 2025-03-18T22:45:11Z

Doesn't resolve any issue.

### Description
- Upgraded `rails` from 7.2.2 to 8.0.1
- Upgraded `filterrific` to be compatible with Rails 8
- Upgraded `paper_trail` to be compatible with Rails 8
- Added a workaround that fixes a Devise issue causing tests to fail with rails 8
- Migrate from `annotate` to `annotaterb` because `annotate` doesn't support Rails 8 and it is abandoned

### Type of change
* Dependency update (shouldn't affect users in theory)

### How Has This Been Tested?
I did some light testing locally, and all the tests are passing. But we probably want to test this a little more thoroughly and in staging too.



Diff:
diff --git a/.annotaterb.yml b/.annotaterb.yml
new file mode 100644
index 0000000000..d29b5ceca4
--- /dev/null
+++ b/.annotaterb.yml
@@ -0,0 +1,58 @@
+---
+:position: before
+:position_in_additional_file_patterns: before
+:position_in_class: before
+:position_in_factory: before
+:position_in_fixture: before
+:position_in_routes: before
+:position_in_serializer: before
+:position_in_test: before
+:classified_sort: true
+:exclude_controllers: true
+:exclude_factories: false
+:exclude_fixtures: false
+:exclude_helpers: true
+:exclude_scaffolds: true
+:exclude_serializers: false
+:exclude_sti_subclasses: false
+:exclude_tests: false
+:force: false
+:format_markdown: false
+:format_rdoc: false
+:format_yard: false
+:frozen: false
+:ignore_model_sub_dir: false
+:ignore_unknown_models: false
+:include_version: false
+:show_check_constraints: false
+:show_complete_foreign_keys: false
+:show_foreign_keys: false
+:show_indexes: false
+:simple_indexes: false
+:sort: false
+:timestamp: false
+:trace: false
+:with_comment: true
+:with_column_comments: true
+:with_table_comments: true
+:active_admin: false
+:command:
+:debug: false
+:hide_default_column_types: ""
+:hide_limit_column_types: ""
+:ignore_columns:
+:ignore_routes:
+:models: true
+:routes: false
+:skip_on_db_migrate: false
+:target_action: :do_annotations
+:wrapper:
+:wrapper_close:
+:wrapper_open:
+:classes_default_to_s: []
+:additional_file_patterns: []
+:model_dir:
+  - app/models
+:require: []
+:root_dir:
+  - ""
diff --git a/Gemfile b/Gemfile
index 89ef7cd21f..1110f5c6f6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -14,7 +14,7 @@ gem "pg", "~> 1.5.9"
 # Web server.
 gem "puma"
 # Rails web framework.
-gem "rails", "7.2.2"
+gem "rails", "~> 8.0.1"
 
 ###### MODELS / DATABASE #######
 
@@ -162,7 +162,7 @@ end
 
 group :development do
   # Show database columns and indexes inside files.
-  gem "annotate"
+  gem "annotaterb"
   # Used as a dependency for better_errors.
   gem "binding_of_caller"
   # Show a better error page on development, including a REPL.
diff --git a/Gemfile.lock b/Gemfile.lock
index 159ed3895d..accc1de304 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -2,66 +2,65 @@ GEM
   remote: https://rubygems.org/
   specs:
     Ascii85 (1.1.1)
-    actioncable (7.2.2)
-      actionpack (= 7.2.2)
-      activesupport (= 7.2.2)
+    actioncable (8.0.1)
+      actionpack (= 8.0.1)
+      activesupport (= 8.0.1)
       nio4r (~> 2.0)
       websocket-driver (>= 0.6.1)
       zeitwerk (~> 2.6)
-    actionmailbox (7.2.2)
-      actionpack (= 7.2.2)
-      activejob (= 7.2.2)
-      activerecord (= 7.2.2)
-      activestorage (= 7.2.2)
-      activesupport (= 7.2.2)
+    actionmailbox (8.0.1)
+      actionpack (= 8.0.1)
+      activejob (= 8.0.1)
+      activerecord (= 8.0.1)
+      activestorage (= 8.0.1)
+      activesupport (= 8.0.1)
       mail (>= 2.8.0)
-    actionmailer (7.2.2)
-      actionpack (= 7.2.2)
-      actionview (= 7.2.2)
-      activejob (= 7.2.2)
-      activesupport (= 7.2.2)
+    actionmailer (8.0.1)
+      actionpack (= 8.0.1)
+      actionview (= 8.0.1)
+      activejob (= 8.0.1)
+      activesupport (= 8.0.1)
       mail (>= 2.8.0)
       rails-dom-testing (~> 2.2)
-    actionpack (7.2.2)
-      actionview (= 7.2.2)
-      activesupport (= 7.2.2)
+    actionpack (8.0.1)
+      actionview (= 8.0.1)
+      activesupport (= 8.0.1)
       nokogiri (>= 1.8.5)
-      racc
-      rack (>= 2.2.4, < 3.2)
+      rack (>= 2.2.4)
       rack-session (>= 1.0.1)
       rack-test (>= 0.6.3)
       rails-dom-testing (~> 2.2)
       rails-html-sanitizer (~> 1.6)
       useragent (~> 0.16)
-    actiontext (7.2.2)
-      actionpack (= 7.2.2)
-      activerecord (= 7.2.2)
-      activestorage (= 7.2.2)
-      activesupport (= 7.2.2)
+    actiontext (8.0.1)
+      actionpack (= 8.0.1)
+      activerecord (= 8.0.1)
+      activestorage (= 8.0.1)
+      activesupport (= 8.0.1)
       globalid (>= 0.6.0)
       nokogiri (>= 1.8.5)
-    actionview (7.2.2)
-      activesupport (= 7.2.2)
+    actionview (8.0.1)
+      activesupport (= 8.0.1)
       builder (~> 3.1)
       erubi (~> 1.11)
       rails-dom-testing (~> 2.2)
       rails-html-sanitizer (~> 1.6)
-    activejob (7.2.2)
-      activesupport (= 7.2.2)
+    activejob (8.0.1)
+      activesupport (= 8.0.1)
       globalid (>= 0.3.6)
-    activemodel (7.2.2)
-      activesupport (= 7.2.2)
-    activerecord (7.2.2)
-      activemodel (= 7.2.2)
-      activesupport (= 7.2.2)
+    activemodel (8.0.1)
+      activesupport (= 8.0.1)
+    activerecord (8.0.1)
+      activemodel (= 8.0.1)
+      activesupport (= 8.0.1)
       timeout (>= 0.4.0)
-    activestorage (7.2.2)
-      actionpack (= 7.2.2)
-      activejob (= 7.2.2)
-      activerecord (= 7.2.2)
-      activesupport (= 7.2.2)
+    activestorage (8.0.1)
+      actionpack (= 8.0.1)
+      activejob (= 8.0.1)
+      activerecord (= 8.0.1)
+      activesupport (= 8.0.1)
       marcel (~> 1.0)
-    activesupport (7.2.2)
+    activesupport (8.0.1)
       base64
       benchmark (>= 0.3)
       bigdecimal
@@ -73,12 +72,11 @@ GEM
       minitest (>= 5.1)
       securerandom (>= 0.3)
       tzinfo (~> 2.0, >= 2.0.5)
+      uri (>= 0.13.1)
     addressable (2.8.7)
       public_suffix (>= 2.0.2, < 7.0)
     afm (0.2.2)
-    annotate (3.2.0)
-      activerecord (>= 3.2, < 8.0)
-      rake (>= 10.4, < 14.0)
+    annotaterb (4.14.0)
     ast (2.4.2)
     autoprefixer-rails (10.4.13.0)
       execjs (~> 2)
@@ -197,8 +195,8 @@ GEM
       actionmailer (>= 5.0)
       devise (>= 4.6)
     diff-lcs (1.5.1)
-    discard (1.3.0)
-      activerecord (>= 4.2, < 8)
+    discard (1.4.0)
+      activerecord (>= 4.2, < 9.0)
     docile (1.4.0)
     dotenv (3.1.7)
     dotenv-rails (3.1.7)
@@ -274,7 +272,7 @@ GEM
     ffi (1.17.0-arm64-darwin)
     ffi (1.17.0-x86_64-darwin)
     ffi (1.17.0-x86_64-linux-gnu)
-    filterrific (5.2.5)
+    filterrific (5.2.7)
     flipper (1.3.2)
       concurrent-ruby (< 2)
     flipper-active_record (1.3.2)
@@ -323,7 +321,8 @@ GEM
       activesupport (>= 6.0.0)
       railties (>= 6.0.0)
     io-console (0.8.0)
-    irb (1.14.3)
+    irb (1.15.1)
+      pp (>= 0.6.0)
       rdoc (>= 4.0.0)
       reline (>= 0.4.2)
     jbuilder (2.13.0)
@@ -402,25 +401,25 @@ GEM
     nenv (0.3.0)
     net-http-persistent (4.0.2)
       connection_pool (~> 2.2)
-    net-imap (0.5.0)
+    net-imap (0.5.6)
       date
       net-protocol
     net-pop (0.1.2)
       net-protocol
     net-protocol (0.2.2)
       timeout
-    net-smtp (0.5.0)
+    net-smtp (0.5.1)
       net-protocol
     newrelic_rpm (9.16.0)
     nio4r (2.7.4)
-    nokogiri (1.18.1)
+    nokogiri (1.18.3)
       mini_portile2 (~> 2.8.2)
       racc (~> 1.4)
-    nokogiri (1.18.1-arm64-darwin)
+    nokogiri (1.18.3-arm64-darwin)
       racc (~> 1.4)
-    nokogiri (1.18.1-x86_64-darwin)
+    nokogiri (1.18.3-x86_64-darwin)
       racc (~> 1.4)
-    nokogiri (1.18.1-x86_64-linux-gnu)
+    nokogiri (1.18.3-x86_64-linux-gnu)
       racc (~> 1.4)
     notiffany (0.1.3)
       nenv (~> 0.1)
@@ -452,7 +451,7 @@ GEM
       rspec (>= 2.14)
     orm_adapter (0.5.0)
     ostruct (0.6.1)
-    paper_trail (15.2.0)
+    paper_trail (16.0.0)
       activerecord (>= 6.1)
       request_store (~> 1.4)
     parallel (1.26.3)
@@ -468,6 +467,8 @@ GEM
       ttfunk
     pg (1.5.9)
     popper_js (2.11.8)
+    pp (0.6.2)
+      prettyprint
     prawn (2.5.0)
       matrix (~> 0.4)
       pdf-core (~> 0.10.0)
@@ -479,6 +480,7 @@ GEM
       prawn-table
     prawn-table (0.2.2)
       prawn (>= 1.3.0, < 3.0.0)
+    prettyprint (0.2.0)
     pry (0.14.2)
       coderay (~> 1.1)
       method_source (~> 1.0)
@@ -495,39 +497,40 @@ GEM
     pry-stack_explorer (0.6.1)
       binding_of_caller (~> 1.0)
       pry (~> 0.13)
-    psych (5.2.2)
+    psych (5.2.3)
       date
       stringio
     public_suffix (6.0.1)
     puma (6.6.0)
       nio4r (~> 2.0)
     racc (1.8.1)
-    rack (3.1.8)
+    rack (3.1.10)
     rack-mini-profiler (3.3.1)
       rack (>= 1.2.0)
     rack-protection (4.0.0)
       base64 (>= 0.1.0)
       rack (>= 3.0.0, < 4)
-    rack-session (2.0.0)
+    rack-session (2.1.0)
+      base64 (>= 0.1.0)
       rack (>= 3.0.0)
     rack-test (2.2.0)
       rack (>= 1.3)
     rackup (2.2.1)
       rack (>= 3)
-    rails (7.2.2)
-      actioncable (= 7.2.2)
-      actionmailbox (= 7.2.2)
-      actionmailer (= 7.2.2)
-      actionpack (= 7.2.2)
-      actiontext (= 7.2.2)
-      actionview (= 7.2.2)
-      activejob (= 7.2.2)
-      activemodel (= 7.2.2)
-      activerecord (= 7.2.2)
-      activestorage (= 7.2.2)
-      activesupport (= 7.2.2)
+    rails (8.0.1)
+      actioncable (= 8.0.1)
+      actionmailbox (= 8.0.1)
+      actionmailer (= 8.0.1)
+      actionpack (= 8.0.1)
+      actiontext (= 8.0.1)
+      actionview (= 8.0.1)
+      activejob (= 8.0.1)
+      activemodel (= 8.0.1)
+      activerecord (= 8.0.1)
+      activestorage (= 8.0.1)
+      activesupport (= 8.0.1)
       bundler (>= 1.15.0)
-      railties (= 7.2.2)
+      railties (= 8.0.1)
     rails-controller-testing (1.0.5)
       actionpack (>= 5.0.1.rc1)
       actionview (>= 5.0.1.rc1)
@@ -544,9 +547,9 @@ GEM
     rails-html-sanitizer (1.6.2)
       loofah (~> 2.21)
       nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
-    railties (7.2.2)
-      actionpack (= 7.2.2)
-      activesupport (= 7.2.2)
+    railties (8.0.1)
+      actionpack (= 8.0.1)
+      activesupport (= 8.0.1)
       irb (~> 1.13)
       rackup (>= 1.0.0)
       rake (>= 12.2)
@@ -557,7 +560,7 @@ GEM
     rb-fsevent (0.11.2)
     rb-inotify (0.10.1)
       ffi (~> 1.0)
-    rdoc (6.10.0)
+    rdoc (6.12.0)
       psych (>= 4.0.0)
     recaptcha (5.19.0)
     regexp_parser (2.10.0)
@@ -702,6 +705,7 @@ GEM
       unicode-emoji (~> 4.0, >= 4.0.4)
     unicode-emoji (4.0.4)
     uniform_notifier (1.16.0)
+    uri (1.0.3)
     useragent (0.16.11)
     version_gem (1.1.4)
     warden (1.2.9)
@@ -716,13 +720,14 @@ GEM
       crack (>= 0.3.2)
       hashdiff (>= 0.4.0, < 2.0.0)
     webrick (1.9.1)
-    websocket-driver (0.7.6)
+    websocket-driver (0.7.7)
+      base64
       websocket-extensions (>= 0.1.0)
     websocket-extensions (0.1.5)
     xpath (3.2.0)
       nokogiri (~> 1.8)
     yard (0.9.34)
-    zeitwerk (2.7.1)
+    zeitwerk (2.7.2)
 
 PLATFORMS
   arm64-darwin-20
@@ -737,7 +742,7 @@ PLATFORMS
   x86_64-linux
 
 DEPENDENCIES
-  annotate
+  annotaterb
   awesome_print
   aws-sdk-s3
   azure-storage-blob
@@ -799,7 +804,7 @@ DEPENDENCIES
   pry-remote
   puma
   rack-mini-profiler
-  rails (= 7.2.2)
+  rails (~> 8.0.1)
   rails-controller-testing
   rails-erd
   recaptcha
diff --git a/db/schema.rb b/db/schema.rb
index 1cac48c00a..74fcca3d68 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,9 +10,9 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.2].define(version: 2025_03_02_154355) do
+ActiveRecord::Schema[8.0].define(version: 2025_03_02_154355) do
   # These are extensions that must be enabled in order to support this database
-  enable_extension "plpgsql"
+  enable_extension "pg_catalog.plpgsql"
 
   # Custom types defined in this database.
   # Note that some types may not work with other database engines. Be careful if changing database.
diff --git a/lib/tasks/annotate_rb.rake b/lib/tasks/annotate_rb.rake
new file mode 100644
index 0000000000..1ad0ec39e7
--- /dev/null
+++ b/lib/tasks/annotate_rb.rake
@@ -0,0 +1,8 @@
+# This rake task was added by annotate_rb gem.
+
+# Can set `ANNOTATERB_SKIP_ON_DB_TASKS` to be anything to skip this
+if Rails.env.development? && ENV["ANNOTATERB_SKIP_ON_DB_TASKS"].nil?
+  require "annotate_rb"
+
+  AnnotateRb::Core.load_rake_tasks
+end
diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake
deleted file mode 100644
index e5f0b6a7a0..0000000000
--- a/lib/tasks/auto_annotate_models.rake
+++ /dev/null
@@ -1,57 +0,0 @@
-# NOTE: only doing this in development as some production environments (Heroku)
-# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
-# NOTE: to have a dev-mode tool do its thing in production.
-if Rails.env.development?
-  require 'annotate'
-  task :set_annotation_options do
-    # You can override any of these by setting an environment variable of the
-    # same name.
-    Annotate.set_defaults(
-      'additional_file_patterns'    => [],
-      'routes'                      => 'false',
-      'models'                      => 'true',
-      'position_in_routes'          => 'before',
-      'position_in_class'           => 'before',
-      'position_in_test'            => 'before',
-      'position_in_fixture'         => 'before',
-      'position_in_factory'         => 'before',
-      'position_in_serializer'      => 'before',
-      'show_foreign_keys'           => 'false',
-      'show_complete_foreign_keys'  => 'false',
-      'show_indexes'                => 'false',
-      'simple_indexes'              => 'false',
-      'model_dir'                   => 'app/models',
-      'root_dir'                    => '',
-      'include_version'             => 'false',
-      'require'                     => '',
-      'exclude_tests'               => 'false',
-      'exclude_fixtures'            => 'false',
-      'exclude_factories'           => 'false',
-      'exclude_serializers'         => 'false',
-      'exclude_scaffolds'           => 'true',
-      'exclude_controllers'         => 'true',
-      'exclude_helpers'             => 'true',
-      'exclude_sti_subclasses'      => 'false',
-      'ignore_model_sub_dir'        => 'false',
-      'ignore_columns'              => nil,
-      'ignore_routes'               => nil,
-      'ignore_unknown_models'       => 'false',
-      'hide_limit_column_types'     => 'integer,bigint,boolean',
-      'hide_default_column_types'   => 'json,jsonb,hstore',
-      'skip_on_db_migrate'          => 'false',
-      'format_bare'                 => 'true',
-      'format_rdoc'                 => 'false',
-      'format_markdown'             => 'false',
-      'sort'                        => 'false',
-      'force'                       => 'false',
-      'frozen'                      => 'false',
-      'classified_sort'             => 'true',
-      'trace'                       => 'false',
-      'wrapper_open'                => nil,
-      'wrapper_close'               => nil,
-      'with_comment'                => 'true'
-    )
-  end
-
-  Annotate.load_tasks
-end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index 1af8c6a50b..9e721b8920 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -240,3 +240,10 @@ def await_select2(select2, container = nil, &block)
 
   find("#{container} select option[data-select2-id=\"#{current_id.to_i + 1}\"]", wait: 10)
 end
+
+# TODO: Remove the following workaround once the following commit is in
+# in a new release of Devise:
+# https://github.com/heartcombo/devise/commit/591b03a6c010f47976f7033370a8165c5324a82c
+ActiveSupport.on_load(:action_mailer) do
+  Rails.application.reload_routes_unless_loaded
+end


Reviews:
user: login: dorner
body: Should be safe to update filterrific now.
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-05T00:05:19Z
user: login: coalest
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-05T13:22:43Z
user: login: dorner
body: No concerns here - thank you!

@cielf maybe do a bit more desultory random testing before the release this week? Not too worried though.
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-18T22:45:02Z

Review comments:
diff_hunk: @@ -56,7 +56,9 @@ gem "importmap-rails", "~> 2.1"
 ##### VIEWS/CONTROLLERS #####
 
 # Adds filter support to models and views.
-gem "filterrific"
+# TODO: Stop pinning filterrific to git once there is a release with the following commit:
+# https://github.com/jhund/filterrific/commit/bb1ab756575674a19e1632c9eeb5eda859a8cb8a
+gem "filterrific", git: "https://github.com/jhund/filterrific", branch: "master"
path: Gemfile
user: login: dorner
body: @coalest looks like this has been released!
created_at: 2025-03-05T00:03:53Z
author_association: COLLABORATOR
diff_hunk: @@ -56,7 +56,9 @@ gem "importmap-rails", "~> 2.1"
 ##### VIEWS/CONTROLLERS #####
 
 # Adds filter support to models and views.
-gem "filterrific"
+# TODO: Stop pinning filterrific to git once there is a release with the following commit:
+# https://github.com/jhund/filterrific/commit/bb1ab756575674a19e1632c9eeb5eda859a8cb8a
+gem "filterrific", git: "https://github.com/jhund/filterrific", branch: "master"
path: Gemfile
user: login: coalest
body: Great! I switched it back and upgraded to the new version.
created_at: 2025-03-05T13:22:43Z
author_association: COLLABORATOR

PR comments:
user: login: cielf
created_at: 2025-02-28T01:32:38Z
body: I think we discussed this in the planning meeting a few weeks back and were deliberately going to wait for a while before going forward with Rails 8.             @dorner  - does that match your recollection?
author_association: COLLABORATOR
user: login: dorner
created_at: 2025-03-05T00:02:46Z
body: I think that was for Ruby 3.3 / 3.4. Rails 8 should be safe to update. I'll take a look.
author_association: COLLABORATOR
user: login: cielf
created_at: 2025-03-05T12:48:01Z
body: @dorner  I don't know enough about Rails 8 to intelligently comment -- but given the potentially large number of first time contributors from Scale, and that this feels like a "we should exercise most things" kind of change,  I suggest we postpone merging it until next week.   
author_association: COLLABORATOR
user: login: coalest
created_at: 2025-03-05T13:25:39Z
body: @dorner The annotate gem wasn't working with Rails 8, and upon investigation it has been [abandoned](https://github.com/ctran/annotate_models/issues/1039). I migrated to the recommended replacement [annotaterb](https://github.com/drwl/annotaterb). The main difference being it uses a yaml file for configuration, hence the changes seen in this PR
author_association: COLLABORATOR
user: login: github-actions[bot]
created_at: 2025-03-23T14:31:50Z
body: @coalest: Your PR `Upgrade to Rails 8` is part of today's Human Essentials production release: [2025.03.23](https://github.com/rubyforgood/human-essentials/releases/tag/2025.03.23). 
Thank you very much for your contribution!
author_association: CONTRIBUTOR