What is the ruby best practice for handling a situation in which an object should fail to initialize owing to being passed invalid initialize arguments?
I realize that in ruby, duck typing means that we're not supposed to be overly concerned with what variable/parameters types but rather concern ourselves with how they behave. However, I am working in MacRuby which is bridged over the Cocoa Objective-C API and some of the Cocoa methods expect typed parameters.
For example, I have a ruby class that calls into the Objective-C API and must pass it an object of the NSURL class. It looks something like this:
class Alpha
attr_accessor :model
def initialize(hopefully_a_NSURL)
# bridged from Objective-C API
@model=NSManagedObjectModel.alloc.initWithContentsOfURL(hopefully_a_NSURL)
end # initialize
end
... and I would call it like so:
#bridged from Objective-C API
u=NSURL.fileURLWithPath(p)
a=Alpha.new(u)
puts "a=#{a.model}" # => a=#<NSManagedObjectModel:0x2004970e0
>
... which works nicely.
However, if I were to slip up:
a=Alpha.new("Whoops, a string not a NSURL" )
... it explodes messily with errors coming from the depths of the Objective-C API.
I can, of course, put in test that will prevent bad parameter for reaching the bridged objects:
class Alpha
attr_accessor :model
def initialize(hopefully_a_NSURL)
if hopefully_a_NSURL.class==NSURL
@model=NSManagedObjectModel.alloc.initWithContentsOfURL(hopefully_a_NSURL)
end
end # initialize
end
u=NSURL.fileURLWithPath(p)
a=Alpha.new("")
puts "a=#{a}" # => a=#<Alpha:0x200399160>
... but I still get a live instance back. I even tried returning nil from initialize but it seems that ruby insist on always returning a live instance.
Everything I've read says that type checking is heavily frowned upon in ruby but perhaps I will have to make an exception in the case of MacRuby. Would this be a good use of exceptions in ruby or is there a more elegant solution? I'm a noob in ruby so assume I am approaching the problem from the wrong perspective.