Re: Using url_for in ActionMailer templates

Jeremy Kemper
2005-03-06T03:49:25Z

David Goodlad wrote:
> I am just adding some basic e-mail notices to my Rails app using
> ActionMailer, and have one small issue.  I want to provide a
> confirmation URL to users who sign up for an account.  I can obviously
> just hardcode the URL and append the confirmation code to it, but
I''d
> much rather be able to use something like:
>
> url_for(:controller => ''authentication'', :action =>
''confirm'',
> :confirmation_code => confirmation_code)
>
> and spit that URL out.  However, it seems taht within the context of
> the AM template, no controller is defined, so calling url_for()
> results in an error "undefined method `url_for'' for
nil:NilClass"...
> The stack trace indicates that it''s finding url_for() in
> action_view/base.rb no problem, but I think it''s then trying to
call
> url_for() on a controller object that isn''t set...
>
> Anyone seen this, and/or come across a solution?

Create the URL in your controller and pass it as a parameter to your
mailer action.  Example AuthenticationController signup and confirm:

def signup
  case @request.method

  # Show signup form.
  when :get
    @user = User.new

  # Create the user and send a confirmation email.  Use a before_create
  # callback on User to set unconfirmed status and to generate the
  # confirmation code.
  when :post
    @user = User.new(@params[''user''])
    if @user.save
      confirmation_url = url_for(:controller =>
''authentication'',
:action => ''confirm'', :confirmation_code =>
@user.confirmation_code)
      UserNotifier.deliver_signup_confirmation(@user, confirmation_url)
      flash[:notice] = ''Check yer email for the CODE''
      redirect_to :action => ''index''
    end
  end
end

# Accept a confirm link from email.  Show a manual entry form if
# anything goes wrong.
def confirm
  if code = @params[''confirmation_code'']
    if user = User.find_by_confirmation_code(code)
      user.status = User::CONFIRMED
      user.confirmation_code = nil
      user.confirmed_by = @request.remote_ip
      if user.save
        redirect_to :action => ''index''
      else
        @errors = user.errors
      end
    end
  else
    @errors = [''Enter the confirmation code exactly as you received
it.'']
  end
end

jeremy