# Assigning constant as an unbound dynamic method

**URL:** <https://www.ruby-forum.com/t/assigning-constant-as-an-unbound-dynamic-method/79185>\
**Category:** Ruby\
**Created:** [December 13, 2006, 12:20am UTC](https://www.ruby-forum.com/t/assigning-constant-as-an-unbound-dynamic-method/79185 "2006-12-13T00:20:45Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![asherwood](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c67d28/32.png) [@asherwood](https://www.ruby-forum.com/u/asherwood)\
**Post date:** [December 13, 2006, 12:20am UTC](https://www.ruby-forum.com/t/assigning-constant-as-an-unbound-dynamic-method/79185/1 "2006-12-13T00:20:45Z")

</div>

Disclaimer: I am new to Ruby, and am not a professional programmer. I  
work in Network Support, and have used Perl in the past for various  
scripting tasks. On a lark I picked up the ‘pickaxe’ book and wanted to  
try my hand at a Ruby program which will use SNMP to grab various stats  
from some network devices. I am using the SNMP module  
([http://snmplib.rubyforge.org/](http://snmplib.rubyforge.org/)) and it’s working fine.

In this module you can do a ‘get’ or a ‘walk’ on a device - basically  
the former grabs a single MIB value while the latter goes down the MIB  
tree to grab multiple values at once. I wanted to be able to dynamically  
call either get or walk depending on how my method was called. I know I  
could get around this by just coding two separate methods or the like,  
but I wanted to try to use dynamic method calls which seems to me to be  
more eloquent.

Looking at the examples in the book (p. 408 in 2nd edition), it appears  
I can do a .instance\_method(:) assignment, then bind  
that to a particular object, and then run call. For instance (from  
book):

str = “cat”  
ulen = String.instance\_method(:length)  
blen = ulen.bind(str)  
blen.call → 3

How I’d like to work that in my program is to define two constants  
(within a class called Device), which correspond to the two  
instance\_methods:

class Device  
…  
GET = SMTP::Manager.instance\_method(:get)  
WALK = SMTP::Manager.instance\_method(:walk)

and then:

def query\_device(mibval,type=GET,mib=RFC1213)  
data = []  
response = NOTSET  
begin  
SNMP::Manager.open(:Host =\> @ip.to\_s,  
:Community =\> @comm) do  
|manager|  
manager.load\_module(mib) unless (mib == RFC1213)  
mngr = type.bind(manager)  
response = mngr.call(mibval)  
end  
rescue  
etc…  
end

But when I try running this, I get the following error:

uninitialized constant Device::SMTP (NameError)

It appears to be adding my class onto the method name. I do have the  
necessary “require” in place (before I define the constants), and the  
SNMP::Manager.open command worked fine (before I make changes to get  
dynamic method calls to work). So I’m not sure why it’s adding my class  
name here but it doesn’t try to do that under query\_device.

If I can’t figure it out I will probably just go with passing a  
parameter to query\_device and use ‘catch’ to determine what method to  
call, but if someone could give me a clue as to what I’m doing wrong (or  
if what I’m trying to do is even possible), I’d appreciate it. Thanks.

---

<div class="post-metadata">

**Author:** ![asherwood](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c67d28/32.png) [@asherwood](https://www.ruby-forum.com/u/asherwood)\
**Post date:** [December 13, 2006, 12:27am UTC](https://www.ruby-forum.com/t/assigning-constant-as-an-unbound-dynamic-method/79185/2 "2006-12-13T00:27:08Z")

</div>

You could try adding :: infront of SMTP like  
::SMTP::Manager.instance\_method  
(:get)  
This tells ruby to look up one level for the constant.

j`ey

---

<div class="post-metadata">

**Author:** ![asherwood](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c67d28/32.png) [@asherwood](https://www.ruby-forum.com/u/asherwood)\
**Post date:** [December 13, 2006, 12:51am UTC](https://www.ruby-forum.com/t/assigning-constant-as-an-unbound-dynamic-method/79185/3 "2006-12-13T00:51:12Z")

</div>

Scott Strattner wrote:

> call either get or walk depending on how my method was called. I know I  
> ulen = String.instance\_method(:length)  
> WALK = SMTP::Manager.instance\_method(:walk)  
> manager.load\_module(mib) unless (mib == RFC1213)
> 
> –  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

You can just use the “send” method, which is defined in the base class  
Object from which all other classes are derived, e.g., mngr.send(:get)  
or mngr.send(:walk). So, in your case, pass the symbol :get or :walk  
as your type argument and then send() that to your mngr. See the pic  
axe pg. 574. Hope this helps some.

Ken

---

<div class="post-metadata">

**Author:** ![asherwood](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c67d28/32.png) [@asherwood](https://www.ruby-forum.com/u/asherwood)\
**Post date:** [December 13, 2006, 8:51pm UTC](https://www.ruby-forum.com/t/assigning-constant-as-an-unbound-dynamic-method/79185/4 "2006-12-13T20:51:26Z")

</div>

Scott Strattner wrote:

> How I’d like to work that in my program is to define two constants  
> def query\_device(mibval,type=GET,mib=RFC1213)  
> rescue  
> dynamic method calls to work). So I’m not sure why it’s adding my class  
> name here but it doesn’t try to do that under query\_device.

Try prefixing with ::, that will get you back to the root scope:

GET = ::SMTP::Manager.instance\_method(:get)

Tom
