# Scope problem in controller

**URL:** <https://www.ruby-forum.com/t/scope-problem-in-controller/181901>\
**Category:** Rails\
**Created:** [January 19, 2010, 10:55pm UTC](https://www.ruby-forum.com/t/scope-problem-in-controller/181901 "2010-01-19T22:55:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![byrnejb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d2c977/32.png) [@byrnejb](https://www.ruby-forum.com/u/byrnejb)\
**Post date:** [January 19, 2010, 10:55pm UTC](https://www.ruby-forum.com/t/scope-problem-in-controller/181901/1 "2010-01-19T22:55:38Z")

</div>

I am writing a small helper to walk a hash or an array of arrays to  
find a nested key. (by the way, if there is an existing function for  
this in Ruby I will willingly take it instead).

The call is this

keywalk(collection, key)

the def is this

def keywalk(collection,key)  
key = key.to\_s  
collection.each do |check|  
return check[1] if check[0] == key  
keywalk(check,key) if (check.is\_a?(Array) or check.is\_a?(Hash))  
end  
nil  
end

The problem that I have is that key is always nil inside  
collection.each even though it is define inside the method and a puts  
shows that it has the value passed as that parameter. Why is key  
evidently out of scope inside the iterator?

---

<div class="post-metadata">

**Author:** ![byrnejb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d2c977/32.png) [@byrnejb](https://www.ruby-forum.com/u/byrnejb)\
**Post date:** [January 20, 2010, 1:19am UTC](https://www.ruby-forum.com/t/scope-problem-in-controller/181901/2 "2010-01-20T01:19:02Z")

</div>

On Jan 19, 9:54Â pm, byrnejb [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Â Â keywalk(check,key) if (check.is\_a?(Array) or check.is\_a?(Hash))  
> Â end  
> Â nil  
> end
> 
> The problem that I have is that key is always nil inside  
> collection.each even though it is define inside the method and a puts  
> shows that it has the value passed as that parameter. Â Why is key  
> evidently out of scope inside the iterator?

blocks can see variables created outside them (but local variables  
created inside the block do not persist outside it)  
Your keywalk function will however almost always return nil - when you  
recurse and call keywalk a second time you are ignoring the return  
value

Fred

---

<div class="post-metadata">

**Author:** ![byrnejb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d2c977/32.png) [@byrnejb](https://www.ruby-forum.com/u/byrnejb)\
**Post date:** [January 20, 2010, 4:14am UTC](https://www.ruby-forum.com/t/scope-problem-in-controller/181901/3 "2010-01-20T04:14:35Z")

</div>

On Jan 19, 7:17Â pm, Frederick C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> blocks can see variables created outside them (but local variables  
> created inside the block do not persist outside it)  
> Your keywalk function will however almost always return nil - when you  
> recurse and call keywalk a second time you are ignoring the return  
> value
> 
> Fred

OK. Then I am missing something simple. And, I am probably trying  
too hard. I will revisit the problem.

---

<div class="post-metadata">

**Author:** ![byrnejb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d2c977/32.png) [@byrnejb](https://www.ruby-forum.com/u/byrnejb)\
**Post date:** [January 20, 2010, 11:11pm UTC](https://www.ruby-forum.com/t/scope-problem-in-controller/181901/4 "2010-01-20T23:11:14Z")

</div>

I am clearly misunderstanding something fundamental about ruby methods  
and the return statement.

I have finally gone for the blunt force solution so that I can follow  
along with what is happening.

def keywalk(tcoll,tkey,result=nil)

```
if result
  puts("result returned = #{result}")
  return result
end

print tcoll.to_yaml
puts("")

tcoll.each_pair do | tk, tv |
  puts("tkey is #{tkey} and tk is: #{tk} and tv is #{tv}")
  if tk.to_s == tkey.to_s
    puts("keys are equal and tv is #{tv}")
    result = { tkey => tv.to_s }
    puts("The result is = #{result}")
    return
  end

  if tv.kind_of?(Array)
    puts("Array = #{tv.inspect}")
    tv.each do |tva|
      if tva.kind_of?(Hash)
        keywalk(tva,tkey,result)
      end
    end
  elsif tv.kind_of?(Hash)
    puts("Hash = #{tv.inspect} class is #{tv.class}")
    keywalk(tv,tkey,result)
  else
    # puts("Something else = #{tv.inspect} with class #

```

{tv.class}")  
end  
end  
puts(“The final result was = #{result}”)  
result  
end

Why, even when I finally find the inner key which this does  
accomplish, do I always get nil returned? What do I misapprehend  
about returns?

tkey is user\_id and tk is: user\_id and tv is 339  
keys are equal and tv is 339  
The result is = user\_id339  
This is what keywalk returns:

---

<div class="post-metadata">

**Author:** ![byrnejb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d2c977/32.png) [@byrnejb](https://www.ruby-forum.com/u/byrnejb)\
**Post date:** [January 21, 2010, 12:24am UTC](https://www.ruby-forum.com/t/scope-problem-in-controller/181901/5 "2010-01-21T00:24:59Z")

</div>

Exactly right.

“return” alone will always return “nil”.

Aleksey

---

<div class="post-metadata">

**Author:** ![byrnejb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d2c977/32.png) [@byrnejb](https://www.ruby-forum.com/u/byrnejb)\
**Post date:** [January 20, 2010, 11:31pm UTC](https://www.ruby-forum.com/t/scope-problem-in-controller/181901/6 "2010-01-20T23:31:08Z")

</div>

Quoting byrnejb [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ```
> return result
> puts("The result is = #{result}")
> return
> end
> 
> ```

Do you mean ‘return result’ here?

Jeffrey

---

<div class="post-metadata">

**Author:** ![byrnejb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d2c977/32.png) [@byrnejb](https://www.ruby-forum.com/u/byrnejb)\
**Post date:** [January 21, 2010, 12:36am UTC](https://www.ruby-forum.com/t/scope-problem-in-controller/181901/7 "2010-01-21T00:36:42Z")

</div>

Jeffrey L. Taylor wrote:

> Quoting byrnejb [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > ```
> > return result
> > puts("The result is = #{result}")
> > return
> > end
> > 
> > ```
> 
> Do you mean ‘return result’ here?

You may also be confused by the ActiveSupport “returning” method.

> Jeffrey

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![byrnejb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d2c977/32.png) [@byrnejb](https://www.ruby-forum.com/u/byrnejb)\
**Post date:** [January 21, 2010, 4:04pm UTC](https://www.ruby-forum.com/t/scope-problem-in-controller/181901/8 "2010-01-21T16:04:58Z")

</div>

Jeffrey L. Taylor wrote:

> > ```
> > end
> > 
> > ```
> 
> Do you mean ‘return result’ here?
> 
> Jeffrey

Thank you for pointing out the error with the return. I fixed that  
and and then finally realised that I was not assigning my return value  
when calling the method recursively. This was why the result was  
disappearing after I found it.

The final code looks like this:

def keywalk(tcoll,tkey,result=nil)

```
tcoll.each_pair do | tk, tv |

  if tk.to_s == tkey.to_s
    result = { tkey => tv.to_s }
    return result if result
  end

  if tv.kind_of?(Array)
    puts("Array = #{tv.inspect}")
    tv.each do |tva|
      if tva.kind_of?(Hash)
        result = keywalk(tva,tkey,result)
        return result if result
      end
    end
  elsif tv.kind_of?(Hash)
    puts("Hash = #{tv.inspect} class is #{tv.class}")
    result = keywalk(tv,tkey,result)
    return result if result
  end
end

return result

```

end

A bit bit wordy but at least I can follow along with it in my head.

Regards,
