New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide an easy way to get NoMethodError
instead of nil
on undefined keys.
#60
Comments
What about implementing a fetch method that raises a key error much like a hash does? This then stays with the spirit of a hash. class Hashie::Mash
def fetch(key)
raise KeyError, 'key not found' unless self.include?(key)
self[key]
end
end |
@scottnicolson -- but that wouldn't apply to the hashie dot syntax, would it? I like the dot syntax a lot (e.g. |
BTW, for anyone who tries my snippet above: it works on 1.9 but I discovered it didn't work on 1.8.7 because there is no |
I'd be happy to help review a pull if you've come up with a solution you like. |
@myronmarston any developments? |
Bump. |
👍 for that feature |
I believe the StrictKeyAccess extension in 3.4.3 does this, can someone confirm and close this issue? |
@dblock When I was attempting to verify, I discovered that class StrictMash < Hashie::Mash
include Hashie::Extensions::StrictKeyAccess
end
h = StrictMash.new('a' => {'b' => 3}) #=> Hashie::Extensions::StrictKeyAccess::DefaultError The reason is because I'm not a big fan of that, but I don't really see a clear way forward. We could make it so accessing We could make a different extension that is only for Mash that is slightly less constraining, but I don't know if that's a good way forward either. What are your thoughts? |
Maybe we should build a StringKeyAccess extension for Mash then that is based on |
Pretty old issue but in case somebody needs that too: I tried a few approaches and for now, I'm on a variation of @scottnicolson suggestion that override require "hashie/mash"
class StrictMash < Hashie::Mash
# Extends Hashie::Mash but raises a KeyError when trying to access a property
# that doens't exist yet. A naive version of this consists in aliasing `[]` to
# `fetch` but it makes it impossible to use nice Mash aliases such as `<field>!`,
# `<field>?`, etc.
# So instead we override `method_missing` with just a tiny patch inside.
def method_missing(method_name, *args, &blk)
return self.[](method_name, &blk) if key?(method_name)
name, suffix = method_name_and_suffix(method_name)
# PATCH
if !key?(name) and !suffix
raise KeyError, %(key not found: "#{name}")
end
# EOF PATCH
case suffix
when '='.freeze
assign_property(name, args.first)
when '?'.freeze
!!self[name]
when '!'.freeze
initializing_reader(name)
when '_'.freeze
underbang_reader(name)
else
self[method_name]
end
end
end The nice thing is that it preserves all Mash behaviours, including sub-hashes being StrictMash instances ( StrictKeyAccess is actually too strict and will prevent using Mash's "!", "?", etc suffixes from what I saw. I think StrictKeyAccess not working in Mash is a bug in either Mash or StrictKeyAccess though: Mash first argument is a hash to be converted, not a default value, so it shouldn't trigger the DefaultError it triggers right now if you don't pass a default value / block. If somebody finds the issue interesting enough, I'm up for discussing it and work on a clean PR that could be merged at some point. Else I'll keep my dirty hack, "it works" ;-) |
I find it interesting enough for a PR! |
Instead of a module, what would we think of making the handler injectable? Basically, the Of course, that increases the responsibilities of an already huge class ... 🤔 |
@jbbarth's patch, simplified by using
|
This is the oldest issue in Hashie. Can someone PR the version above as an extension? @betesh |
I'm not involved in any projects using hashie at the moment. If you just want someone to open a PR, feel free to use my code. |
My request is similar to #17.
Hashie::Mash
, out of the box, doesn't provide a way to distinguish between a fat-fingered/typo'd key and a key that exists but is set to nil. I saw @mbleigh's comment on #17 saying thatHashie::Mash
is meant to work like a hash, and since that's how a hash works, that's how aHashie::Mash
works. I get that. The suggested he suggested in that thread works OK for flat hash but falls apart once you start working with nested hashes:I came up with a version that does work, but it feels like a lot of code for something that should be simpler:
On top of that, it took me several hours to come up with this working version; I had several previous attempts that did things like subclass
Hashie::Mash
but I kept getting errors on instantiation that I couldn't work around. This version I've come up with also suffers from a potential perf issue: it has to walk the entire nested hash tree to ensure every level gets this behavior.Ideally, I'd love if Hashie supported one of these two things out of the box:
The text was updated successfully, but these errors were encountered: