From: Brian Candler Date: 2009-12-09T19:28:24+09:00 Subject: Re: Newbie question: what exceptions are thrown by FTP class Simon Morgan wrote: > Really I’m after something along the lines of what Java’s JavaDoc might > give which lists the thrown exceptions and the reasons why If the author includes that in the API documentation, then you'll have it; if the author doesn't, then I'm afraid you won't. In the case of Net::FTP you can see that the author decided to remove all of the exception classes from the documentation (:stopdoc:), presumably to avoid cluttering it up. > or if there is a tool that can generate this > sort of info? The documentation you are currently looking at is generated via rdoc, which basically extracts comments and method signatures from the code. However, Ruby is a very dynamic language and it's not possible to determine from static source analysis which exceptions may or may not be thrown. This isn't just nitpicking. It's quite common in Ruby to pass around and use objects of 'unrelated' classes at runtime: 'unrelated' in the sense of not sharing a common ancestor class other than Object. Rather, they implement the same 'duck-type' interface. In the case of Net::FTP you might arrange that it uses a SOCKSSocket instead of a Socket, for example, and SOCKSSocket could have its own set of exceptions that it raises (SOCKS authentication error, for example). You could argue that if it raises a different exception under similar circumstances then that's a duck-type violation - the duck goes honk instead of quack. Unfortunately, this aspect of duck-typing is often overlooked. Anyway: there's no formal "interface" in ruby, which means objects can implement whatever methods they feel like, and raise whatever exceptions they feel like, and change their behaviour at runtime whenever they feel like. You probably find this dirty. However it's what enables all sorts of goodness, such as ActiveRecord being able to define model classes at runtime based on the columns in your database. The advice I give to you is: relax, and have good unit test coverage. > I did try looking at the source however the problem is just the time it > takes to go through everything to find what throws what It's pretty obvious in this case. All you have to do is look for classes of which Exception is an ancestor (or StandardError or RuntimeError), and they are all bundled together at the top of the file. It's just convention, rather than rigidly enforced. > and this is > fairly error-prone and time-consuming; e.g. if I call nlst() without a > network connection, the exception is thrown from nlst > retrlines > > voidcmd > putline, which is throwing an error from a call to > TCPSocket.write... Indeed. Hence my advice to be generic in your rescue strategy. But *why* would you be calling nlst on a connection which isn't open? Isn't that a programmer error, and therefore you shouldn't be catching the exception at all? > -- although I guess I may still need to search through all the code to > find the different IOError and SystemCallError instances, to see if I’d > want to treat them differently. Those are pretty low-level - for example, Errno::ECONNREFUSED is a subclass of SystemCallError, so to determine all possible exceptions when opening a socket you'll really need to look at the documentation for the unix open(2) call and the possible errno values which it can set. It has to be said that Ruby's own core documentation is a long way from complete. Regards, Brian. -- Posted via http://www.ruby-forum.com/.