[ACCEPTED]-How do I convert hash keys to method names?-ruby
You could just wrap up your hash in an OpenStruct:
require 'ostruct'
tempData = {"a" => 100, "here" => 200, "c" => "hello"}
os = OpenStruct.new tempData
os.a #=> 100
os.here #=> 200
If 5 you really really wanted to, you could also 4 monkey-patch the Hash
class, but I'd advise 3 against that:
class Hash
def method_missing(m, *args, &blk)
fetch(m) { fetch(m.to_s) { super } }
end
end
tempData = {"a" => 100, "here" => 200, "c" => "hello"}
tempData.a #=> 100
Update: In my personal extensions library I added a Hash#to_ostruct method. This 2 will recursively convert a hash into an 1 OpenStruct
including all nested hashes.
There is another way to do this.
JSON.parse(tempData.to_json, object_class: OpenStruct)
that will 3 give object
#<OpenStruct a=100, here=200, c="hello">
In this way nested hash
also will 2 be converted to OpenStruct Object
tempData = {a: { b: { c: 3}}, foo: 200, msg: 'test msg'}
obj = JSON.parse(tempData.to_json, object_class: OpenStruct)
Now we are able to call 1
obj.a.b.c # 3
obj.foo # 200
obj.msg # 'test msg'
Hope this will help someone.
Alternatively, if it’s just a small script 16 it might be more convenient to just extend 15 Hash
itself
class Hash
def method_missing sym,*
fetch(sym){fetch(sym.to_s){super}}
end
end
method_missing
is a magic method that is called 14 whenever your code tries to call a method 13 that does not exist. Ruby will intercept 12 the failing call at run time and let you 11 handle it so your program can recover gracefully. The 10 implementation above tries to access the 9 hash using the method name as a symbol, the 8 using the method name as a string, and eventually 7 fails with Ruby's built-in method missing 6 error.
NB for a more complex script, where 5 adding this behavior might break other third-party 4 gems, you might alternatively use a module and 3 extend each instance
module H def method_missing sym,* fetch(sym){fetch(sym.to_s){super}} end end the = { answer: 42 } the.extend(H) the.answer # => 42
and for greater convenience 2 you can even propagate the module down to nested 1 hashes
module H def method_missing sym,* r = fetch(sym){fetch(sym.to_s){super}} Hash === r ? r.extend(H) : r end end the = { answer: { is: 42 } } the.extend(H) the.answer.is # => 42
If the hash is inside a module, you can 4 define methods on that module (or class) dynamically 3 using define_method
. For example:
module Version
module_function
HASH = {
major: 1,
minor: 2,
patch: 3,
}
HASH.each do |name, value|
define_method(name) do
return value
end
end
end
This will define a Version
module 2 with major
, minor
, and patch
methods that return 1, 2, and 1 3, respectively.
you can extend the Hash class in the following 1 way.
class Hash
# return nil whenever the key doesn't exist
def method_missing(m, *opts)
if self.has_key?(m.to_s)
return self[m.to_s]
elsif self.has_key?(m.to_sym)
return self[m.to_sym]
end
return nil
# comment out above line and replace with line below if you want to return an error
# super
end
end
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.