Reputation: 38349
I'm having a hard time figuring out the "Rails Way" to add a email confirmation URL to a mailer.
I'm opting not to do this purely RESTfully because, well, it's difficult with text email because they can't PUT
requests.
so here's my routes.rb: get 'confirm/:id' => 'Confirmations#confirm'
and in my mailer I'd like to put email_confirm_url(@user.email_token)
where I want the URL to occur.
I created a helper:
#app/helpers/confirmations_helper.rb
module ConfirmationsHelper
def email_confirm_url(token)
"/confirm/#{token}"
end
end
this all works, sort of, except when I call email_confirm_url(@user.email_token)
…
I literally get: "/confirm/abcdefg…
"
When what I want is: http://myhostname/confirm/abcdefg…
Or in development: http://localhost:3000/confirm/abcdefg…
How can I make my URL helper behave more like the built in <resource>_path
and <resource>_url
helpers in Rails? though realistically I suppose I really only need _url
.
#Edit: I have this in my environment config:
#config/environments/development.rb
...
config.action_mailer.default_url_options = { :host => "localhost:3000" }
Upvotes: 5
Views: 3916
Reputation: 2134
I recently wrote a helper to convert my _path
method into a _url
method.
Rails uses ActionDispatch::Http::URL.full_url_for
to produce the _url
methods, and passes in Rails.application.routes.default_url_options
to set the host
, port
, and protocol
.
This means you can generate a URL from a given path with
ActionDispatch::Http::URL.full_url_for(Rails.application.routes.default_url_options.merge(path: path))
My work in progress helper looks like:
def self.url_helper(route_name)
define_method("#{route_name}_url") do |*args|
path = public_send(:"#{route_name}_path", *args)
options = Rails.application.routes.default_url_options.merge(path: path)
ActionDispatch::Http::URL.full_url_for(options)
end
end
This could then be used in combination with your path helper to build an email_confirm_url
method:
url_helper :email_confirm
def email_confirm_path(token)
"/confirm/#{token}"
end
Upvotes: 1
Reputation: 11689
What about using an already existing url plus concatenation? I.e. you can use root_path
and root_url
, then you concatenate and the behavior is exactly the same as rails!
For example you can do this:
def mystrangemethod_url(option1, option2)
"#{ root_url }/#{ option1 }/#{ option2 }"
end
And you are done. Easy and the only requirement is set set your root path in routes.rb. Also with the option you have set in development.rb, it will work also in mailers too.
Upvotes: 0
Reputation: 1174
In order to access the request object you should implement this function in the controller for your mailer and pass it to the template with a variable.
app/mailers/emailer.rb
@tracking_url = "http://#{request.host}:#{request.port}/confirm/#{token}"
app/view/emailer/template_name.html.erb
<%= link_to 'name', @tracking_url %>
Upvotes: 0