Click to See Complete Forum and Search --> : Ruby - chdir()


EyesWideOpen
06-07-2001, 05:09 PM
I don't suspect that there are too many Ruby peeps hanging around here but I figured I'd post anyway. ;)

I can't figure out why the chdir isn't working here. :confused:

Any ideas?


#!/usr/bin/ruby

require 'net/ftp'

# declare the name of the ftp server
server = "ftp.cpan.org"

print "Establishing connection to #{server}...\n"

# include module Net so the FTP class can be accessed
include Net

# create a ftp object so the FTP class methods may be accessed;
# provide the name of the ftp server to connect to
ftp = FTP.new("#{server}")

# connect to the ftp server using anonymous login
# make sure the login succeeded before continuing
# exit with a print statement if the login failed
if( ! ftp.login("anonymous", "me\@here.com") )
print "Login failed.\n\n"
exit
end

# change working directory (chdir) to /pub/CPAN
# make sure the call to chdir() succeeds
# exit with a print statement if chdir() failed
if( ! ftp.chdir('/pub/CPAN') )
print "Call to method chdir() failed.\n\n"
exit
end

# get the present working directory (pwd) and store it in a variable
pwd = ftp.pwd

print "#{pwd} is current directory.\n"

# download the welcome.msg file from the ftp server
# rename the file and store it locally
if ( ftp.gettextfile("welcome.msg", "README.cpan") )
print "Retrieving file...\n"
else
print "Unable to retrieve file\n\n"
end

print "Closing connection to #{server}...\n"

# close the FTP connection
ftp.quit

print "Connection closed.\n"

klamath
06-08-2001, 01:56 AM
I guess I'm one of the few other Ruby fans (other than yourself). Luckily, Ruby is so good we don't need lots of people to solve your problems ;-)

The problem you were having is that FTP#chdir is supposed to return nil -- if there is an error, it throws an exception. So the call to #chdir was succeeding -- but your code was interpreting the return value (nil) as an error, when in fact it meant nothing.

The only reason FTP#login wasn't failing is that it happens to return the welcome message when you connect -- so the return value is non-nil and your check works.

So I decided to basically rewrite your code. I made the following changes:

1) Added proper error handling and removed the faulty return status checks. Ruby has quite classy error handling, if you let it.

2) Changed calls to print to puts -- it sticks a newline in there automatically

3) Removed ultra-verbose comments. Too many comments are BAD! (really, they are). The reason is that commenting excessively makes the code more expensive and laborious to change -- not only do you need to change the code, you've gotta update the docs too. When the code does something trivial (like 'FTP.login(...)'), the user can just lookup the documentation for the method you're calling and figure out (very easily) what you're trying to do. Basically, you should write your code clearly enough that comments are only rarely necessary -- and when they are, you normally your comments should be things like 'I chose this algorithm because ...' or 'FIXME: fix this bug ...', etc -- not explaining what a specific method does, but the thinking behind the design of a specific section. If you're using a language like C, then you'll probably need to comment to explain things -- but with a language like Ruby, properly written code is clear enough that comments just slow people down.

4) Removed the console status reporting (mostly). I just wanted it out of the way, feel free to add it back in again

5) Simplified the FTP constructor -- if it wants a string, just give it a string, no need to quote and then interpolate

6) Changed constants into true $CONSTANTS. This is marginally better. I also moved the filenames from the code into constants

7) Changed all double-quotes to single-quotes when you won't interpolating anything -- I'm just picky ;-)

8) FYI, they're no need to escape a '@' in double-quoted strings: Ruby only interpolates #{}, so a '@' is treated normally. Try
ruby -e 'puts "@home"'

9) Corrected the filenames. The files you were trying to fetch were non-existent

10) Changed FTP#quit to FTP#close -- AFAICT, FTP#quit doesn't exist

11) Changed it to use passive FTP: I'm behind a firewall so active FTP doesn't work for me.

So the code is below. Knowing how much UBB sucks, it will probably screw up the indenting, so email me (klamath@home.com) if you'd like a 'proper' copy


#!/usr/bin/ruby -w

require 'net/ftp'

$SERVER = 'ftp.cpan.org'
$FILE = 'README'
$LOCAL_FILE = 'README.cpan'

include Net

begin
ftp = FTP.new($SERVER)
ftp.passive = true

ftp.login('anonymous', 'me@here.com')

ftp.chdir('/pub/CPAN')

puts "#{ftp.pwd} is the current directory."

ftp.gettextfile($FILE, $LOCAL_FILE)

rescue FTPError
puts "Error encountered: #{$!}"
raise

ensure
ftp.close() unless ftp.nil?
end

EyesWideOpen
06-08-2001, 09:34 AM
Wow, thanks alot for the help. I appreciate it. ;)

Originally posted by klamath:
3) Removed ultra-verbose comments.

I realize that the comments were overkill but they were mainly for the benefit of newbies for the CCAE (http://codeexamples.org) where you can choose to view/not view comments if you so desire.

Speaking of CCAE, I can't in good consciousness submit this now because you spiced it up for me (not that I'm complaining)! So how about you submit this to the CCAE and give them their first Ruby example?!


9) Corrected the filenames. The files you were trying to fetch were non-existent

This is going to sound wacky but the welcome.msg file was there yesterday. I've noticed that things (directory structure, files, etc) on the CPAN ftp server change often -- or maybe there are multiple servers??? The file exists on www.cpan.org (http://www.cpan.org) as well.


10) Changed FTP#quit to FTP#close -- AFAICT, FTP#quit doesn't exist

There is a quit method. If you look at the ftp.rb file in the lib/1.6/net directory of your Ruby install you'll see the following function:


def quit
voidcmd("QUIT")
end



Thanks again for all of your help.

http://www.tinyminds.com/images/forum/avatar/019.gif

klamath
06-08-2001, 11:57 AM
So how about you submit this to the CCAE and give them their first Ruby example?!


Sure, I'll comment it and send it in sometime today. Thanks for the suggestion.

There is a quit method.

Hmmm... strange -- it's not documented in "Programming Ruby" (although most of the rest of the public methods are). Weird...

Thanks again for all of your help.

Sure, no problem.