Skip to content

WA-RAILS7-008: Update ActiveSupport::Deprecation for Rails 7.1+#707

Merged
kitcommerce merged 1 commit intonextfrom
wa-rails7-008-deprecation
Mar 4, 2026
Merged

WA-RAILS7-008: Update ActiveSupport::Deprecation for Rails 7.1+#707
kitcommerce merged 1 commit intonextfrom
wa-rails7-008-deprecation

Conversation

@kitcommerce
Copy link

Summary

Updates Workarea.deprecation to register with Rails.application.deprecators when running on Rails 7.1+, while keeping backward compatibility with Rails 6.x.

Changes

  • core/lib/workarea.rb: Updated self.deprecation to detect Rails.application.deprecators via respond_to? and register the deprecator when available

Approach

Uses a respond_to? guard so:

  • Rails < 7.1: Creates ActiveSupport::Deprecation.new('3.6', 'Workarea') as before
  • Rails >= 7.1: Also registers it with Rails.application.deprecators[:workarea]

The public Workarea.deprecation API is unchanged — callers don't need to be updated.

Client impact

None — internal deprecation tooling only. No public API changes.

Related

Closes #700

@kitcommerce kitcommerce added gate:build-pending Build gate running gate:build-passed Build gate passed review:architecture-pending Review in progress review:simplicity-pending Review in progress review:security-pending Review in progress review:rails-conventions-pending Rails conventions review in progress and removed gate:build-pending Build gate running labels Mar 1, 2026
@kitcommerce
Copy link
Author

Architecture Review

{
  "reviewer": "architecture",
  "verdict": "PASS",
  "severity": null,
  "summary": "Clean, minimal change that correctly uses respond_to? feature detection for Rails version compatibility.",
  "findings": []
}

Verdict: PASS

The design is sound:

  • Feature detection via respond_to? is the canonical Rails upgrade pattern — preferable to version comparisons since it's resilient to backports and works across arbitrary Rails versions.
  • Lazy initialization with @deprecation ||= is appropriate — the deprecator is stateless configuration, and memoization avoids repeated registration with Rails.application.deprecators.
  • The ||= guard on deprecators[:workarea] correctly prevents overwriting if something else registered a Workarea deprecator first (defensive, low-risk).
  • Placement in self.deprecation is the right spot — it's the single factory method for the deprecator, keeping registration co-located with creation.

No architectural concerns.

@kitcommerce kitcommerce added review:architecture-done Review complete and removed review:architecture-pending Review in progress labels Mar 1, 2026
@kitcommerce
Copy link
Author

Simplicity Review

Verdict: PASS

{
  "reviewer": "simplicity",
  "verdict": "PASS",
  "severity": null,
  "summary": "Change is minimal, clear, and uses idiomatic Rails compatibility guard — no simplicity concerns.",
  "findings": []
}

The begin...end block cleanly expresses three steps: create, conditionally register, return. The respond_to?(:deprecators) guard is the standard Rails version-detection idiom. No unnecessary abstraction, no dead code, easy to read at a glance. ✅

@kitcommerce kitcommerce added review:simplicity-done Review complete and removed review:simplicity-pending Review in progress labels Mar 1, 2026
@kitcommerce
Copy link
Author

🔒 Security Review

{
  "reviewer": "security",
  "verdict": "PASS",
  "severity": null,
  "summary": "No security implications — change registers an internal deprecator with no user input, no serialization, and no auth or data exposure changes.",
  "findings": []
}

The ||= race on @deprecation and deprecators[:workarea] is benign under MRI's GVL (worst case: duplicate object creation, immediately discarded). No injection surface, no privilege changes, no data flow alterations.

@kitcommerce kitcommerce added review:security-done Review complete and removed review:security-pending Review in progress labels Mar 1, 2026
@kitcommerce
Copy link
Author

Rails Conventions Review

Verdict: PASS_WITH_NOTES

{
  "reviewer": "rails-conventions",
  "verdict": "PASS_WITH_NOTES",
  "severity": "LOW",
  "summary": "The approach is idiomatic and safe; one low-priority note about duck-typing vs. version-checking conventions for Rails engines.",
  "findings": [
    {
      "severity": "LOW",
      "file": "core/lib/workarea.rb",
      "line": 183,
      "issue": "Using respond_to?(:deprecators) for version detection is duck-typing, which is generally acceptable, but Rails engine gems more commonly guard on Rails::VERSION::MINOR >= 1 (for 7.1+) to express intent clearly. The current approach will silently succeed if any other object happens to define :deprecators on Rails.application in the future.",
      "suggestion": "Consider replacing the respond_to? guard with an explicit version check: if Rails.gem_version >= Gem::Version.new('7.1'). This makes the intent explicit and is the Rails engine community convention for API availability guards."    }
  ]
}

Notes

The core change is sound and idiomatic:

  • Registering with Rails.application.deprecators[:workarea] is exactly the pattern the Rails 7.1 guides prescribe for engines and gems.
  • Using ||= on the registry slot prevents double-registration if the method is called more than once.
  • The begin…end block returning deprecator correctly preserves the memoized return value regardless of the registration branch taken.

On the version-detection approach: respond_to?(:deprecators) is a valid duck-type guard and is the simplest safe option. However, the Rails engine convention for "feature introduced in version X.Y" is a Gem::Version comparison rather than a duck-type check. The difference is mostly expressive: a version gate documents why the guard exists, making it easier to remove when Rails 6.x support is eventually dropped. Neither approach is wrong; this is a style-level observation, not a blocker.

@kitcommerce kitcommerce added review:rails-conventions-done Rails conventions review complete and removed review:rails-conventions-pending Rails conventions review in progress labels Mar 1, 2026
@kitcommerce
Copy link
Author

Rails Conventions Review

Verdict: PASS_WITH_NOTES

{
  "reviewer": "rails-conventions",
  "verdict": "PASS_WITH_NOTES",
  "severity": null,
  "summary": "Follows Rails conventions correctly; respond_to? is idiomatic for feature detection and deprecators registration matches Rails 7.1+ documented patterns.",
  "findings": [
    {
      "severity": "LOW",
      "file": "core/lib/workarea.rb",
      "line": 183,
      "issue": "Rails.application.deprecators[:workarea] ||= deprecator uses ||= inside a block that is itself guarded by @deprecation ||=, making the inner guard redundant.",
      "suggestion": "Use direct assignment: Rails.application.deprecators[:workarea] = deprecator. The outer memoization already ensures this block runs at most once per process."
    }
  ]
}

Notes

respond_to? pattern ✅ — Duck typing for feature detection is idiomatic Ruby/Rails and more robust than version string comparison. Correct choice here.

deprecators registration ✅ — Rails.application.deprecators[:workarea] = deprecator is exactly the pattern documented in the Rails 7.1 release notes and guides for gem/engine integration.

Lazy registration ⚠️ (LOW, non-blocking) — Registration happens on first call to Workarea.deprecation rather than in a Railtie/Engine initializer. More idiomatic would be a config.after_initialize block in an Engine initializer, but this is a minimal-footprint change and the lazy approach works correctly. Not a blocker.

Inner ||= redundancy (LOW, non-blocking) — See finding above. Cosmetic, no correctness impact.

@kitcommerce kitcommerce added review:rails-security-pending Rails security review in progress review:database-pending Database review in progress review:test-quality-pending Review in progress labels Mar 1, 2026
@kitcommerce
Copy link
Author

Rails Security Review

Verdict: ✅ PASS

No security concerns. The change registers an internal deprecation instance with Rails.application.deprecators — no user input, no data flow, no authorization impact. The respond_to? guard is safe. The loofah (>= 2.19.1) and dragonfly (~> 1.4) bumps are security-positive.

@kitcommerce kitcommerce added review:rails-security-done Rails security review complete and removed review:rails-security-pending Rails security review in progress labels Mar 1, 2026
@kitcommerce
Copy link
Author

Database Review

Verdict: PASS

No database changes in this PR. The deprecation system update and gem version bumps have no data layer impact.

@kitcommerce kitcommerce added review:database-done Database review complete and removed review:database-pending Database review in progress labels Mar 1, 2026
@kitcommerce
Copy link
Author

Rails Security Review

Verdict: PASS

No Rails security concerns. Internal deprecation tooling change — no user input, no auth flows, no data access changes. Dragonfly and loofah updates fix CVEs.

Register deprecator with Rails.application.deprecators when available
(Rails 7.1+) while maintaining backward compatibility with Rails 6.x.

Closes #700
@kitcommerce kitcommerce force-pushed the wa-rails7-008-deprecation branch from 56e362a to a8681b7 Compare March 4, 2026 03:23
@kitcommerce kitcommerce added gate:build-pending Build gate running gate:build-failed Build gate failed gate:build-passed Build gate passed review:architecture-pending Review in progress review:simplicity-pending Review in progress review:security-pending Review in progress review:rails-conventions-pending Rails conventions review in progress and removed gate:build-failed Build gate failed gate:build-pending Build gate running labels Mar 4, 2026
@kitcommerce
Copy link
Author

Architecture Review

Verdict: ✅ PASS_WITH_NOTES

Summary

Clean, minimal change that correctly adapts Workarea.deprecation for Rails 7.1+ while preserving backward compatibility. No architectural concerns.

Findings

No issues found. The change is architecturally sound:

  • Public API preserved: Workarea.deprecation returns the same ActiveSupport::Deprecation instance — all callers are unaffected.
  • Coupling unchanged: The module already depends on Rails and ActiveSupport; registering with Rails.application.deprecators introduces no new cross-layer dependency.
  • Dependency direction correct: Core framework code registering itself with the Rails deprecation registry is the right direction — framework adapts to host, not the other way around.
  • respond_to? guard is idiomatic: Duck-typing the Rails version via feature detection rather than version string comparison is the correct Ruby/Rails pattern. It survives edge cases (backports, monkey-patches) better than Rails::VERSION checks.
  • ||= on registration is defensive: Prevents double-registration if deprecation is called after something else already registered a :workarea deprecator — good.

Notes (observational, no action needed)

  • (LOW) core/lib/workarea.rb:183 — The memoized method now has a side effect (registration) inside a lazy initializer. This is a minor smell in the abstract — initialization and registry enrollment happen in the same call. An alternative would be a Rails.application.config.after_initialize hook. However, for a single deprecator registration this is entirely pragmatic and introducing an initializer would be over-engineering for the scope. No change recommended.

Recommendation

Merge as-is. The approach is consistent with how other gems (e.g., rails-i18n, devise) handle deprecator registration for Rails 7.1+ compatibility.

@kitcommerce kitcommerce added review:architecture-done Review complete and removed review:architecture-pending Review in progress labels Mar 4, 2026
@kitcommerce
Copy link
Author

Security Review

Verdict: ✅ PASS

Reviewer: Security

Summary

This change updates Workarea.deprecation to register with Rails.application.deprecators on Rails 7.1+ via a respond_to? guard, while preserving backward compatibility with Rails 6.x. Reviewed the diff for security concerns.

Findings

No security issues found. Specifically verified:

  • No secrets or credentials — no tokens, API keys, or sensitive data introduced
  • No injection risk — no user-supplied input; purely internal framework registration
  • No data exposure — deprecation warnings are developer-facing tooling, no PII or sensitive data involved
  • No auth/authz impact — no changes to authentication or authorization paths
  • Safe runtime guardrespond_to?(:deprecators) is a clean capability check with no side effects
  • Defensive registration||= avoids overwriting any existing deprecator, preventing accidental clobbering

Recommendations

None. This is a minimal, well-scoped internal tooling change with no security surface.

@kitcommerce
Copy link
Author

Simplicity Review

Verdict: PASS_WITH_NOTES (LOW)

Findings

  • LOWcore/lib/workarea.rb, line ~183: The begin...end block with a local variable is functional but slightly more ceremony than necessary. The same intent can be expressed more concisely with .tap:

    # Current (6 lines inside begin...end)
    @deprecation ||= begin
      deprecator = ActiveSupport::Deprecation.new('3.6', 'Workarea')
      if Rails.application.respond_to?(:deprecators)
        Rails.application.deprecators[:workarea] ||= deprecator
      end
      deprecator
    end
    
    # Alternative (3 lines, same behavior)
    @deprecation ||= ActiveSupport::Deprecation.new('3.6', 'Workarea').tap do |d|
      Rails.application.deprecators[:workarea] ||= d if Rails.application.respond_to?(:deprecators)
    end
  • LOW — The inner ||= on Rails.application.deprecators[:workarea] is a mild defensiveness smell. Since the outer method memoizes via @deprecation ||=, being called with an already-set key is unlikely. Harmless, but not strictly necessary.

Recommendations

  • Consider the .tap refactor above — it removes the local variable and trims 3 lines without sacrificing readability. Either form is acceptable.
  • No blockers. Change is appropriately minimal for the problem: one compatibility guard, one behavioral difference, no new abstractions.

Summary

Change is well-scoped and proportionate. No over-engineering, no new concepts, no unnecessary abstraction. Public API is unchanged. The two LOW notes are cosmetic cleanup suggestions, not correctness concerns.

@kitcommerce kitcommerce added review:security-done Review complete and removed review:security-pending Review in progress labels Mar 4, 2026
@kitcommerce
Copy link
Author

Rails Conventions Review

Verdict: PASS

Findings

No Rails convention violations. This is a clean, idiomatic change.

What the diff does (conventions lens):

  • Uses ||= with a begin...end block for lazy memoization — idiomatic Ruby/Rails
  • Uses respond_to? for feature detection — the standard Rails pattern for multi-version compatibility
  • Registers with Rails.application.deprecators[:workarea] — exactly the Rails 7.1+ convention for per-gem deprecators
  • Uses ||= on the registry assignment, so if another initializer already registered a :workarea key it won't clobber it — thoughtful

Works with Rails, not against it. The change embraces the framework's evolving deprecation conventions rather than fighting them or papering over the difference.

Recommendations

None required. One observational note:

  • Rails.application is assumed to be non-nil at call time. This is the same assumption the existing code made (ActiveSupport is a Rails dependency), so it's not a regression. If self.deprecation were ever called before application initialization, Rails.application.respond_to?(...) would raise a NoMethodError — but that's a pre-existing constraint, not introduced here.

Reviewed by: rails-conventions agent | Wave 1

@kitcommerce
Copy link
Author

Rails Security Review

Verdict: PASS

Findings

No Rails security concerns. This change modifies internal deprecation infrastructure only — no user-facing input, no parameter handling, no query construction, no view rendering, no authentication/authorization changes, and no secrets.

Recommendations

None.

@kitcommerce
Copy link
Author

Database Review

Verdict: PASS

Findings

  • No database migrations, schema changes, or query modifications in this PR.
  • Change is limited to Ruby-level deprecation infrastructure (ActiveSupport::Deprecation registration).

Recommendations

  • None — this PR has no database surface area.

@kitcommerce
Copy link
Author

Test Quality Review

Verdict: PASS_WITH_NOTES

Findings

  • No direct test for Workarea.deprecation: core/test/workarea_test.rb exists but contains only a trivial smoke test (assert_kind_of Module, Workarea). No test directly exercises the self.deprecation method or its return value.

  • Rails 7.1 registration path is untested explicitly: The new Rails.application.deprecators[:workarea] ||= deprecator branch has no assertion verifying that registration actually occurs on Rails 7.1+. If this silent registration were to silently fail (e.g., the key were wrong, or the object were not what Rails expects), no existing test would catch it.

  • Rails 6.x fallback path is also untested explicitly: No test stubs out respond_to?(:deprecators) returning false and asserts the plain deprecator is still returned correctly.

  • Coverage is indirect: CI passes on both Rails 6.1 and 7.1 matrices. Workarea.deprecation is called in production code loaded during test runs (e.g., authentication.rb, order/item.rb, test_case.rb), so a catastrophic breakage would surface — but a subtly incorrect registration (wrong key, double-registration, nil return) would not.

  • Memoization not tested: The @deprecation ||= begin...end block means the first call wins for the lifetime of the process. No test verifies idempotency (calling Workarea.deprecation twice returns the same instance).

Recommendations

  1. Add a unit test in core/test/workarea_test.rb covering:

    • Workarea.deprecation returns an ActiveSupport::Deprecation instance
    • The return value is memoized (same object on repeated calls)
    • On Rails 7.1+: Rails.application.deprecators[:workarea] equals Workarea.deprecation
    • On Rails 6.x (mocked): registration is skipped gracefully, deprecator is still returned
  2. Example skeleton:

    def test_deprecation_returns_active_support_deprecation
      assert_instance_of ActiveSupport::Deprecation, Workarea.deprecation
    end
    
    def test_deprecation_is_memoized
      assert_same Workarea.deprecation, Workarea.deprecation
    end
    
    def test_deprecation_registered_with_rails_deprecators
      skip unless Rails.application.respond_to?(:deprecators)
      assert_equal Workarea.deprecation, Rails.application.deprecators[:workarea]
    end

Context

The change itself is simple, idiomatic, and the CI matrix provides meaningful confidence (both Rails versions run the full test suite). The gap is that the CI passes via indirect coverage — if a future change breaks the deprecators integration specifically, there is no targeted test that would catch it. This is a low-risk but real coverage debt.

@kitcommerce
Copy link
Author

Performance Review

Verdict: PASS

Findings

  • Change is fully guarded by @deprecation ||= memoization — the entire block executes at most once per process lifetime (on first call to Workarea.deprecation)
  • Added overhead per invocation after initialization: zero (memoized @deprecation short-circuits immediately)
  • One-time startup cost: one respond_to? call (fast Ruby introspection, ~nanoseconds) + one hash lookup/assignment on Rails.application.deprecators — both O(1) and negligible
  • No database queries, no I/O, no per-request overhead, no object retention beyond the single ActiveSupport::Deprecation instance already being created in the original code
  • The ||= on deprecators[:workarea] is a nice touch — safe even if something else registers the same key first

Recommendations

  • None. This is purely startup initialization with no measurable performance impact.

@kitcommerce
Copy link
Author

Frontend Review

Verdict: PASS

Findings

  • No JavaScript, CSS, or view template changes in this diff
  • Change is confined to core/lib/workarea.rb — pure Ruby backend infrastructure
  • No asset pipeline impact
  • No accessibility implications
  • No XSS or frontend security surface touched

Recommendations

  • None — nothing to review from a frontend perspective

@kitcommerce
Copy link
Author

Accessibility Review

Verdict: PASS

Findings

  • No accessibility impact. This is a pure server-side Ruby change updating ActiveSupport::Deprecation registration for Rails 7.1+ compatibility.
  • No view templates, HTML, CSS, JavaScript, or any UI surface area was modified.
  • ARIA, keyboard navigation, focus management, color contrast, screen reader compatibility, and form labeling are all out of scope for this diff.

Recommendations

  • None. No accessibility considerations apply to this change.

@kitcommerce
Copy link
Author

Documentation Review

Verdict: PASS_WITH_NOTES

Findings

  • No doc updates needed for this change. The update keeps the public Workarea.deprecation API unchanged and adds Rails 7.1+ registration via Rails.application.deprecators behind a respond_to? guard.
  • Optional note (non-blocking): If you maintain internal upgrade notes for Rails 7.1 adoption, it may be worth adding a short mention that Workarea now registers its deprecator under :workarea in Rails.application.deprecators when available. This can help with debugging/centralized deprecation behavior in host apps.

@kitcommerce
Copy link
Author

✅ All Review Waves Passed

All reviewers returned PASS or PASS_WITH_NOTES. This PR is merge-ready.

  • Wave 1 (Foundation): ✅ architecture, simplicity, security
  • Wave 2 (Correctness): ✅ test-quality, rails-conventions, rails-security, database
  • Wave 3 (Quality): ✅ performance, accessibility, frontend
  • Wave 4 (Documentation): ✅ documentation (PASS_WITH_NOTES — no doc updates required; optional internal note about Rails.application.deprecators[:workarea] registration on 7.1+)

Labeled merge:ready. Awaiting auto-merge after hold window (60 min).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gate:build-passed Build gate passed merge:ready All conditions met, eligible for merge review:accessibility-done Review complete review:architecture-done Review complete review:database-done Database review complete review:documentation-done review:frontend-done Frontend review complete review:performance-done Review complete review:rails-conventions-done Rails conventions review complete review:rails-security-done Rails security review complete review:security-done Review complete review:simplicity-done Review complete review:test-quality-done Review complete

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant