Skip to content

Replace OpenStruct with hash-backed Context (v4.0.0)#225

Open
crisnahine wants to merge 2 commits intocollectiveidea:masterfrom
crisnahine:master
Open

Replace OpenStruct with hash-backed Context (v4.0.0)#225
crisnahine wants to merge 2 commits intocollectiveidea:masterfrom
crisnahine:master

Conversation

@crisnahine
Copy link

@crisnahine crisnahine commented Mar 6, 2026

Summary

  • Replaces Interactor::Context < OpenStruct with a plain hash-backed implementation
  • Removes the ostruct runtime dependency entirely
  • Bumps version to 4.0.0 (semver major — breaking change)

Motivation

OpenStruct was deprecated in Ruby 3.2+ and may be removed in a future Ruby version. This change eliminates the deprecation warning and future-proofs the gem with zero runtime dependencies.

What changed

lib/interactor/context.rb

  • Context now inherits from Object instead of OpenStruct
  • Hash-backed @table store with method_missing for dynamic accessors
  • Implements [], []=, to_h, ==, inspect, to_s explicitly
  • Compatible with Ruby 1.9+ (uses plain Hash#each, not transform_keys)

interactor.gemspec

  • Removed spec.add_dependency "ostruct"
  • Version bumped to 4.0.0

lib/interactor.rb

  • Fixed pre-existing StandardRB Lint/IdentityComparison warning (object_id !=!equal?)

spec/interactor/context_spec.rb

  • Added spec asserting Context.superclass == Object to lock in the new contract
  • Updated send(:table) internal accessor test to use public to_h

Breaking changes

  • context.is_a?(OpenStruct) now returns false
  • OpenStruct-only methods (each_pair, marshal_dump, marshal_load) are no longer available

Migration: If your code does not check is_a?(OpenStruct) or call OpenStruct-specific methods, no changes are required.

Test results

111 examples, 0 failures
StandardRB: no offenses

Upgrades

- Assert Context.superclass == Object (currently fails — inherits OpenStruct)
- Replace internal send(:table) test with public to_h assertion
Interactor::Context no longer inherits from OpenStruct, which is
deprecated in Ruby 3.2+ and may be removed in a future Ruby version.
The replacement is a plain hash-backed implementation that preserves
the full public API with no runtime dependencies.

Breaking changes (major version bump to 4.0.0):
- context.is_a?(OpenStruct) now returns false
- OpenStruct-only methods (each_pair, marshal_dump, etc.) are gone

All documented public API is unchanged:
- Dynamic attribute accessors (context.foo, context.foo = val)
- Bracket access ([], []=) with symbol/string key normalization
- to_h, ==, inspect, to_s, fail!, success?, failure?, rollback!
- deconstruct_keys for Ruby 3.0+ pattern matching

Also fixes a StandardRB identity comparison warning in Interactor#run.
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.

1 participant