Ruby on Rails: Best way to handle repeated error checking without goto?
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:
before_filter :check_errors
def example
regular code...
end
private
def check_errors
error checking...
end
Case statements
Use Case statements to improve your if
statements, 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_filters
whenever 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).
Here's a little secret: Exceptions are basically glorified gotos. Also, ruby has a catch/throw syntax, see: http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_exceptions.html
In your case, ask, is it really an error or just an undesirable condition. An error to me is when a belongs_to references a record that doesn't exist, but having an empty belongs_to isn't. This changes from situation to situation.
Looking at your comment above, I think I would be more inclined to add some private methods that set the instance variables and return true of false, and chain them together:
if load_model1 && load_model2 && load_model3 ... do regular page view else #render error page, use @load_error end private def load_model1 @model1 = .... if @model1.blank? # or nil? or whatever error condition @load_error="model 1 failed return false else return true end end def load_model2 ... end def load_model3 ... end
精彩评论