Skip to content

Commit

Permalink
Merge pull request #2403 from herwinw/struct_new
Browse files Browse the repository at this point in the history
Fix keyword arguments in Struct.new
  • Loading branch information
herwinw committed Dec 18, 2024
2 parents 26cc851 + b943e2b commit dfcad8c
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 15 deletions.
23 changes: 20 additions & 3 deletions spec/core/struct/new_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ def obj.to_str() "Foo" end
Struct.const_defined?("Animal2").should be_false
end

it "allows non-ASCII member name" do
name = "r\xe9sum\xe9".dup.force_encoding(Encoding::ISO_8859_1).to_sym
struct = Struct.new(name)
struct.new("foo").send(name).should == "foo"
end

it "fails with invalid constant name as first argument" do
-> { Struct.new('animal', :name, :legs, :eyeballs) }.should raise_error(NameError)
Expand Down Expand Up @@ -74,9 +79,21 @@ def obj.to_str() "Foo" end

ruby_version_is "3.2" do
it "raises a TypeError if passed a Hash with an unknown key" do
NATFIXME 'raises a TypeError if passed a Hash with an unknown key', exception: SpecFailedException do
-> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError)
end
-> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError)
end
end

ruby_version_is ""..."3.3" do
it "raises ArgumentError if not provided any arguments" do
-> { Struct.new }.should raise_error(ArgumentError)
end
end

ruby_version_is "3.3" do
it "works when not provided any arguments" do
c = Struct.new
c.should be_kind_of(Class)
c.superclass.should == Struct
end
end

Expand Down
15 changes: 3 additions & 12 deletions src/struct.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class << self
alias [] new
end

def self.new(*attrs, &block)
def self.new(*attrs, keyword_init: nil, &block)
duplicates = attrs.tally.find { |_, size| size > 1 }
unless duplicates.nil?
raise ArgumentError, "duplicate member: #{duplicates.first}"
Expand All @@ -17,15 +17,6 @@ def self.new(*attrs, &block)
attrs.shift
end

if attrs.last.is_a?(Hash)
options = attrs.pop
unknown_keys = options.keys.difference([:keyword_init])
if unknown_keys.any?
raise ArgumentError, "unknown keyword: #{unknown_keys.map(&:inspect).join(', ')}"
end
else
options = {}
end
result = Class.new(Struct) do
include Enumerable

Expand All @@ -38,7 +29,7 @@ def self.new(*attrs, &block)
end
alias_method :size, :length

if options[:keyword_init]
if keyword_init
define_method :initialize do |args = {}|
unless args.is_a?(Hash)
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0)"
Expand All @@ -61,7 +52,7 @@ def self.new(*attrs, &block)
end

self.class.define_method :keyword_init? do
options[:keyword_init] ? true : options[:keyword_init]
keyword_init ? true : keyword_init
end

define_method :each do
Expand Down

0 comments on commit dfcad8c

Please sign in to comment.