tl;dnr: My page links are fine, but links erb-olated into non-page text (email) lack the production app mount-point.
detail: My RoR app uses slightly different URLs in dev and production: in dev, the top-level entity is the resource model:
http://localhost:3000/ENTITY/1/edit
But in production, the app is mounted one level down, so URLS have an extra term:
https://server.example.com/APP/ENTITY/1/edit
This works fine for most cases: url_helpers like edit_entity_url
return the URLs as I've shown them. Frankly, I'm not clear exactly how that works; I suppose Phusion Passenger and Rack work it out?
However, when I send email (such as to confirm a password reset), it's not working: edit_entity_url
never adds the APP
mount-point. Short of my own conditional logic in ERB, how can I get that "/APP" in there?
Things I've tried:
- Setting `Rails.application.routes.default_url_options[:host] to include "/registry" (no effect)
- using
<%= link_to 'Reset', edit_entity_url(...) %>
(no help)
Version info:
- actionmailer (4.0.2)
- Rails 4.0.2
- ruby 2.1.0p0
- rack (1.5.2)
- passenger (4.0.35)
The Apache "sites-enabled" file that ties things together (and the only place I can find that the "/registry" token is defined):
<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>
The Rails config/environments/production.rb
file.
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" <XXX@example.com>},
:exception_recipients => %w{XXX@example.com}
}
View for the email (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.
Yes, it's odd to base the URL on the reset_token not the user_id, but it's handled in the controller. Structure based on Railscast #274