Rails3: rewrite url_for for subdomain support, how to extend action mailer to use such url_for
I take code from Subdomain RailsCast
module UrlHelper
def开发者_开发知识库 with_subdomain(subdomain)
subdomain = (subdomain || "")
subdomain += "." unless subdomain.empty?
[subdomain, request.domain, request.port_string].join
end
def url_for(options = nil)
if options.kind_of?(Hash) && options.has_key?(:subdomain)
options[:host] = with_subdomain(options.delete(:subdomain))
end
super
end
end
class ApplicationController < ActionController::Base
include UrlHelper
end
It is ok to use modified url_for
in views of Controllers. But I have trouble with ActionMailer.
I tried to use following:
class Notifier < ActionMailer::Base
include UrlHelper
end
But ActionMailer views still use old unmodified url_for from ActionDispatch::Routing::RouteSet.
What is the best practice to add new url_for
Add the following code to the file app/helpers/url_helper.rb:
def set_mailer_url_options
ActionMailer::Base.default_url_options[:host] = with_subdomain(request.subdomain)
end
and modify the file app/controllers/application_controller.rb to add:
before_filter :set_mailer_url_options
Source
I have a solution for this issue but I don't think it is still the best way to do it. I have tried and will still try to come up with a better solution but here is what I have done in my email template. The reason I put this in the email template is because I'm using Devise, but I'm hoping to come up with something better.
subdomain = @resource.account.subdomain
subdomain = (subdomain || "")
subdomain += "." unless subdomain.empty?
host = [subdomain, ActionMailer::Base::default_url_options[:host]].join
You can pass the host to the url_for now like this
user_confirmation_url(:host => host)
I found the simplest solution on Rails 3.0.x was to construct the host-with-subdomain manually in every URL in my mailer views. For example:
Your account is here:
<%= account_url(:host => "#{@account.subdomain}.#{ActionMailer::Base.default_url_options[:host]}" %>
-- where your @account
model knows its subdomain.
This in nice and simple, threadsafe, and isolated. You don't need to pollute other parts of your codebase. And it's easy to back out once you move to Rails 3.1.x, which should handle all this automatically I believe.
精彩评论