For example, I have a hash, in which updating is valid but adding new key is invalid.
opts = {
url: 'www.google.com',
local: 'disk',
limit: 10
}
opts[:url] = 'www.facebook.com' # valid
opts[:other] = 'www.apple.com' # should raise an error
For example, I have a hash, in which updating is valid but adding new key is invalid.
opts = {
url: 'www.google.com',
local: 'disk',
limit: 10
}
opts[:url] = 'www.facebook.com' # valid
opts[:other] = 'www.apple.com' # should raise an error
Using a built-in like Struct
as @stefan suggested is a nice fast solution. Only the initiation is a bit weird.
opts = Struct.new(:url, :local, :limit).new(
'www.google.com', 'disk', 10
)
opts[:url] = 'www.facebook.com'
opts[:other] = 'www.apple.com' # NameError: no member 'other' in struct
opts.to_h #=> {:url=>"www.facebook.com", :local=>"disk", :limit=>10}
However, if you want to you can also somewhat easily build your own solution to have more control over how it works and to be more similar to an actual hash.
class MyHash < Hash
def initialize(hash)
super()
update(hash)
end
def []=(key, value)
raise 'Unknown key passed to MyHash' unless key?(key) # or whatever error you want
super
end
end
opts = MyHash.new(
url: 'www.google.com',
local: 'disk',
limit: 10
)
opts[:url] = 'www.facebook.com'
opts[:other] = 'www.apple.com' # RuntimeError: Unknown key passed to MyHash
opts #=> {:url=>"www.facebook.com", :local=>"disk", :limit=>10}
MyHash
is a Hash
for basically all purposes and can be used anywhere a regular hash can. Do note though, that this only overrides the direct setter ([]=
). Indirectly assigning new values via update
(merge!
) for example still works.
While using Struct is a better option you can also consider to Freeze the Hash.
But you cannot update directly the key, so it doesn't work with all keys object, for example Integers, so you need to use keys as String, Arrays, etc:
h = {a: 'aa', b: 'bb', c: '1', ary: [1]}
h.freeze
h[:b].replace 'ss'
h[:c].replace '2'
h[:ary] << 10
h
#=> {:a=>"aa", :b=>"ss", :c=>"2", :ary=>[1, 10]}
h[:d] = '10'
#=> can't modify frozen Hash: {:a=>"aa", :b=>"ss", :c=>"2", :ary=>[1, 10]} (FrozenError)