# Defining a method to select values from a hash

**URL:** <https://www.ruby-forum.com/t/defining-a-method-to-select-values-from-a-hash/169077>\
**Category:** Ruby\
**Created:** [May 29, 2009, 2:29am UTC](https://www.ruby-forum.com/t/defining-a-method-to-select-values-from-a-hash/169077 "2009-05-29T02:29:53Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![dannytip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/58f4c7/32.png) [@dannytip](https://www.ruby-forum.com/u/dannytip)\
**Post date:** [May 29, 2009, 2:29am UTC](https://www.ruby-forum.com/t/defining-a-method-to-select-values-from-a-hash/169077/1 "2009-05-29T02:29:53Z")

</div>

I’m terribly confused with this, and can’t seem to figure it out (or  
explain it).

Using HTTParty, I have a method that grabs some XML and returns it as a  
hash:

def check(data)  
@results = self.class.post(‘/checkDocument’, :query =\> {:key =\>  
@key,  
:data =\> data})  
end

def errors  
errors = @results[‘results’][‘error’]  
end

An example of the hash it returns:

> > atd.check(“I’m realy hating this wether”)  
> > =\> [{“suggestions”=\>{“option”=\>[“really”, “ready”, “real”, “relay”,  
> > “realty”]}, “precontext”=\>“I’m”, “type”=\>“spelling”, “string”=\>“realy”,  
> > “description”=\>“Spelling”}, {“suggestions”=\>{“option”=\>[“weather”,  
> > “whether”]},  
> > “url”=\>“[http://service.afterthedeadline.com/info.slp?text=wether](http://service.afterthedeadline.com/info.slp?text=wether)”,  
> > “precontext”=\>“this”, “type”=\>“spelling”, “string”=\>“wether”,  
> > “description”=\>“Did you mean…”}]

Now calling the .errors method, I can get the string from each one like  
this:

> > atd.errors.each { |error| p error[‘string’] }  
> > “realy”  
> > “wether”

What I’d like to do is write a method for string, so that  
atd.errors.each { |error| p.error.string } would result in the same  
thing. For the life of me, I can’t figure out how to do that. 😕

The other problem I’m having with the way I’m doing it now is that  
calling .errors.each when there’s only one error sent back gives me a  
“can’t convert String into Integer” error.

So, if anyone could point me in the right direction, I’d appreciate it.  
🙂

---

<div class="post-metadata">

**Author:** ![dannytip](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/58f4c7/32.png) [@dannytip](https://www.ruby-forum.com/u/dannytip)\
**Post date:** [May 29, 2009, 10:35am UTC](https://www.ruby-forum.com/t/defining-a-method-to-select-values-from-a-hash/169077/2 "2009-05-29T10:35:52Z")

</div>

You want foo[‘bar’] and foo.bar to be the same thing, like in  
Javascript? In that case you need to modify Hash, not String. Below is  
some code which does that.

---- 8\< ----

# Extend a Hash with this module to get semantics of a Javascript

object:

# me.foo is the same as me[‘foo’]

module JSObjectMixin  
def method\_missing(meth,\*rest,&blk)  
key = meth.to\_s  
if key[-1] == ?=  
self[key[0…-2]] = rest.first  
else  
self[key]  
end  
end  
end

def extend\_jsobject(tree)  
case tree  
when Hash  
tree.extend JSObjectMixin  
tree.each do |k,v|  
extend\_jsobject(v)  
end  
when Array  
tree.each do |v|  
extend\_jsobject(v)  
end  
end  
end

errors = [{“suggestions”=\>{“option”=\>[“really”, “ready”, “real”,  
“relay”,  
“realty”]}, “precontext”=\>“I’m”, “type”=\>“spelling”,  
“string”=\>“realy”,  
“description”=\>“Spelling”}, {“suggestions”=\>{“option”=\>[“weather”,  
“whether”]},  
“url”=\>“[http://service.afterthedeadline.com/info.slp?text=wether](http://service.afterthedeadline.com/info.slp?text=wether)”,  
“precontext”=\>“this”, “type”=\>“spelling”, “string”=\>“wether”,  
“description”=\>“Did you mean…”}]  
extend\_jsobject(errors)

errors.each { |error| p error[‘string’] }  
errors.each { |error| p error.string }  
---- 8\< ----

Another option would be to walk your results structure and replace each  
Hash with an OpenStruct (see ostruct.rb in the standard library).  
However, that would _only_ allow error.string, not error[‘string’]

> The other problem I’m having with the way I’m doing it now is that  
> calling .errors.each when there’s only one error sent back gives me a  
> “can’t convert String into Integer” error.

Simple solution:

Array(atd.errors).each { … }

If atd.errors is already an Array this does nothing; if it isn’t, then  
it is wrapped in a one-element array.

Better solution: If this is using XML::Simple internally, there’s an  
option you can give it to return arrays always, even when there’s only a  
single instance (or I believe you can tell it to do this for specific  
tags). I can’t remember offhand what that option is, but you should be  
able to find it. Then see if the library you’re using allows that option  
to be passed through.

HTH,

Brian.
