You are right to say the following:
File.open("/etc/passwd", "r") do |passwords|
while pw_entry = passwords.gets
user, pw, uid, gid, gecos, home, shell = pw_entry.split(/:/)
print uid
end
end
is nearly equivalent to:
require 'etc'
Etc.passwd { |user|
print uid
}
In fact these two ruby snippets will produce exactly the same result.
The only difference is that the last method uses another way of iterating through the passwd file. It uses a closure which receives a parameter user
as an input. This user
is the only user
that exists in the scope of the anonymous function.
Now, about your problem with the difference between your two methods:
When you reference variables inside a ruby closure that don't belong to the closure itself (i.e. outer variables) the reference to the symbol of that variable within that (outer) scope is stored inside the closure's code. Since in the first method you reuse the same symbol within the same scope, uid
references the last known value of uid
when the closure's code is called after all facts have been added. This is known as the outer variable trap.
One way to work around this problem is by having each uid
exist in its own scope.
def addUserFact(passwd_entry)
user, pw, uid, gid, gecos, home, shell = passwd_entry.split(/:/)
Facter.add("user_" + user) do
setcode do
uid
end
end
end
File.open("C:/cygwin/etc/passwd", "r") do |passwords|
while pw_entry = passwords.gets
addUserFact(pw_entry)
end
end