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

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

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. :frowning:

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

Adam P. wrote:

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

On Tue, Oct 21, 2008 at 9:59 AM, Brian C. [email protected]
wrote:

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.

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.