views:

67

answers:

1

Hi,

After I have created a serious bunch of classes (with initialize methods), I am loading these into IRb to test each of them. I do so by creating simple instances and calling their methods to learn their behavior. However sometimes I don't remember exactly what order I was supposed to give the arguments when I call the .new method on the class. It requires me to look back at the code. However, I think it should be easy enough to return a usage message, instead of seeing:

ArgumentError: wrong number of arguments (0 for 9)

So I prefer to return a string with the human readable arguments, by example using "puts" or just a return of a string. Now I have seen the rescue keyword inside begin-end code, but I wonder how I could catch the ArgumentError when the initialize method is called.

Thank you for your answers, feedback and comments!

+4  A: 

It is possible to hook into object creation by overriding the Class#new method e.g.

class Class
  # alias the original 'new' method before overriding it
  alias_method :old_new, :new
  def new(*args)
    return old_new(*args)
    rescue ArgumentError => ae          
      if respond_to?(:usage)
        raise ArgumentError.new(usage)
      else 
        raise ae
      end
  end
end

This overriden method calls the normal new method but catches ArgumentError and if the class of the object being created provides a usage method then it will raise an ArgumentError with the usage message otherwise it will reraise the original ArgumentError.

Here is an example of it in action. Define a Person class:

class Person
  def initialize(name, age)
  end

  def self.usage
    "Person.new should be called with 2 arguments: name and age"
  end
end

and then try and instantiate it without the required arguments:

irb(main):019:0> p = Person.new
ArgumentError: Person.new should be called with 2 arguments: name and age
    from (irb):8:in `new'
    from (irb):22

Note: this isn't perfect. The main problem being that it is possible that the ArgumentError we catch has been caused by something other than an incorrect number of arguments being passed to initialize which would lead to a misleading message. However it should do what you want in most cases.

mikej
I like both answers, especially that I know that you can override the new method / class constructor. However the second one is clearly simplistic enough to serve my needs. Thank you so much!
Shyam