In languages that have goto, I like to create an error block at the end of a function (after return) and then when I do error checking within the function, I can just be concise and goto the error handler within each check. As I understand it, this is the one valid use of goto that isn’t considered bad practice.
Example in pseudocode:
def example
if (x) goto error
do something
if (y) goto error
do something
If (z) goto error
do something
return
label 'error'
log "error occurred"
begin
redirect_to :back
rescue
redirect_to root_url
end
return;
end
As you can see, in this case, my error block is as long as the function itself, and repeating it 3 times would double the size of my code, and not be very DRY. However, it seems that Ruby doesn’t support goto, or at least if it does, as best as I can tell from looking on Google, it’s some sort of possibly joke library labeled evil.
Therefore, what are people doing in Ruby in order to handle repeated error checking where the same result should occur in each error?
Callbacks
You should transfer many of these errors into your models, using Callbacks. These apply to errors that are relevant to actions that involve records in your database, i.e. checking whether a data input is appropriate.
Filters
Use before_filters and after_filters to check for errors, especially when you need to perform these checks on multiple controller actions. An example:
Case statements
Use Case statements to improve your
ifstatements, particularly when you have multiple checks involved.Prioritizing the above
Use callbacks in your models whenever you can and definitely whenever data saving/updating/validation is involved.
Use
before_filterswhenever the code is to be reused across multiple actions (and in my opinion, always whenever you have involved error checking like this).If you need these checks to occur only once, in this controller action alone, that do not involve records being changed, simply rewrite your code in a valid case statement (but my recommendation would still be to transfer to a before_filter).