Reputation: 111030
I'm building a method that ingests incoming email, and processes the email. Along the way there are a lot of things that could prevent the email from being processes successfully. The wrong reply-to address, the wrong from address, an empty message body etc..
The code is full of Switch Statements (case/when/end) and If statements. I'd like to learn a smarter, cleaner way of doing this. Additionally, a way to can track an error and at the end have one location where it emails back the user with an error. Is something like this possible with rails?
@error = []
Case XXX
when xxxx
if XXXXX
else
@error = 'You don't have permission to reply to the xxxxx'
end
else
@error = 'Unfamilar XXXX'
end
Then something at the end like...
If @errors.count > 0
Send the user an email letting them know what went wrong
else
do nothing
end
Thanks for the help here. If you know of any other tutorials that would teach me how to write logic like the above smarter, that'd be great. Right now I have case/if statements going 3 levels deeps, it's hard to keep it straight.
Thanks
Upvotes: 1
Views: 687
Reputation: 4403
I suggest using Exceptions. Start with this tutorial, then use Google, trial and error to go from there.
Edit: In more complex cases, exceptions may not be the right tool. You might want to use validator functions instead, for example (see other answers), or you could just return early instead of nesting ifs, e.g.:
unless sender_valid?
@error = "Sender invalid"
return
end
unless subject_valid?
@error = "Invalid command"
return
end
# normal no-errors flow continues here...
Upvotes: 2
Reputation: 14977
First, I would just assign a symbol to each error message as a simple hash:
ErrorsDescription = {
:first => "First error",
:second => "Second error",
...
}
And use symbols instead of strings.
Then, your if and switch statements. Basicaly I can't really help you, because I don't see what kind of condition statements you have. What are you checking? Why do you have 3 level deep conditions? Probably you can write it simpler using if and switch - so this is my first answer to this issue. Another solution may be writing simple methods to improve readability, so you can write like this:
if @email.has_wrong_reply_to_address?
@errors << :wrong_reply_to_address
else
...
end
Also, as @mpapis suggested, you can use Rails build in validation system, but not as ActiveRecord
but as ActiveModel
. Here you have some examples how to do it and how it works (also take a look here). Of course you may need to write custom validations, but they are just simple methods. Once you do all above job, you can just use:
@email.valid?
And if it is not, you have all errors in hash:
@email.errors
Just as in ordinary ActiveRecord
object.
Then you may extend your Emial
class with send_error_email
method which sends an email if there was an error.
EDIT:
This is about new information you attached in comment.
You don't have to use nested ifs and switch here. You can have it looking like this:
def is_this_email_valid?
if !email_from_user_in_system?
@errors << :user_not_in_system
return false
end
if comment_not_exists?
@errors << :comment_not_exists
return false
end
if user_cannot_comment_here?
@errors << :permision_error
return false
end
...
true
end
Then you can use it:
if [email protected]_this_email_valid?
@email.send_error_mail
end
Upvotes: 3
Reputation: 53178
Is it possible to map your message to a model ? then all the if/switch logic would be validations and automatically handled by rails. Good starting point is active record validations guide
Also worth reading is action mailer guide
Upvotes: 1
Reputation: 9857
You could throw an error when something is not right. Then catch it at the end of your method.
http://phrogz.net/programmingruby/tut_exceptions.html
To make your code more readable and not have a lot of switch and if/then statements, you could create separate methods that validate certain aspects and call them from your main error-checking method.
Upvotes: 1