let’s say that I have this function in Rails (I have actually 😛 – eval is used because there will be third, fourth or more as class_number in the future) :
def all_profession_costs(class_number)
second = {'Wealth Ranger' => 1000, 'Wisdom Vacuum' => 1000, 'Life Leecher' => 1000, 'Dense Mass' => 1000}
costs = eval(class_number)
costs
end
This seems to be working fine now, but if I accidentally use ‘firsta’ for my class_number, the whole thing will likely collapse and maybe there will be a difficult error to spot.
So, now I’m thinking two things. I definitely want to check things as much as possible, but I don’t like putting things like “raise RuntimeError”, because it makes the code much uglier. And makes it run slower. Well, I suppose the latter is bearable, since checking means better code.
However, I don’t like ugly. I’m thinking of creating a separate ExceptionHandling module, in order to do validation stuff like that.
In this example, I would want to check whether class_number is ‘first’, ‘second’ or ‘third’.
Instead of something like:
raise RuntimeError unless ['first', 'second', 'third'].include?(class_number.to_s)
Maybe I could write a simple module (working probably like a Python decorator), that will make this thing better to read, what I think is more beautiful code, something like:
validates class_number, :inclusion => ['first', 'second', 'third']
Sort of like the standard model validator.
What do you think about that? Is that a good idea or not? How would you treat some error handling in Rails?
Validation – In the example given by you, you don’t have to raise an exception. You could simply return false if class_number is not either one of “first”, “second”, “third”. And check the response where the method gets called. This approach is the validation approach.
Exception – You raise exceptions when the error that may be cause is not due to bad user input but because something seriously went wrong in your logic, implementation or factors you don’t have control over.
These are not hard and fast rules though. They are more of a guideline that I usually follow.
In the above example, it depends on where the
class_numberis coming from. Is it coming from a user input? I would do a validation. If it is not supposed to come from a user input, I would raise an exception. Also, you don’t have to simple raise aRuntimeError. You can design your own exception class. In your case, something like,and do
unless [‘first’, ‘second’, ‘third’].include?(class_number.to_s)
raise InvalidClassNumber, “Class number can either be ‘first’, ‘second’ or ‘third’. We got #{class_number.to_s}”
end
Where you call this method, you can rescue it and do whatever you need to do handle it.
Custom exception classes give you the flexibility to handle precisely those exceptions that you are expecting, instead of handling a generic exception like
RuntimeError. You can have as many exception classes as you need in your application. You can even give them a namespace using::.Profession::InvalidClassNumber < RuntimeError.