Rails3: переписать url_for для поддержки субдоменов, как расширить action mailer для использования такого url_for

Я беру код из поддомена 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  

Можно использовать модифицированные url_for в представлениях контроллеров. Но у меня проблемы с ActionMailer.

Я попытался использовать следующее:

class Notifier < ActionMailer::Base
  include UrlHelper
end

Но представления ActionMailer по-прежнему используют старый немодифицированный url_for из ActionDispatch::Routing::RouteSet.

Как лучше всего добавить новый url_for


person petRUShka    schedule 15.11.2010    source источник


Ответы (3)


Добавьте следующий код в файл app/helpers/url_helper.rb:

def set_mailer_url_options
    ActionMailer::Base.default_url_options[:host] = with_subdomain(request.subdomain)
end

и измените файл app/controllers/application_controller.rb, чтобы добавить:

before_filter :set_mailer_url_options

Источник

person Ryan Crispin Heneise    schedule 11.05.2011
comment
Не потокобезопасно, лучше использовать менее элегантное, но более надежное решение: actionmailer-with-request simonecarletti.com/blog/2009/10/actionmailer-and-host-value — подробности здесь - person Dmitry Polushkin; 08.09.2011

У меня есть решение этой проблемы, но я не думаю, что это лучший способ сделать это. Я пробовал и буду пытаться придумать лучшее решение, но вот что я сделал в своем шаблоне электронной почты. Причина, по которой я поместил это в шаблон электронной почты, заключается в том, что я использую Devise, но я надеюсь придумать что-то лучшее.

subdomain = @resource.account.subdomain
subdomain = (subdomain || "")
subdomain += "." unless subdomain.empty?
host = [subdomain, ActionMailer::Base::default_url_options[:host]].join

Теперь вы можете передать хост url_for следующим образом

user_confirmation_url(:host => host)
person bokor    schedule 18.11.2010
comment
Я хочу переписать url_for для рассылки действий. Похоже на контроллер действий - person petRUShka; 18.11.2010
comment
Ну, я в основном встроил приведенный выше код в уровень представления, поэтому я полагаю, что вы можете сделать то же самое в контроллере. Таким образом, вы можете переместить код UrlHelper в качестве методов в свой контроллер Notifier и попробовать его... опять же, не лучшее решение, но на данный момент это может вам помочь. Я все еще много работаю над этим, и если я что-то придумаю, я дам вам знать. Похоже, что ActionMailer почти требует от вас передачи хоста и не перезаписывает, как это делают контроллеры. - person bokor; 19.11.2010

Я обнаружил, что самым простым решением в Rails 3.0.x было создание хоста с субдоменом вручную в каждом URL-адресе в моих представлениях почтовой программы. Например:

Your account is here:

<%= account_url(:host => "#{@account.subdomain}.#{ActionMailer::Base.default_url_options[:host]}" %>

-- где ваша модель @account знает свой субдомен.

Это красиво и просто, потокобезопасно и изолированно. Вам не нужно загрязнять другие части вашей кодовой базы. И легко отказаться, как только вы перейдете на Rails 3.1.x, который, как я полагаю, должен обрабатывать все это автоматически.

person Andy Stewart    schedule 07.10.2011