assigning constant as an unbound dynamic method

S

Scott Strattner

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/) 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 <Class>.instance_method:)<method name>) 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.
 
C

coachhilton

Scott said:
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/) 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 <Class>.instance_method:)<method name>) 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.

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
 
T

Tom Werner

Scott said:
Looking at the examples in the book (p. 408 in 2nd edition), it appears
I can do a <Class>.instance_method:)<method name>) 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.
Try prefixing with ::, that will get you back to the root scope:

GET = ::SMTP::Manager.instance_method:)get)

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top