Wednesday, March 12, 2008

Begin Rescue Else End

So today I was working on a project. This project will be an admin interface for an application that has already been running for a while(which was written in PHP). So I am having to use a legacy database(tutorial coming soon for making admin interface for a legacy DB!) Anyway, I have an employee, and a department. The employee references which department he is in by the ID. However, some employees have an ID that is not used in the department table(department got deleted at some point, never existed, who knows?).


In my employee model, I am making a function to take the department id from the employee tables(thisdept), and look up the number in the department table to get the name of the department, all pretty standard stuff.


Here is what I tried first:



def deptname
dept = Department.find(thisdept)
dept.name
end



ActiveRecord::RecordNotFound in Employees#index

Showing vendor/plugins/active_scaffold/frontends/default/views/_list_record.rhtml where line #10 raised:

Couldn't find Department with ID=13


So we are going to need something along the lines of a try - catch. Ruby's equivalent is the begin-rescue-else-end. Begin is the code that might throw an error. Rescue is the code to excute if there is an error. Else is executed if there is no error. You can also add an ensure block, which will be run after everything, regardless. Here is my fix:




def deptname
begin
dept = Department.find(thisdept)
rescue
"No Department"
else
dept.name
end
end

Works like a charm! See you next time.

9 comments:

Derek Berner said...

Hey man --

How about this?

def deptname
Department.find(thisdept).name rescue "No Department"
end

Inline rescues are my friend ;-)

rledge21 said...

Awesome, didn't know about inline rescues, thanks for the tip.

Anonymous said...

thats more like it

meceo said...

I don't like rescue in this example, that will catch all exceptions, no matters what went wrong

dep = Department.find_by_id(thisdept)
dep.present? ? dep.name : "No Department"

no rescue required

Soro said...

rescue ROX! And the inline use is more 'polite' I must say.

@meceo argument is silly "I don't like rescue in this example, that will catch all exceptions, no matters what went wrong"
Isn't that the whole point?!

What if someone just destroyed the dept. he was looking for?

Anonymous said...

@Soro
The point is that dependent on the error you might want to do more than only print "No Department" to the user.
Maybe you additionally want to fire a systems management event if (and only if) you have a db error.

Greetings
Heinz

Anonymous said...

Thank you! Helped me get some safety into my application. I am catching all those bad people trying to grab orders they shouldn't be seeing.

Have a nice life!

Michael

meceo said...

@soro please have a look on this example scenario:
Your application gives information about departments in your company. You are asked by your boss to give a telephone number to HR department. You check in application but unfortunately your database has problems, let say some locks on department table make it unreadable or connection pool number exceeded (many things can go wrong). What do you see? You see "No Department" and you have no idea that HR department exists but your application are having exceptions. With such wonderful information "No HR department in our company" you get back to your boss. What do you think will happen next? Is your application reliable? Are your application users reliable? (in this case user is you).

You should always rescue only exceptions that you are expecting (TimeoutException etc)

I hope you get a point.

BR, meceo

niroa said...

What namely you are writing is a horrible mistake.