Как да включите ruby ​​on rails производствена точка за монтиране в url_helpers за имейл?

tl;dnr: Връзките към страниците ми са добри, но връзките, преобразувани в текст извън страницата (имейл), нямат точката за монтиране на производственото приложение.

подробност: Моето приложение RoR използва малко по-различни URL адреси в dev и production: в dev обектът от най-високо ниво е ресурсният модел:

http://localhost:3000/ENTITY/1/edit

Но в производството приложението се монтира едно ниво надолу, така че URL адресите имат допълнителен термин:

https://server.example.com/APP/ENTITY/1/edit

Това работи добре в повечето случаи: url_helpers като edit_entity_url връща URL адресите, както съм ги показал. Честно казано, не ми е ясно как точно работи това; Предполагам, че Phusion Passenger и Rack се справят?

Въпреки това, когато изпратя имейл (като например за потвърждаване на повторно задаване на парола), той не работи: edit_entity_url никога не добавя APP точката за монтиране. Като изключим моята собствена условна логика в ERB, как мога да вкарам това "/APP" там?

Неща, които съм пробвал:

  • Настройка на `Rails.application.routes.default_url_options[:host] да включва "/registry" (без ефект)
  • използване на <%= link_to 'Reset', edit_entity_url(...) %> (без помощ)

Информация за версията:

  • actionmailer (4.0.2)
  • Релси 4.0.2
  • ruby 2.1.0p0
  • багажник (1.5.2)
  • пътник (4.0.35)

Файлът с активирани сайтове на Apache, който свързва нещата заедно (и единственото място, където мога да намеря, че е дефиниран токенът „/registry“):

<VirtualHost *:80>
    ServerName server.example.com
        DocumentRoot /var/www
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

    Alias /registry /app01/capapp/registry/current/public
    <Location /registry>
        PassengerBaseURI /registry
        PassengerAppRoot /app01/capapp/registry/current
    </Location>
    <Directory /app01/capapp/registry/current/public>
        Allow from all
        Options -MultiViews
    </Directory>

    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
        AllowOverride None
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log

    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined

    Alias /doc/ "/usr/share/doc/"
    <Directory "/usr/share/doc/">
        Options Indexes MultiViews FollowSymLinks
        AllowOverride None
        Order deny,allow
        Deny from all
        Allow from 127.0.0.0/255.0.0.0 ::1/128
    </Directory>

</VirtualHost>

Файлът Rails config/environments/production.rb.

Registration::Application.configure do
  config.cache_classes = true
  config.eager_load = true
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true
  config.serve_static_assets = false
  config.assets.js_compressor = :uglifier
  config.assets.compile = false
  config.assets.digest = true
  config.assets.version = '1.0'
  config.log_level = :debug
  config.i18n.fallbacks = true
  config.active_support.deprecation = :notify
  config.log_formatter = ::Logger::Formatter.new
  Rails.application.routes.default_url_options[:host] = "server.example.com"
end

Registration::Application.config.middleware.use ExceptionNotification::Rack,
:email => {
  :email_prefix => "[Registration]",
  :sender_address => %{"Admin" <[email protected]>},
  :exception_recipients => %w{[email protected]}
}

Преглед на имейла (app/views/user_mailer/password_reset.text.erb):

To reset your password click the URL below.  

<%= edit_password_reset_url(@user.password_reset_token) %>

If you did not request your password to be reset please ignore this email 
and your password will stay as it is.  

Да, странно е URL адресът да се основава на reset_token, а не на user_id, но той се обработва в контролера. Структура, базирана на Railscast #274


person jackr    schedule 23.01.2014    source източник
comment
Сега, след като публикувах, гремлинът за подобни въпроси на StackOverflow посочва този много подобен, 9-месечен въпрос без отговор: RackEnv не се зачита при използване на помощници за маршрути от модел   -  person jackr    schedule 23.01.2014
comment
Различни дискусии с възможност за търсене предлагат създаване на виртуален хост, вместо да променяте URL адреса, но това включва DNS записи, които са извън моя непосредствен обхват.   -  person jackr    schedule 24.01.2014


Отговори (2)


Е, това е отвратителен хак, но го "реших" с ръчна намеса. В app/views/user_mailer/password_reset.text.erb сега казвам:

To reset your password click the URL below.  

<%  url = root_url.chomp('/') %>
<%  url += "/registry" if Rails.env.production? %>
<%= url + edit_password_reset_path(@user.password_reset_token) %>

Все още се интересувам, ако някой има по-добра идея!

person jackr    schedule 23.01.2014

Можете да предадете параметъра :script_name на url_for (или други методи, базирани на url_for), за да зададете точката на монтиране. използвам

url_for( :only_path => false,
:host => some.host,
:script_name => Rails.application.config.relative_url_root
...

и задайте config.relative_url_root = '/your-mount-point' в конфигурацията.

Повече подробности за това тук: как -to-get-ruby-on-rails-production-mount-point-included-in-url-helpers-for-email

person jpgeek    schedule 02.06.2014