The most recent I've just written tonight.
I needed a way to send myself an email containing the cause of the error when a user tried to change their profile, reset password, etc, and the update failed due to a validations error.
So I wrote a little helper method for my application_helper.rb:
def human_readable_errors(errors, col_names)
arr = Array.new
for name in col_names
if errors[name] && errors[name].is_a?(Array)
arr << name + ": {" + errors[name].compact.join(', ') + "}"
elsif errors[name]
arr << name + ": {" + errors[name].to_s + "}"
end
end
return arr.to_sentence
end
Now in my mailer model I can send emails with this lovely line:
def profile_update_failure(user, original)
@recipients = "no-spam@peterboling.com"
@from = "Admin "
@subject = "[ERROR] Profile Update Failure (#{user.login})"
@sent_on = Time.now
@content_type = "text/plain"
@body = {
:name => user.name,
:login_name => user.login,
:message => "Profile was NOT updated.\n\r" + get_object_diff(user, original),
:date => Time.now.to_date.to_s,
:time => Time.now.strftime("%I:%M %p"),
:errors => "Profile update failed because:\r\n\r\n" + human_readable_errors(user.errors, User.column_names)
}
end
And I will get an email with some lines like this:
Resetting password failed because:
login: {is too short (minimum is 1 characters), can't be blank, can't be changed ... ever} and last_name: {can't be blank}"
You may have noticed the get_object_diff method call. That's the easiest way to see if the user has changed anything, and what EXACTLY they changed. This way I have a record of all the changes in email (which I prefer to storing this sort of thing in a database. I use the email history as the record of what changed when.)
So I put the get_object_diff method in my mailer_helper.rb because I only use it when mailing... (Oh and the object class must be acts_as_comparable)
#Object class must be acts_as_comparable
def get_object_diff(first, second)
i = 0
j = 0
diff = first.differences(second).to_a
d = String.new
up = String.new
for p in diff
i += 1
if p.is_a?(Array)
for s in p
j += 1
if !s.is_a?(Array) && s != :updated_at
d += s.to_s.humanize + ": "
elsif !s.is_a?(Array) && s == :updated_at
up += s.to_s.humanize + ": "
elsif p[0] != :updated_at
d += s.reverse.to_sentence(:connector => 'changed to', :skip_last_comma => true)
d += "\n\r"
elsif p[0] == :updated_at
up += s[0].to_s
up += "\n\r"
else
d += "and " + s[0].to_s
d += "\n\r"
end
end
j = 0
end
end
return d + (up || "")
end
The output of this method generates somthing like this example:
The following things were updated in your profile:
City: Pickadilly changed to South Bend
Address1: 597 N Fizzling Sticks Ave #42 changed to 653 E 6th Ave
Postal code: 47304 changed to 22222
Phone: 555-555-1234 changed to
Email: no-spam@peterboling.com changed to please-spam@yahoo.com
State: MO changed to NY
Updated at: Tue Aug 28 14:51:36 UTC 2007
If you did not initiate this request, please notify us immediately.


0 hashings:
Post a Comment