Skip to content

Commit

Permalink
Emit a performance warning when OpenStruct is used
Browse files Browse the repository at this point in the history
The OpenStruct documentation clearly state that it shouldn't
be used when performance is expected.

Ruby 3.3 introduce a new category of warnings that is silenced
by default: performance.

The expected use case is to enable this warning when looking
for potential performance issues within an application.

As such I think it would make sense to emit a performance warning
when OpenStruct is used, as it may help pinpoint that a dependency
rely on it, etc.
  • Loading branch information
byroot committed Sep 28, 2023
1 parent ba2c352 commit 8a814d9
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 0 deletions.
12 changes: 12 additions & 0 deletions lib/ostruct.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@
class OpenStruct
VERSION = "0.5.5"

HAS_PERFORMANCE_WARNINGS = begin
Warning[:performance]
true
rescue NoMethodError, ArgumentError
false
end
private_constant :HAS_PERFORMANCE_WARNINGS

#
# Creates a new OpenStruct object. By default, the resulting OpenStruct
# object will have no attributes.
Expand All @@ -124,6 +132,10 @@ class OpenStruct
# data # => #<OpenStruct country="Australia", capital="Canberra">
#
def initialize(hash=nil)
if HAS_PERFORMANCE_WARNINGS && Warning[:performance]
warn "OpenStruct use is discouraged for performance reasons", uplevel: 1, category: :performance
end

if hash
update_to_values!(hash)
else
Expand Down
1 change: 1 addition & 0 deletions ostruct.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ Gem::Specification.new do |spec|

spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
spec.add_development_dependency "test-unit"
end
19 changes: 19 additions & 0 deletions test/ostruct/test_ostruct.rb
Original file line number Diff line number Diff line change
Expand Up @@ -412,4 +412,23 @@ def test_class
assert_equal('my-class', os.class)
assert_equal(OpenStruct, os.class!)
end

has_performance_warnings = begin
Warning[:performance]
true
rescue NoMethodError, ArgumentError
false
end

if has_performance_warnings
def test_performance_warning
assert_in_out_err(
%w(-Ilib -rostruct -w -W:performance -e) + ['OpenStruct.new(a: 1)'],
"",
[],
["-e:1: warning: OpenStruct use is discouraged for performance reasons"],
success: true,
)
end
end
end

0 comments on commit 8a814d9

Please sign in to comment.