FYI I'm using 1.0.9, so if you are on the 3.0 branch things might be a little different. But...
First I changed Devise::Models:Recoverable:ClassMedhods#send_reset_password_instructions
To:
def send_reset_password_instructions(attributes={})
recoverables = find_or_initialize_with_error_by(:email, attributes[:email], :not_found,true)
unless recoverables[0].new_record?
recoverables.each {|r| r.prepare_to_reset_password}
::DeviseMailer.deliver_reset_password_instructions(recoverables)
end
recoverables
end
Then I modified Devise::Models:Recoverable#send_reset_password_instructions to:
# Resets reset password token and send reset password instructions by email
def send_reset_password_instructions
prepare_to_reset_password
::DeviseMailer.deliver_reset_password_instructions(self)
end
And added Devise::Models:Recoverable#prepare_to_reset_password:
# Prepares for password reset
def prepare_to_reset_password
generate_reset_password_token!
end
Then I edited: DeviseMailer#setup_mail to:
def setup_mail(records, key)
if records.is_a?(Array)
record = records[0]
else
record = records
end
scope_name = Devise::Mapping.find_scope!(record)
mapping = Devise.mappings[scope_name]
subject translate(mapping, key)
from mailer_sender(mapping)
recipients record.email
sent_on Time.now
content_type Devise.mailer_content_type
body render_with_scope(key, mapping,
mapping.name => record, :resource => records)
end
Devise::Models#find_or_initialize_with_error_by to:
# Find an initialize a record setting an error if it can't be found.
def find_or_initialize_with_error_by(attribute, value, error=:invalid,many = false)
if value.present?
conditions = { attribute => value }
records = find(:all, :conditions => conditions)
else
records = []
end
if !records.empty?
records = records[0] if !many
else
record = new
if value.present?
record.send(:"#{attribute}=", value)
else
error, skip_default = :blank, true
end
add_error_on(record, attribute, error, !skip_default)
many ? records << record : records = record
end
records
end
PasswordsController#create to:
# POST /resource/password
def create
@resources = resource_class.send_reset_password_instructions(params[resource_name])
self.resource = @resources.is_a?(Array) ? @resources[0] : @resources
if resource.errors.empty?
set_flash_message :notice, :send_instructions
redirect_to new_session_path(resource_name)
else
render_with_scope :new
end
end
And finally the devise_mailer/reset_password_instructions.html.erb to:
<% if @resource.size == 1%>
<p>To reset your password, please click the link below (or copy and paste it into your browser):</p>
<%= link_to 'Change my password', edit_password_url(@resource[0], :reset_password_token => @resource[0].reset_password_token) %>
<% else %>
<p>Multiple accounts are associated with your e-mail address.</p>
<p>To reset the password for one of the accounts, click on the link for that account.</p>
<% for resource in @resource %>
<p><%= link_to 'Change my password for account: '+resource.user_name, edit_password_url(resource, :reset_password_token => resource.reset_password_token) %></p>
<% end %>
<% end %>
<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>