Skip to content

chore(deps): partial dependency upgrade for rails 8.x compatibility - #8489

Merged
adi-herwana-nus merged 2 commits into
masterfrom
adi/rails-8-upgrade-dependencies-1
Jul 21, 2026
Merged

chore(deps): partial dependency upgrade for rails 8.x compatibility#8489
adi-herwana-nus merged 2 commits into
masterfrom
adi/rails-8-upgrade-dependencies-1

Conversation

@adi-herwana-nus

@adi-herwana-nus adi-herwana-nus commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Isolated, low-risk dependency PR that unblocks the upcoming Rails 7.2 → 8.0 → 8.1
migration by moving ActiveRecord-coupled gems onto Rails-8-capable revisions (and dropping
one dead dependency). Every change still supports Rails 7.2, so this ships and runs on
the current production stack unchanged — it can be merged and deployed before any Rails
bump to de-risk the migration.

No application code changes; Gemfile / Gemfile.lock only.

Gem Before After Rails range after
active_record_upsert git jesjos ref c3e07ae (v0.11.2, caps AR < 8.0) git jesjos ref cb6f2a2 (v0.13.0, AR < 8.2) 5.2 → 7.2 → 8.0 → 8.1
calculated_attributes git Coursemology fork 3d9fe0c (v1.0.1, caps AR < 8) git aha-app ref ecaf6c9 (v1.1.1) 6.0 → 7.2 → 8.0
unread RubyGems ~> 0.14.0 (AR >= 6.1) git ledermann ref 9114324 7.2 → 8.0 → 8.1
kaminari RubyGems gem 'kaminari' (1.2.2) removed — unused n/a

Motivation

These gems monkey-patch ActiveRecord internals, and both were pinned to revisions that
hard-cap ActiveRecord below 8, which would block bundle install on Rails 8:

  • active_record_upsert @ c3e07ae → gemspec activerecord '< 8.0'.
  • calculated_attributes (Coursemology fork) @ 3d9fe0c → gemspec activerecord '>= 6.0.0', '< 8'.

Upstream for both has since added Rails 8 support, so we can move onto upstream revisions
and (for calculated_attributes) retire the Coursemology fork entirely.


Change 1 — active_record_upsert: pin upstream commit with Rails 8.1 support

- gem 'active_record_upsert', git: 'https://github.com/jesjos/active_record_upsert', ref: 'c3e07ae'
+ # v0.13.0 — adds Rails 8.1 support (PR #153); not yet published to RubyGems, so pin the commit.
+ # gemspec: activerecord '>= 5.2', '< 8.2'; retains Gemfile.rails-7-2 → still runs on current prod.
+ gem 'active_record_upsert', git: 'https://github.com/jesjos/active_record_upsert', ref: 'cb6f2a2'

Why pin a commit instead of a released version: the latest RubyGems release,
v0.12.0 (2025-07-24), caps activerecord < 8.1 and ships no Gemfile.rails-8-1 — it
does not support Rails 8.1. 8.1 support landed after the release, in commit
4698d58 "chore: Add support for Rails 8.1"
(PR #153). We pin the
cb6f2a2 "v0.13.0"
version-bump commit, which contains that support (activerecord '>= 5.2', '< 8.2',
Gemfile.rails-7-2 + Gemfile.rails-8-0 + Gemfile.rails-8-1) and reports as a clean
0.13.0. This avoids repinning twice (now for 8.0, again for 8.1); when v0.13.0 is
published to RubyGems we can swap the git pin for gem 'active_record_upsert', '~> 0.13'.

Upstream CI coverage for this line tests ActiveRecord 5.2, 6.0, 6.1, 7.0, 7.1, 7.2,
8.0, 8.1
.


Change 2 — calculated_attributes: retire Coursemology fork, move to upstream aha-app

- gem 'calculated_attributes', git: 'https://github.com/Coursemology/calculated_attributes.git'
+ # Retire Coursemology fork; upstream now maintains 7.2 + 8.0 support.
+ # ecaf6c9 = v1.1.1 (supports Rails 7.0/7.1/7.2/8.0). 8.1 (upstream master/v1.2.0) comes
+ # in the Rails 8.1 upgrade PR — see note below.
+ gem 'calculated_attributes', git: 'https://github.com/aha-app/calculated_attributes.git', ref: 'ecaf6c9'

Why the fork existed: upstream aha-app/calculated_attributes never published newer
than v0.5.0 (2020) to RubyGems, so it was always consumed from git. Our fork branched
before upstream had any Rails 7.2 support and carries a custom
rails_7_2_patches.rb (commit 3d9fe0c)
plus the activerecord < 8 cap.

Why the fork is no longer needed: upstream has since implemented equivalent Rails 7.2
support and added 8.0/8.1.

No single upstream ref supports both 7.2 and 8.1. This PR (running on prod Rails 7.2)
pins ecaf6c9 (v1.1.1). The follow-up Rails 8.1 upgrade PR must bump this to
upstream master (v1.2.0), which can only happen once prod is off Rails 7.2

On the "7.2 patch was a backport from upstream" question — verified, with a correction

I checked this because it was assumed the custom rails_7_2_patches.rb was a simple
backport of upstream's. The evidence says otherwise, and it's worth recording:

  • Chronology is reversed. Our patch 3d9fe0c is dated 2024-09-18. Upstream's
    earliest 7.2 support (c2fc8b3 "PFT-253: rails 7.2 compatibility")
    is dated 2025-03-18 — ~6 months later. At the time ours was written, upstream had
    only rails_7_patches.rb and no 7.2 handling, so ours cannot be a backport from
    aha-app
    .
  • What ours actually is: the define_attribute_methods override is adapted from
    vanilla Rails 7.2's own method (the file even carries a
    # https://github.com/rails/rails/.../attribute_methods.rb source comment) with the
    calculated-column filter re-applied — i.e. a backport/adaptation of Rails' method, not
    of an aha-app patch.
  • Equivalence to what we're adopting: comparing our 3d9fe0c file against upstream's
    ecaf6c9 rails_7_2_patches.rb (identical to af9002c's — the PR-course pages #25 merge didn't touch it):
    • Associations::JoinDependency#instantiate override — byte-identical.
    • AttributeMethods::ClassMethods#define_attribute_methods — same intent (skip defining
      accessors for calculated columns); upstream's is a leaner override, ours copies more
      of the Rails 7.2 method body (the abstract_class? / load_schema /
      generate_alias_attributes wrapping). Functionally equivalent for our usage.

Files to compare (the "git diff" proof):

Exact diff (ours → upstream ecaf6c9)
   module AttributeMethods
     module ClassMethods
       def define_attribute_methods
-        # https://github.com/rails/rails/blob/main/activerecord/lib/active_record/attribute_methods.rb
         ...
-          unless abstract_class?
-            load_schema
-            columns_to_define =
-              if defined?(calculated) && calculated.instance_variable_get('@calculations')
-                calculated_keys = calculated.instance_variable_get('@calculations').keys
-                attribute_names.reject { |c| calculated_keys.include? c.intern }
-              else
-                attribute_names
-              end
-            super(columns_to_define)
-            alias_attribute :id_value, :id if _has_attribute?("id")
-          end
+          columns_to_define =
+            if defined?(calculated) && calculated.instance_variable_get('@calculations')
+              calculated_keys = calculated.instance_variable_get('@calculations').keys
+              attribute_names.reject { |c| calculated_keys.include? c.intern }
+            else
+              attribute_names
+            end
+          super(columns_to_define)
         ...
   # JoinDependency#instantiate override: identical, no change

Takeaway: dropping our fork loses nothing — upstream's ecaf6c9 implements the same
two overrides (one identical, one equivalent-but-leaner) and is actively maintained.


Change 3 — unread: pin upstream commit with Rails 8.1 support

- gem 'unread', '~> 0.14.0'
+ # 0.14.0 (Oct 2024) is the last RubyGems release; Rails 8.0/8.1 support was added on master
+ # afterwards but not yet published. Pin the commit. gemspec: activerecord '>= 7.2', ruby '>= 3.2'.
+ gem 'unread', git: 'https://github.com/ledermann/unread.git', ref: '9114324'

Why pin a commit: the last RubyGems release is v0.14.0 (2024-10-05); Rails 8.0/8.1
support was added on master afterwards (2cdb630,
PR #136, 2026-03) but has not been
published. We pin master HEAD 9114324,
whose Appraisals test rails-7.2, rails-8.0, and rails-8.1 and whose gemspec is
activerecord '>= 7.2', required_ruby_version '>= 3.2' — compatible with current prod
(Ruby 3.3.5 / Rails 7.2) and the full target range.

Behaviorally identical to what we run today: git diff v0.14.0..9114324 -- lib is
empty — the only changes since 0.14.0 are CI matrix, Appraisals, gemfiles, and the
gemspec version bumps. No runtime code change. Swap the git pin for gem 'unread', '~> 0.15'
(or whatever the next release is) once it's published to RubyGems.

Usage (acts_as_readable / acts_as_reader): User (reader); read/unread tracking on
UserNotification, GenericAnnouncement, Course::Announcement, Course::Forum::Topic,
Course::Discussion::Topic, and Course::Discussion::Post.


Change 4 — kaminari: remove (dead dependency)

- # Paginator for Rails
- gem 'kaminari'

kaminari is declared in the Gemfile but not used anywhere in the app:

  • No .page / .per / Kaminari / paginate_array / paginate calls in app/, lib/,
    config/, or spec/ (exhaustive grep across .rb / .slim / .erb / .haml /
    .jbuilder). The only matches are the unrelated constant SUBMISSIONS_PER_PAGE and a
    kaminari.* ignore rule in config/i18n-tasks.yml.
  • No config/initializers/kaminari.rb and no generated app/views/kaminari/ templates.
  • In Gemfile.lock, kaminari (1.2.2) is a top-level entry only — nothing else depends on it.

Pagination is instead done by hand via Generic::CollectionConcern#paginated
(raw limit/offset) and ApplicationPaginationConcern#page_param.

How we know it's dead — the history

kaminari was added, used for a while, and then progressively refactored out as pages moved
to React with backend pagination:

  • Added in 0de8ffc "install gem kaminari"
    (2015-01-14) — a Gemfile/Gemfile.lock-only commit; no code used it yet.
  • First actual use in 71f2019 "Add basic Forum::Topic Controller"
    (2015-11-15), which introduced …with_topic_statistics.includes(:creator).page(params[:page]).with_latest_post
    in the forum topics controller.
  • Over the following years every .page(...) call site (forum topics, comments, submissions,
    experience-points history, announcements, admin panel, video submissions) was removed as
    those features were ported to React, replaced by the hand-rolled paginated scope
    introduced in 65fb218 "refactor(submissions controller): refactor pagination scope".
  • Today: zero .page( / .per( / Kaminari references remain, and the forum topics
    controller that first used it no longer does — the feature that originally motivated the
    gem has been fully refactored away.

Risk / rollback

  • Scope: Gemfile + Gemfile.lock only; no app code.
  • Every changed revision runs on Rails 7.2, so behavior on the current production stack is
    expected to be unchanged. This is the whole point of shipping it as a standalone PR ahead
    of the Rails bump. unread is additionally proven identical (empty lib/ diff vs 0.14.0).
  • Rollback: revert the Gemfile changes and bundle install.
  • Three gems are now consumed from git commit pins (upstream hasn't published these revisions
    to RubyGems). Follow-ups when releases land: active_record_upsert '~> 0.13' once 0.13.0
    ships; unread back to a version constraint once the next release ships;
    calculated_attributes → upstream master/v1.2.0 during the Rails 8.1 PR (it, uniquely,
    needs a second ref bump because no single upstream ref covers both 7.2 and 8.1).
  • kaminari removal is the one change that isn't a pin swap — low risk given it's unused, but
    it's the item most worth a careful boot + full-suite check (see smoke tests).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Rails/ActiveRecord-coupled dependencies to revisions that can be used during the upcoming Rails 7.2 → 8.x migration, while keeping the application on Rails 7.2 today. The PR only changes Bundler inputs/outputs (Gemfile + lockfile) to unblock future Rails upgrades and remove an unused gem.

Changes:

  • Pin active_record_upsert to upstream commit cb6f2a2 (v0.13.0) for Rails 8.1 compatibility.
  • Switch calculated_attributes from the Coursemology fork to upstream aha-app (currently pinned to bd64377).
  • Pin unread to upstream commit 9114324 and remove unused kaminari.

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated 1 comment.

File Description
Gemfile Switches/pins Rails-coupled gems to upstream git commits and removes kaminari.
Gemfile.lock Updates the resolved dependency graph to reflect new git sources and removed gems.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Gemfile Outdated
@adi-herwana-nus
adi-herwana-nus force-pushed the adi/rails-8-upgrade-dependencies-1 branch from a8f3369 to 0363641 Compare July 18, 2026 20:42
adi-herwana-nus and others added 2 commits July 21, 2026 08:08
- re-pinned "active_record_upsert", "calculated_attributes", "unread"
- removed dead "kaminari" gem
Bumps [websocket-driver](https://github.com/faye/websocket-driver-node) from 0.7.4 to 0.7.5.
- [Changelog](https://github.com/faye/websocket-driver-node/blob/main/CHANGELOG.md)
- [Commits](faye/websocket-driver-node@0.7.4...0.7.5)

---
updated-dependencies:
- dependency-name: websocket-driver
  dependency-version: 0.7.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
@adi-herwana-nus
adi-herwana-nus force-pushed the adi/rails-8-upgrade-dependencies-1 branch from 0363641 to 345bad9 Compare July 21, 2026 00:09
@adi-herwana-nus

Copy link
Copy Markdown
Contributor Author

Absorbing changes from #8483 for deployment.

@adi-herwana-nus
adi-herwana-nus enabled auto-merge (rebase) July 21, 2026 00:10
@adi-herwana-nus
adi-herwana-nus disabled auto-merge July 21, 2026 00:10
@adi-herwana-nus
adi-herwana-nus merged commit 6258fea into master Jul 21, 2026
9 of 10 checks passed
@adi-herwana-nus
adi-herwana-nus deleted the adi/rails-8-upgrade-dependencies-1 branch July 21, 2026 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants