Can anyone tell me why my code isn't working?

A

Adam Penny

Hi there,

For some reason the get_mac_by_printer(host_name) method isn't working.
All the other bits work, but I have a feeling that I'm running into a
problem with variables defined within blocks, but I'm at a loss as to
how to negotiate it. The resulting mac is returning as nilClass and it
definitely isn't nil! Code as follows:

#Class for handling the plist file.
class PlistHash
def initialize(path)
@path=path
@plist_hash=Plist::parse_xml(@path)
end

def get_mac_by_host(host_name)
servers=@plist_hash['servers'].each do |s|
mac=s['mac'] if s['name']==host_name
return mac
end
end

def get_mac_by_printer(printer_name)
printers=@plist_hash['printers']
printers.each do |v|
host=v['host'] if v['name']==printer_name
return host
end
mac=get_mac_by_host(host)
return mac
end

def get_broadcast_ip
broadcast_ip=@plist_hash['broadcastIP']
end
end

Thanks for your help,

Adam
 
A

Adam Penny

Solved it.

I came up with this solution to force the each loops to return a
specific value from the array of hashes. Explicitly returning the value
of the block each block did the trick. Still don't think I've got the
hang of variable scope though. :-(

class PlistHash
def initialize(path)
@plist_hash=Plist::parse_xml(path)
end

def get_mac_by_host(host_name)
servers=@plist_hash['servers'].each do |s|
return s['mac'] if s['name']==host_name
end
end

def get_host_by_printer(printer_name)
printers=@plist_hash['printers']
printers.each do |v|
return v['server'] if v['name']==printer_name
end
end
def get_mac_by_printer(printer_name)
host=self.get_host_by_printer(printer_name)
return self.get_mac_by_host(host)
end

def get_broadcast_ip
broadcast_ip=@plist_hash['broadcastIP']
end
end
 
B

Brian Candler

Adam said:
For some reason the get_mac_by_printer(host_name) method isn't working.
All the other bits work, but I have a feeling that I'm running into a
problem with variables defined within blocks, but I'm at a loss as to
how to negotiate it.

No, nothing to do with variable scoping.
The resulting mac is returning as nilClass and it
definitely isn't nil! Code as follows: ...
def get_mac_by_host(host_name)
servers=@plist_hash['servers'].each do |s|
mac=s['mac'] if s['name']==host_name
return mac
end
end

It definitely *is* nil.

Note that your 'each' loop will onlyever run for one iteration, since
'return mac' will always return from the enclosing method
(get_mac_by_host) during the first iteration. So, unless the passed
host_name happens to match the first entry of @plist_hash['servers'],
then the assignment

mac = s['mac'] if s['name']==host_name

will not be executed (because it's qualified by "if ... false condition
..."), so the value of the local variable 'mac' will be nil.

To demonstrate:

if 1 == 2
foo = "oops"
end
puts foo # nil

So your loop is similar to:

def mycode
(1..5).each do |v|
res = v if v == 3
return res
end
end
puts mycode # nil

You could fix this by changin "return res" to "return res if v == 3", or
"return res if res", but more simply

def mycode
(1..5).each do |v|
return v if v == 3
end
end
puts mycode # 3
 
J

Jesús Gabriel y Galán

You could fix this by changin "return res" to "return res if v == 3", or
"return res if res", but more simply

def mycode
(1..5).each do |v|
return v if v == 3
end
end
puts mycode # 3

Also check Enumerable#find:

irb(main):002:0> a = [{:name => "a", :value => 3}, {:name => "b",
:value => 4}, {:name => "c", :value => 10}]
=> [{:value=>3, :name=>"a"}, {:value=>4, :name=>"b"}, {:value=>10, :name=>"c"}]
irb(main):003:0> a.find {|s| s[:name] == "b"}
=> {:value=>4, :name=>"b"}

So, you method could be done as:

def get_mac_by_host(host_name)
s = @plist_hash['servers'].find {|s| s['name'] == host_name}
return s['mac'] if s
nil
end

(not tested). Hope this helps,

Jesus.
 
B

Brian Candler

Just to make the semantics of 'return' clearer:

def foo
1
return 2
raise "Never get here"
3
end

puts foo # 2

return doesn't cause store a value for returning later; it causes the
method to return immediately, returning that value.
 

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,995
Messages
2,570,233
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top