From e38ab848ababedf80b2464d0fb33d658287d8d9e Mon Sep 17 00:00:00 2001 From: "Durable Programming, LLC" Date: Wed, 19 Feb 2025 13:17:38 -0500 Subject: [PATCH 1/2] Add has_key? method to OpenStruct class Adds has_key? method to OpenStruct class to check if a given name exists as a member. This allows checking for presence of a key without creating an accessor method. Method accepts both string and symbol keys, converting them to symbols before checking. Includes comprehensive test coverage for various usage scenarios. --- lib/ostruct.rb | 24 ++++++++++++++++++ test/ostruct/test_ostruct.rb | 47 ++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/lib/ostruct.rb b/lib/ostruct.rb index a8763da..cf057f6 100644 --- a/lib/ostruct.rb +++ b/lib/ostruct.rb @@ -383,6 +383,30 @@ def delete_field(name, &block) end end + + # Returns +true+ if the given name is a member of this OpenStruct object, +false+ otherwise. + # The given +name+ is converted to a symbol before checking. + # + # require "ostruct" + # person = OpenStruct.new("name" => "John Smith", :age => 70) + # person.has_key?(:name) # => true + # person.has_key?("age") # => true + # person.has_key?(:phone) # => false + # + # This method can be used to test for the presence of a value without creating + # an accessor method if it doesn't exist: + # + # person = OpenStruct.new + # person.name = "John" + # person.has_key?(:name) # => true + # person.has_key?(:age) # => false + # person.age # => nil (but creates an accessor) + # person.has_key?(:age) # => false + # + def has_key?(name) + @table.has_key?(name.to_sym) + end + InspectKey = :__inspect_key__ # :nodoc: # diff --git a/test/ostruct/test_ostruct.rb b/test/ostruct/test_ostruct.rb index 616f84d..6b5d04d 100644 --- a/test/ostruct/test_ostruct.rb +++ b/test/ostruct/test_ostruct.rb @@ -439,4 +439,51 @@ def test_performance_warning ) end end + def setup + end + + def test_has_key_with_symbol + o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) + assert_true o.has_key?(:name) + assert_true o.has_key?(:age) + assert_true o.has_key?(:pension) + assert_false o.has_key?(:address) + end + + def test_has_key_with_string + o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) + assert_true o.has_key?("name") + assert_true o.has_key?("age") + assert_true o.has_key?("pension") + assert_false o.has_key?("address") + end + + def test_has_key_after_deletion + o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) + o.delete_field(:name) + assert_false o.has_key?(:name) + end + + def test_has_key_with_nil_value + o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) + o.pension = nil + assert_true o.has_key?(:pension) + end + + def test_has_key_with_new_ostruct + os = OpenStruct.new + assert_false os.has_key?(:any_key) + end + + def test_has_key_after_setting_value + o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) + o.phone = "123-456-7890" + assert_true o.has_key?(:phone) + end + + def test_has_key_case_sensitivity + o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) + assert_true o.has_key?(:name) + assert_false o.has_key?(:Name) + end end From 4e6c28621fc1c76ed52b903fdd6df8b3b8557eaf Mon Sep 17 00:00:00 2001 From: Durable Programming Team Date: Sun, 21 Sep 2025 09:33:57 -0400 Subject: [PATCH 2/2] rename has_key? to include?, add key? and has_key? as aliases --- lib/ostruct.rb | 16 ++++++----- test/ostruct/test_ostruct.rb | 56 ++++++++++++++++++++++-------------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/lib/ostruct.rb b/lib/ostruct.rb index cf057f6..e8ab721 100644 --- a/lib/ostruct.rb +++ b/lib/ostruct.rb @@ -389,23 +389,25 @@ def delete_field(name, &block) # # require "ostruct" # person = OpenStruct.new("name" => "John Smith", :age => 70) - # person.has_key?(:name) # => true - # person.has_key?("age") # => true - # person.has_key?(:phone) # => false + # person.include?(:name) # => true + # person.include?("age") # => true + # person.include?(:phone) # => false # # This method can be used to test for the presence of a value without creating # an accessor method if it doesn't exist: # # person = OpenStruct.new # person.name = "John" - # person.has_key?(:name) # => true - # person.has_key?(:age) # => false + # person.include?(:name) # => true + # person.include?(:age) # => false # person.age # => nil (but creates an accessor) - # person.has_key?(:age) # => false + # person.include?(:age) # => false # - def has_key?(name) + def include?(name) @table.has_key?(name.to_sym) end + alias_method :has_key?, :include? + alias_method :key?, :include? InspectKey = :__inspect_key__ # :nodoc: diff --git a/test/ostruct/test_ostruct.rb b/test/ostruct/test_ostruct.rb index 6b5d04d..a31e7d1 100644 --- a/test/ostruct/test_ostruct.rb +++ b/test/ostruct/test_ostruct.rb @@ -442,48 +442,62 @@ def test_performance_warning def setup end - def test_has_key_with_symbol + def test_has_key_alias + o = OpenStruct.new(name: "John Smith", age: 70) + assert_equal o.include?(:name), o.has_key?(:name) + assert_equal o.include?("name"), o.has_key?("name") + assert_equal o.include?(:missing), o.has_key?(:missing) + end + + def test_include_with_symbol o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) - assert_true o.has_key?(:name) - assert_true o.has_key?(:age) - assert_true o.has_key?(:pension) - assert_false o.has_key?(:address) + assert_true o.include?(:name) + assert_true o.include?(:age) + assert_true o.include?(:pension) + assert_false o.include?(:address) end - def test_has_key_with_string + def test_include_with_string o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) - assert_true o.has_key?("name") - assert_true o.has_key?("age") - assert_true o.has_key?("pension") - assert_false o.has_key?("address") + assert_true o.include?("name") + assert_true o.include?("age") + assert_true o.include?("pension") + assert_false o.include?("address") end - def test_has_key_after_deletion + def test_include_after_deletion o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) o.delete_field(:name) - assert_false o.has_key?(:name) + assert_false o.include?(:name) end - def test_has_key_with_nil_value + def test_include_with_nil_value o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) o.pension = nil - assert_true o.has_key?(:pension) + assert_true o.include?(:pension) end - def test_has_key_with_new_ostruct + def test_include_with_new_ostruct os = OpenStruct.new - assert_false os.has_key?(:any_key) + assert_false os.include?(:any_key) end - def test_has_key_after_setting_value + def test_include_after_setting_value o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) o.phone = "123-456-7890" - assert_true o.has_key?(:phone) + assert_true o.include?(:phone) end - def test_has_key_case_sensitivity + def test_include_case_sensitivity o = OpenStruct.new(name: "John Smith", age: 70, pension: 300) - assert_true o.has_key?(:name) - assert_false o.has_key?(:Name) + assert_true o.include?(:name) + assert_false o.include?(:Name) + end + + def test_key_alias + o = OpenStruct.new(name: "John Smith", age: 70) + assert_equal o.include?(:name), o.key?(:name) + assert_equal o.include?("name"), o.key?("name") + assert_equal o.include?(:missing), o.key?(:missing) end end