0

I am confused about how Rails 4 generates urls using _url and _path helpers. My configuration is I have a hardware device handling https requests which routes to nginx serving static files and referring rails requests to a thin server.

In my config/environments/production.rb i have

config.action_controller.default_url_options = {host: "mydomain", protocol: 'https'}

If I issue a redirect in a controller using an `_path helper it tries to redirect to the nginx port. (which is not accessible externally) If I issue a redirect in a controller using an _url helper it redirect correctly according to the config.

In a view a link_to _path and _url generate the correct url

So I have two questions Why do the helpers work differently in a view and in a controller. Is there a way to generate the correct url using _path or should I change everything to _url - and is there a downside to that?

thanks in advance

Andy

misterManSam
  • 24,303
  • 11
  • 69
  • 89
Andy
  • 135
  • 1
  • 1
  • 8

2 Answers2

5

In short:

_url Gives the entire path (domain name and protocol).

_path Gives the path after the '/' (no domain name or protocol).

There are various reasons why you'd use one over the other.

In longer form you can read this page: http://guides.rubyonrails.org/routing.html . There is more information there that could help you here but it is quite well written and my attempts at summarizing things would probably short you of important details.


To address your questions directly:

  • Why do the helpers work differently in a view and in a controller?

Probably better answered by http://guides.rubyonrails.org/routing.html than by me (I don't know exactly what you're trying to do).

You could also read this:

*_path are for views because ahrefs are implicitly linked to the current URL. So it’d be a waste of bytes to repeat it over and over. In the controller, though, *_url is needed for redirect_to because the HTTP specification mandates that the Location: header in 3xx redirects is a complete URL.

. . . As posted here: https://stackoverflow.com/a/2350837/1026898

  • Is there a way to generate the correct url using _path or should I change everything to _url?

Use your judgement based on the information provided above to make a decision. Are you trying to redirect to another domain (I suspect not)? If you are, you want to use '_url' over '_path'. If you are not, you probably want to use _path. It's hard to say without knowing your exact case.

  • Is there a downside to that?

Well technically there's probably some additional overhead if you do it one way or the other that you could avoid if you did it the other way. The real problem would arise, however, only when another developer comes in and has to make changes behind you. If you are using a weird solution (a solution different than the intended use of the helpers) it would be strange for them to figure out why you did things the way you did them.

Community
  • 1
  • 1
Ecnalyr
  • 5,792
  • 5
  • 43
  • 89
  • Thanks for the comments - I have read the link [link](http://guides.rubyonrails.org/routing.html) - it does explain that _url helpers includes server name and protocol which explains why my _url redirects work and _path don't. But it does not explain why the _path helper behaves differently in views and controllers. I can see how to get it to work as I want, but it makes me feel nervous that I don't understand. – Andy Jul 15 '14 at 12:03
  • Sorry creating confusion with my comments! New to SO as well as rails. – Andy Jul 15 '14 at 12:04
  • @Andy I don't understand why you're using `config.action_controller.default_url_options` at all. I have several apps live (some Rails 3, and some Rails 4) and I have never had a need to explicitly declare the value you are using. I use default_url_options to configure my ActionMailer and S3 connection, but nothing else. I suspect the issues you are having may be related to that. Why do you do that? – Ecnalyr Jul 15 '14 at 12:14
  • If I don't touch the default_url_options at all - the rails(thin) server generates all redirects to http://physical_nginx_server:nginx_port which is where it is seeing the traffic come from, but is internal to my architecture. I need it to generate urls like https://external_alias.co.uk which is the publicly available url. If there is a cleaner way to do it, I'm all ears! Cheers – Andy Jul 15 '14 at 13:12
  • @Andy: You're probably fine as far as that goes. You might want to update your original post to include a very explicit example of your problem and your attempted solution for us to give you concreted reasoning. Maybe if we are a little less abstract in our discussion we will get you the answer you need. – Ecnalyr Jul 15 '14 at 13:20
0

I guess this is because _path generates a relative path whereas _url generates the complete url.

Now, when you are in the controller, _path helper will try to redirect to the nginx port because it is where the request is being processed. Whereas, when you are in a view, the relative path works just fine.

I recommend that you change to _url in controllers.

Also, these methods are created automatically when routes are defined and in the case of RESTful routes, they follow a predictable convention.

Running 'rake routes' is a helpful way of seeing all of the routes being generated.

I recommend you read http://guides.rubyonrails.org/routing.html for more information.

Peeyush
  • 6,144
  • 5
  • 23
  • 37