Skip to content

Fix NoMethodError on enum methods when subclass defines no enums of its own - #58

Merged
dblock merged 1 commit into
masterfrom
fix-subclass-no-defines
Aug 15, 2026
Merged

Fix NoMethodError on enum methods when subclass defines no enums of its own#58
dblock merged 1 commit into
masterfrom
fix-subclass-no-defines

Conversation

@dblock

@dblock dblock commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #49.

Ruby::Enum's class methods (keys, values, key?, value?, key, value, to_h, parse, each) read directly from the @_enum_hash/@_enums_by_value instance variables. These are only initialized the first time define is called on a class (or explicitly in the included hook).

A subclass that inherits Ruby::Enum behavior purely through Ruby class inheritance - without calling define itself and without re-including Ruby::Enum - never has these ivars set on its own singleton class, so any of the above methods raised NoMethodError: undefined method '...' for nil.

class PostMediaType
  include Ruby::Enum
  define :FOO, 'foo'
end

class PostVideoType < PostMediaType
end

PostVideoType.values
# NoMethodError: undefined method `values' for nil

Fix

Introduces private _enum_hash/_enums_by_value reader methods that lazily default to {}, and uses them everywhere instead of the raw instance variables. This preserves all existing behavior (including values' superclass-aware recursion) while making the other methods null-safe for subclasses with no enums of their own.

Testing

  • Added a SubclassWithNoOwnDefines test class and specs covering values plus a regression test that keys, key?, value?, key, value, to_h, parse, and each no longer raise.
  • bundle exec rspec spec/ - 55 examples, 0 failures, 100% line coverage.
  • bundle exec rubocop - clean.
  • spec_i18n suite - 3 examples, 0 failures.

Ruby::Enum's class methods (keys, values, key?, value?, key, value,
to_h, parse, each) relied directly on @_enum_hash/@_enums_by_value
instance variables, which are only set the first time define is
called. A subclass that includes Ruby::Enum only through inheritance
and never calls define itself never gets these ivars set, so calling
any of the above methods raised NoMethodError on nil.

Introduces private _enum_hash/_enums_by_value reader methods that
default to an empty hash, and uses them everywhere instead of the raw
instance variables.

Closes #49.

Co-authored-by: Copilot <[email protected]>
@github-actions

Copy link
Copy Markdown

Danger Report

No issues found.

View run

@dblock
dblock merged commit 19b3249 into master Aug 15, 2026
22 checks passed
@dblock
dblock deleted the fix-subclass-no-defines branch August 15, 2026 01:09
dblock added a commit that referenced this pull request Aug 15, 2026
…erclass

Follow-up to #49/#58. values already merged enums from a superclass
chain, but keys, key?, value?, key, value, to_h, parse and each only
looked at a class' own enums, silently ignoring any enums defined in
a superclass.

Introduces _enum_hash/_enums_by_value that merge a class' own enums
with those of its superclass chain (subclass definitions take
precedence over the same key/value defined in a superclass), and uses
them for all read methods. define/duplicate validation continues to
use the class' own enums only (_own_enum_hash/_own_enums_by_value), so
a subclass may still redefine a key or value already used by a
superclass.

Documents the change in README.md and UPGRADING.md, and adds tests
covering a subclass redefining a parent class' key.

Co-authored-by: Copilot <[email protected]>
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.

Add support for sub/superclasses (NoMethodError: undefined method `values' for nil ?)

1 participant