Andrew
Andrew

Reputation: 238707

How to generate URL with host in Rails development environment?

I am working on an application that has set its default host to localhost:

config.action_controller.default_url_options = { host: "localhost" }
config.action_mailer.default_url_options = { host: "localhost" }

This works fine if you're serving your app on a specific port (like http://localhost:3000). I am using Pow so that I can access the app from a URL like http://myapp.dev.

How can I change this setting so that it will work with my domain as well as the other developers using localhost? I need to generate full URLs since they will be used in emails. Is it possible to pass some sort of config value to Pow?

Upvotes: 2

Views: 7951

Answers (6)

hjblok
hjblok

Reputation: 2966

You could use an environment variable to configure a default host. See Luc Boissaye's answer on how to set this up with dotenv. If you don't add the .env to your repo, each developer can create his own .env and configure his (or her) own preferences.

But you can also use existing environment variables to configure the default_url_options. For example Pow.cx sets the POW_DOMAINS variable:

config.action_mailer.default_url_options = {
  ENV['POW_DOMAINS'].present? ? 'my-app.dev' : 'localhost' 
}

As far as I know you only need to set the config.action_controller.default_url_options if you want to force it to some default. When you use the rails _path helpers in your views, this will generate a relative URL (/path). If you use the _url helpers, this will generate an absolute URL (http://your.host/path), but both the protocol (http) and host (your.host) are request based.

Upvotes: 1

Salman Siddiqui
Salman Siddiqui

Reputation: 130

This will check if Application root directory is symlinked in .pow of current user and set the host accordingly.

if File.exists?(Dir.home+"/.pow/#{Rails.root.basename}")
  config.action_mailer.default_url_options = { host: "#{Rails.root.basename}.dev" }
else
  config.action_mailer.default_url_options = { host: "localhost" }
end

Upvotes: 1

Luc Boissaye
Luc Boissaye

Reputation: 945

In development, I like to use dotenv gem(https://github.com/bkeepers/dotenv).

I put in .env :

DOMAIN=myapp.dev

And I put inside config/route.rb: MyApplication::Application.routes.draw do default_url_options host: ENV['DOMAIN']

In production I define on heroku my domain with this command :

h config:set DOMAIN=myapp.herokuapp.com

or with a custom domain :

h config:set DOMAIN=superdomain.com

Upvotes: 1

shikha
shikha

Reputation: 669

You need to override default_url_options in your application controller (at least in rails 3)

http://edgeguides.rubyonrails.org/action_controller_overview.html#default_url_options

class ApplicationController < ActionController::Base
 def default_url_options
  if Rails.env.production?
   {:host => "myproduction.com"}
  else  
   {}
  end
 end

end

Upvotes: 0

Archonic
Archonic

Reputation: 5362

Described on Action Mailer Basics:

Unlike controllers, the mailer instance doesn't have any context about the incoming request so you'll need to provide the :host parameter yourself.

As the :host usually is consistent across the application you can configure it globally in config/application.rb:

config.action_mailer.default_url_options = { host: 'example.com' }

Because of this behavior you cannot use any of the *_path helpers inside of an email. Instead you will need to use the associated *_url helper. For example instead of using

<%= link_to 'welcome', welcome_path %>

You will need to use

<%= link_to 'welcome', welcome_url %>

The use of Pow makes things a little trickier but thankfully it integrates with XIP.io so you can access myapp.dev from machines on the local network. Just follow the instructions here: Accessing Virtual Hosts from Other Computers.

The question doesn't mention this, but it might be useful information - If you'd like to actually send mail in your dev (or perhaps test/staging) environment, Instead of seeing mail just in the rails console (with something like powder applog), I'd recommend just hooking it up to a gmail.

Upvotes: 0

Benjamin Bouchet
Benjamin Bouchet

Reputation: 13181

This is the best way I found:

1- Create a config/smtp_settings.example.yml file:

development:
  :method: :letter_opener
  :url_options:
    :host: localhost
    :port: 3000

production: &production
  :method: :smtp
  :url_options:
    :host: www.the_site.com
  :smtp_settings:
    address: smtp.gateway.com
    port: 465
    user_name: [email protected]
    # etc ...

staging:
  <<: *production

test:
  :method: :test
  :url_options:
    :host: test.host

Notes:

  • This uses letter_opener as development mailer, change to your own method
  • There is a staging environment defined as an exact copy of the production environment, remove if you don't use staging

2- Remove config.action_mailer.delivery_method and config.action_mailer.default_url_options and config.action_mailer.smtp_settings from all files under config/environments/ folder

3- Add in the file config/application.rb the following:

config.action_mailer.delivery_method = config_for(:smtp_settings)[:method]
config.action_mailer.default_url_options = config_for(:smtp_settings)[:url_options]
config.action_mailer.smtp_settings = config_for(:smtp_settings)[:smtp_settings] if config_for(:smtp_settings)[:method] == :smtp

Notes: config_for has been introduced in the latest version of Rails (4.2.0 as per writing). If you use an older version of rails you must manually load the yml files


And the trick on top of all of that to answer your question:

Push to your repository the file config/smtp_settings.example.yml and ignore the file config/smtp_settings.yml.

Each developper of your team would have to create their own config/smtp_settings.yml by copying the file smtp_settings.example.yml and changing the host to match their machine's IP address, so the mail send by each developer leads to their own machine.

You off course requires you to start the local development server binded to 0.0.0.0 so it's accessible from other hosts (considering your security environment off course)

Upvotes: 2

Related Questions