1122

How can I get the current absolute URL in my Ruby on Rails view?

The request.request_uri only returns the relative URL.

Aryan Beezadhur
  • 4,503
  • 4
  • 21
  • 42
Jakub Arnold
  • 85,596
  • 89
  • 230
  • 327

33 Answers33

1503

For Rails 3.2 or Rails 4+

You should use request.original_url to get the current URL. Source code on current repo found here.

This method is documented at original_url method, but if you're curious, the implementation is:

def original_url
  base_url + original_fullpath
end

For Rails 3:

You can write "#{request.protocol}#{request.host_with_port}#{request.fullpath}", since request.url is now deprecated.


For Rails 2:

You can write request.url instead of request.request_uri. This combines the protocol (usually http://) with the host, and request_uri to give you the full address.

satchel
  • 405
  • 5
  • 16
Jaime Bellmyer
  • 23,051
  • 7
  • 53
  • 50
  • 32
    as other users pointed: DEPRECATION WARNING: Using #request_uri is deprecated. Use fullpath instead – giladbu Apr 26 '11 at 17:20
  • 9
    @giladbu `fullpath` does NOT include the protocol/domain/port! It’s not an absolute URL! – Alan H. Aug 01 '11 at 21:36
  • 37
    `"http://#{request.host+request.fullpath}"` will work or otherwise, (if the port is important) `"http://#{request.host}:#{request.port+request.fullpath}"` – Nilloc Feb 01 '12 at 20:21
  • 7
    if port important, this one works right: `"http://#{request.host}:#{request.port}#{request.fullpath}"` – Sucrenoir Apr 19 '12 at 15:16
  • You can also use `request.host_with_port` to make something compatible with both production and dev envs. – rogercampos Jul 18 '12 at 14:41
  • Its clear that the `request.*` api has changed a lot between rails versions and may continue to change. However, the api for `url_for` has remained mostly constant. I would use `url_for` for that reason. I woud say that @grzuy's answer is the best one. – PeppyHeppy Dec 28 '12 at 07:10
  • 3
    Can you point to a reference for the claim that `request.url` is deprecated? The proposed solution is just a long way of saying what `request.url` already does; the implementation is simply protocol + host_with_port + fullpath (https://github.com/rails/rails/blob/33841a9db3e560ef062d36d14ea07f7d71dd65ab/actionpack/lib/action_dispatch/http/url.rb#L86) – mhartl Mar 22 '13 at 20:01
  • 1
    This answer is outdated! See @Mike's answer for a smarter solution (i.e. use `request.original_url`). – collimarco Jul 22 '13 at 08:25
  • how do you use this with `link_to request.original_url` and add an extra parameter? somehow with `params.merge` maybe? – cwd Apr 26 '14 at 00:04
  • 1
    What if there is no `request` because I am not in controller but in a worker thread? – Paul Nov 23 '14 at 22:18
140

I think that the Ruby on Rails 3.0 method is now request.fullpath.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mcr
  • 4,615
  • 2
  • 31
  • 30
130

You could use url_for(only_path: false)

grzuy
  • 4,791
  • 2
  • 20
  • 17
  • In my (a bit special case) this was almost exactly what I wanted. I just changed the option to true and got the url for the current page, without options. Thanks :) – Spiralis Oct 23 '11 at 13:16
  • @David not in the View it doesn't. But it should'n be used there anyway =) – Lyuben Todorov Nov 14 '12 at 00:25
  • In my case I wanted to change host name but keep everything else. I found that url_for(host: 'www.newdomain.com') worked the best for me as a solution to the problem. IMO, its a more robust solution since its the same across all versions of rails. – PeppyHeppy Dec 28 '12 at 07:06
  • 1
    FYI This will not work if you have multiple paths for the same resource. – thekingoftruth Jul 16 '14 at 17:32
  • For a `/activities/:id` path I got `404?id=:id` when doing `url_for(only_path: false)` from a page handling "not found", `request.original_url` works fine – Dorian Aug 27 '21 at 18:36
67

If you're using Rails 3.2 or Rails 4, you should use request.original_url to get the current URL.


Documentation for the method is at http://api.rubyonrails.org/classes/ActionDispatch/Request.html#method-i-original_url, but if you're curious, the implementation is:

def original_url
  base_url + original_fullpath
end

EDIT: This is still the case for Rails 7 (Docs).

Ray Baxter
  • 3,181
  • 23
  • 27
Mike
  • 9,692
  • 6
  • 44
  • 61
67

DEPRECATION WARNING: Using #request_uri is deprecated. Use fullpath instead.

lulalala
  • 17,572
  • 15
  • 110
  • 169
ecoologic
  • 10,202
  • 3
  • 62
  • 66
  • 4
    See notes on answer http://stackoverflow.com/a/2165727/166279, fullpath doesn't include the domain. – Nilloc Feb 01 '12 at 20:07
  • this line came straight from the log at time of writing when using `request.uri` and this has already been pointed out several times in this question, but... ok, thanks – ecoologic Feb 01 '12 at 22:17
  • 1
    @ManishShrivastava: funny, in spite of all the "original" effort I put answering more complex questions, this copy and paste gave me the highest score, well... better than nothing – ecoologic Aug 27 '14 at 00:02
52

You can add this current_url method in the ApplicationController to return the current URL and allow merging in other parameters

# https://x.com/y/1?page=1 
# + current_url( :page => 3 )
# = https://x.com/y/1?page=3
def current_url(overwrite={})
    url_for :only_path => false, :params => params.merge(overwrite)
end

Example Usage:

current_url --> http://...
current_url(:page=>4) --> http://...&page=4
Charles
  • 1,121
  • 19
  • 30
grosser
  • 14,707
  • 7
  • 57
  • 61
39

For Ruby on Rails 3:

request.url
request.host_with_port

I fired up a debugger session and queried the request object:

request.public_methods
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Duke
  • 7,070
  • 3
  • 38
  • 28
32

In Ruby on Rails 3.1.0.rc4:

 request.fullpath
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lucas Renan
  • 3,787
  • 3
  • 28
  • 35
29

I needed the application URL but with the subdirectory. I used:

root_url(:only_path => false)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dorian
  • 22,759
  • 8
  • 120
  • 116
28
 url_for(params)

And you can easily add some new parameter:

url_for(params.merge(:tag => "lol"))
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yuri Barbashov
  • 5,407
  • 1
  • 24
  • 20
16

I think request.domain would work, but what if you're in a sub directory like blah.blah.com? Something like this could work:

<%= request.env["HTTP_HOST"] + page = "/" + request.path_parameters['controller'] + "/" + request.path_parameters['action'] %>

Change the parameters based on your path structure.

Hope that helps!

James M
  • 239
  • 1
  • 6
  • 8
    Yes Jaime's answer is way better, but if you want to be really inefficient, you could do it my way. – James M Jan 29 '10 at 22:47
14

It looks like request_uri is deprecated in Ruby on Rails 3.

Using #request_uri is deprecated. Use fullpath instead.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ken Earley
  • 769
  • 4
  • 14
13

Using Ruby 1.9.3-p194 and Ruby on Rails 3.2.6:

If request.fullpath doesn't work for you, try request.env["HTTP_REFERER"]

Here's my story below.

I got similar problem with detecting current URL (which is shown in address bar for user in her browser) for cumulative pages which combines information from different controllers, for example, http://localhost:3002/users/1/history/issues.

The user can switch to different lists of types of issues. All those lists are loaded via Ajax from different controllers/partials (without reloading).

The problem was to set the correct path for the back button in each item of the list so the back button could work correctly both in its own page and in the cumulative page history.

In case I use request.fullpath, it returns the path of last JavaScript request which is definitely not the URL I'm looking for.

So I used request.env["HTTP_REFERER"] which stores the URL of the last reloaded request.

Here's an excerpt from the partial to make a decision

- if request.env["HTTP_REFERER"].to_s.scan("history").length > 0
  - back_url = user_history_issue_path(@user, list: "needed_type")
- else
  - back_url = user_needed_type_issue_path(@user)
- remote ||= false
=link_to t("static.back"), back_url, :remote => remote
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sergiy Seletskyy
  • 16,236
  • 7
  • 69
  • 80
  • Yup, fullpath gets you the url you requested, not the url you *came from*, which is what I needed as well. Thanks for this! – Spencer Rathbun Aug 10 '12 at 13:31
  • 2
    Works great, just what I needed. This should be in a seperate question and answer though. Kinda hard to find here. :/ – DDDD Apr 07 '14 at 16:31
12

This works for Ruby on Rails 3.0 and should be supported by most versions of Ruby on Rails:

request.env['REQUEST_URI']
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tim Santeford
  • 27,385
  • 16
  • 74
  • 101
12

None of the suggestions here in the thread helped me sadly, except the one where someone said he used the debugger to find what he looked for.

I've created some custom error pages instead of the standard 404 and 500, but request.url ended in /404 instead of the expected /non-existing-mumbo-jumbo.

What I needed to use was

request.original_url
Frans
  • 1,389
  • 2
  • 16
  • 28
9

You can use the ruby method:

:root_url

which will get the full path with base url:

localhost:3000/bla
Jai Chauhan
  • 4,035
  • 3
  • 36
  • 62
Idan Wender
  • 977
  • 8
  • 10
  • This is the only solution that works in serializers using active_model_serializers in Rails 4. – Kris Khaira Dec 09 '14 at 23:46
  • Can you please tell me how can I restrict the params I pass to an absolute url when I use somethin like `:root_url` to get the absolute url ? Assume I'm usin somethin like `some_method(:products_brand_url, brand: brand, entity_name: "brand")` and `some_method` is defined as ` def some_method(route, opts = {}) end ` I don't want my route to look like - `http://localhost:3000/brands/brand_name?&entity_name="brand"`. I want the route to look like `http://localhost:3000/brands/brand_name`. I just want the `entity_name` to be a part of the opts hash and not as a params to the absolute url. – boddhisattva Feb 28 '17 at 15:25
  • Certainly there's no _Ruby_ method called `root_url`. – smileart May 17 '19 at 16:43
9

If by relative, you mean just without the domain, then look into request.domain.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ghoppe
  • 21,452
  • 3
  • 30
  • 21
8
(url_for(:only_path => false) == "/" )? root_url : url_for(:only_path => false)
msroot
  • 817
  • 11
  • 13
6

In Rails 3 you can use

request.original_url

http://apidock.com/rails/v3.2.8/ActionDispatch/Request/original_url

mikrobi
  • 291
  • 1
  • 3
  • 11
6

you can use any one for rails 3.2:

request.original_url
or
request.env["HTTP_REFERER"]
or
request.env['REQUEST_URI']

I think it will work every where

"#{request.protocol}#{request.host}:#{request.port}#{request.fullpath}"
uma
  • 2,932
  • 26
  • 20
6

Rails 4.0

you can use request.original_url, output will be as given below example

get "/articles?page=2"

request.original_url # => "http://www.example.com/articles?page=2"
Arvind singh
  • 1,312
  • 15
  • 15
5

You can either use

request.original_url 

or

"#{request.protocol}#{request.host_with_port}" 

to get the current URL.

Robin Garg
  • 203
  • 2
  • 13
5

For Rails 3.2 or Rails 4 Simply get in this way "request.original_url" Reference: Original URL Method

For Rails 3 As request.url is deprecated.We can get absolute path by concatenating

"#{request.protocol}#{request.host_with_port}#{request.fullpath}"

For Rails 2

request.url
Amit
  • 174
  • 1
  • 7
3

if you want to be specific, meaning, you know the path you need:

link_to current_path(@resource, :only_path => false), current_path(@resource)
Victor S
  • 5,098
  • 5
  • 44
  • 62
3

For rails 3 :

request.fullpath

Pankhuri
  • 958
  • 8
  • 5
3
request.env["REQUEST_URI"]

works in rails 2.3.4 tested and do not know about other versions.

Satishakumar Awati
  • 3,604
  • 1
  • 29
  • 50
3

To get the request URL without any query parameters.

def current_url_without_parameters
  request.base_url + request.path
end
Nerve
  • 6,463
  • 4
  • 29
  • 29
3

You can set a variable to URI.parse(current_url), I don't see this proposal here yet and it works for me.

Artem Mostyaev
  • 3,874
  • 10
  • 53
  • 60
RaK427
  • 31
  • 3
1

You can use:

request.full_path

or

request.url

Hopefully it will resolve your problem.

Cheers

Ali Hassan Mirza
  • 552
  • 11
  • 23
0

To get the absolute URL which means that the from the root it can be displayed like this

<%= link_to 'Edit', edit_user_url(user) %>

The users_url helper generates a URL that includes the protocol and host name. The users_path helper generates only the path portion.

users_url: http://localhost/users
users_path: /users
Ahmad hamza
  • 1,816
  • 1
  • 23
  • 46
0

Rails 4

Controller:

def absolute_url
  request.base_url + request.original_fullpath
end

Action Mailer Notable changes in 4.2 release:

link_to and url_for generate absolute URLs by default in templates, it is no longer needed to pass only_path: false. (Commit)

View:

If you use the _url suffix, the generated URL is absolute. Use _path to get a relative URL.

<%= link_to "Home", root_url %>

For More Details, go to:

http://blog.grepruby.com/2015/04/absolute-url-full-url-in-rails-4.html

user3118220
  • 1,438
  • 12
  • 16
0

For Rails 3.x and up:

#{request.protocol}#{request.host_with_port}#{request.fullpath}

For Rails 3.2 and up:

request.original_url

Because in rails 3.2 and up:

request.original_url = request.base_url + request.original_fullpath

For more info, plese visit http://api.rubyonrails.org/classes/ActionDispatch/Request.html#method-i-original_url

V K Singh
  • 1,134
  • 9
  • 14
-2

you can get absolute url by calling:

request.original_url

or

request.env['HTTP_REFERER']