72

Right now I'm using this which works for the development host, but I have to manually change the {:host => ""} code when I move to production.

post.rb

def share_all
  url =  Rails.application.routes.url_helpers.post_url(self, :host => 'localhost:3000')
  if user.authentications.where(:provider => 'twitter').any?
    user.twitter_share(url)  
  end
end

I'd like to use this and then define the default_url_options per environment:

post.rb

def share_all
  url =  Rails.application.routes.url_helpers.post_url(self)
  if user.authentications.where(:provider => 'twitter').any?
    user.twitter_share(url)  
  end
end

I've tried adding this to my config/environments/development.rb but I still get the "Missing host to link to! Please provide :host parameter or set default_url_options[:host]" error

development.rb

config.action_controller.default_url_options = {:host => "localhost:3000"}

And I even tried it this way:

development.rb

config.action_controller.default_url_options = {:host => "localhost", :port => "3000"}

EDIT:

I've now also followed this and still the same error guide http://edgeguides.rubyonrails.org/action_controller_overview.html#default_url_options

application controller

class ApplicationController < ActionController::Base
  protect_from_forgery
  include ApplicationHelper
  def default_url_options
    if Rails.env.production?
      { :host => "example.com"}
    else
      {:host => "example1.com"}
    end
  end
end

This is driving me crazy, what am I missing here???

trying_hal9000
  • 4,343
  • 8
  • 43
  • 62

9 Answers9

130

Okay I figured it out the correct way to write it is

Rails.application.routes.default_url_options[:host] = 'localhost:3000'

:)

tokland
  • 66,169
  • 13
  • 144
  • 170
trying_hal9000
  • 4,343
  • 8
  • 43
  • 62
  • 6
    If you have dynamic host's then it's not thread safe. I found only one way, is to set Thread.current in ApplicationController through before_filter, and use this host in Model. – Dmitry Polushkin Aug 15 '11 at 19:15
  • 5
    is there a way to set it from config.routes or something like that? – sites May 11 '13 at 16:32
  • 1
    @juanpastas: I just added it to the top of `routes.rb`: `Example::Application.routes.default_url_options[:host] = 'example.com'` – lime Nov 28 '13 at 16:01
  • 1
    FWIW I think is probably best addressed by using the _path helpers versus the url helpers... i.e. relative path versuse absolute url. :) This is usually a problem with rspec. – engineerDave Jan 12 '14 at 07:27
  • Switching to _path helpers only helps so far. For instance, if you use redirect_to, it calls url_for under the hood so you need to pass :only_path => true each time you call it. – jxpx777 Sep 18 '14 at 13:34
  • Where do you do this for rails engine? – Jwan622 Nov 30 '16 at 17:32
  • Also, using `_path` helpers is not working scenario if you have an ActiveJob what wants to use url helpers – Gabor Garami Jul 29 '17 at 09:23
  • In 5.1.4 this does not work in web page rendering, but only work in rails console. See https://stackoverflow.com/a/48781000/474597 for more details. – lulalala Feb 14 '18 at 07:35
  • `Rails.application.routes.default_url_options = { host: 'localhost:3000', protocol: 'https' }` if you want to change to `https` too – new2cpp Sep 12 '19 at 02:35
12

Inherit your Application's default_url_options from ActionMailer.

You want to keep things as DRY as possible so, ideally, you don't want to hard code your host and port in multiple places for the same environment, unless your ActionMailer actually uses a different host and port than the rest of your Application.

To set the default_url_options for your entire Application, simply add the following line to your config/environment.rb file (changing MyApp to your app's name):

# Set the default host and port to be the same as Action Mailer.
MyApp::Application.default_url_options = MyApp::Application.config.action_mailer.default_url_options

This will fix your problem and automatically set your Application's default_url_options to the same as your config.action_mailer.default_url_options:

$ MyApp::Application.config.action_mailer.default_url_options
#=> {:host=>"lvh.me", :port=>"3000"}

$ MyApp::Application.default_url_options
#=> {:host=>"lvh.me", :port=>"3000"}
Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
  • 1
    If you do this, you might want to add a comment above your Action Mailer `default_url_options` stating that the Application `default_url_options` inherit them. Wouldn't want someone changing the Action Mailer `default_url_options` not realizing it will change them for the entire application. – David Gay May 24 '20 at 17:25
  • @DavidGay Agree. Ideally, I would rather set the `default_url_options` explicitly and then specify that `action_mailer.default_url_options` inherit from those. For some reason, I didn't do it like that 2.5 years ago. – Joshua Pinter Jan 06 '21 at 22:25
7

You have to restart your server before the changes to this file takes effect.

Ryan Bigg
  • 106,965
  • 23
  • 235
  • 261
6

config/environments/development.rb (any other environment, same)

add this row with host that you want

routes.default_url_options[:host] = 'localhost:3000'
5

config.action_mailer.default_url_options = { :host => "your host" }

for instance your host localhost:3000

you can put this in test.rb, development.rb, production.rb files host could be different from environment to environment

2

I know this is an old thread, but I ran into this with Ruby 2.6.3 and Rails 5.2.3. The behavior I was seeing was basically that every path I added would fail with Error during failsafe response: undefined method 'empty?' for nil:NilClass. In production it worked fine, but in my development environment, I would get the error mentioned above.


The fix for me was add this to controllers/application_controller.rb:

def default_url_options
  if Rails.env.production?
    Rails.application.routes.default_url_options = { host: "www.production-domain.com", protocol: 'https' }
  elsif Rails.env.development?
    Rails.application.routes.default_url_options = { host: 'localhost:3000', protocol: 'http' }
  end
end

I was then able to run my development environment on my local.

1

Just ran into this problem myself trying to generate a URL in a rake task. It's definitely non-obvious and many of these solutions will work. My solution is a take off from @joshua-pinter's but done in the environment file. For example my development.rb looks like:

Rails.application.configure do
  …
  config.action_mailer.default_url_options = self.default_url_options = { host: 'localhost', port: 3000 }
  …
end

with the appropriate changes made to production.rb.

Aaron
  • 13,349
  • 11
  • 66
  • 105
1

This is how I usually go about this problem:

First, properly set your config/environments/production.rb (and other environments) from the rails new auto-generated file:

Rails.application.configure do
  # [...]
  config.action_mailer.default_url_options = {
    host: "https://your_app.your_domain.tld"
  } # You may also use an env variable ENV['HOST'] if necessary
end

Then, go back to your config/application.rb and set to inherit from this ActionMailer configuration:

require_relative "boot"
require "rails/all"
Bundler.require(*Rails.groups)

module YourModule
  class Application < Rails::Application
    # [...]
    config.after_initialize do |app|
      app.routes.default_url_options = app.config.action_mailer.default_url_options
    end
  end
end
Sébastien Saunier
  • 1,787
  • 2
  • 19
  • 28
0

For me whats worked is

ActionMailer::Base.default_url_options = { host: "yourhosthere"} # e.g. yourhosthere=localhost:3000 or yourhosthere=example.com

because if you already set a port in the config files then changing the [:host] only will result in an error

TypeError (no implicit conversion of Symbol into Integer):
dowi
  • 1,005
  • 15
  • 30