Reputation: 10882
I want to use the new Ruby 3 feature in this very simple case. I know it must be possible but I have not figured it out from the documentation.
Given a hash, I want to check that it has certain keys. I don't mind if it has others in addition. And I want to do this with pattern matching (or know that it is impossible.) I also don't want to use a case statement which seems overkill.
{name: "John", salary: 12000, email: "[email protected]" }
Raise an error if the hash does not have name, and email as strings and salary as a number.
Use the contruct in an if or other conditional?
And what if the hash has strings as keys (which is what I get from JSON.parse) ?
{"name" => "John", "salary" => 12000, "email" => "[email protected]" }
Upvotes: 0
Views: 1729
Reputation: 4927
You're looking for the =>
operator:
h = {name: "John", salary: 12000, email: "[email protected]" }
h => {name: String, salary: Numeric, email: String} # => nil
With an additional pair (test: 0
):
h[:test] = 0
h => {name: String, salary: Numeric, email: String} # => nil
Without the :name
key:
h.delete :name
h => {name: String, salary: Numeric, email: String} # key not found: :name (NoMatchingPatternKeyError)
With the :name
key but the class of its value shouldn't match:
h[:name] = 1
h => {name: String, salary: Numeric, email: String} # String === 1 does not return true (NoMatchingPatternKeyError)
A strict match:
h[:name] = "John"
h => {name: String, salary: Numeric, email: String} # => rest of {:test=>0} is not empty
The in
operator returns a boolean value instead of raising an exception:
h = {name: "John", salary: 12000, email: "[email protected]" }
h in {name: String, salary: Numeric, email: String} # => true
h[:name] = 1
h in {name: String, salary: Numeric, email: String} # => false
Upvotes: 4
Reputation: 80065
"I also don't want to use a case statement which seems overkill." case
is just the syntax for pattern matching. AFAIK it is not the same as a case when
, it's a case in
.
h = {name: "John", salary: 12000, email: "[email protected]", other_stuff: [1] }
case h
in {name: String, salary: Integer, email: String}
puts "matched"
else
raise "#{h} not matched"
end
Upvotes: 3