How can I get a full url in rails?
url_for @book is returning only a path like /book/1 and not www.domain.com/book/1
Thanks (and sorry if the answer is obvio
According to the docs, this shouldn't happen. The option you're looking for is :only_path
and it's false by default. What happens if you set it to false explicitly?
url_for(@book, :only_path => false)
While you can use url_for
you should prefer Ryan's method when you can - book_url(@book)
for a full url or book_path(@book)
for the path.
In Rails 4, url_for only takes one argument, so you need to pass an array with an explicit hash inside for the only_path
option.
Good:
url_for([@post, @comment, {only_path: true}])
Bad:
url_for(@post, @comment, {only_path: true})
url_for([@post, @comment], {only_path: true})
From the source, url_for
with an Array
input just calls:
polymorphic_url([@post, @comment], {only_path: true})
as shown in @moose's answer.
As noted by @lime, only_path
is generally not needed for polymorphic_url
since you distinguish that with the _url
_path
suffixes.
Use the :host option. For example, you can use:
url_for(@book, :host => "domain.com")
Note: with Rails 3 and above, use polymorphic_url
instead of url_for
.
In Rails 5, if you want the full url for the current controller/action (== current page), just use:
url_for(only_path: false)
Long answer:
In Rails 5, url_for
in a view is ActionView::RoutingUrlFor#url_for
. If you look at it's source code (https://api.rubyonrails.org/classes/ActionView/RoutingUrlFor.html#method-i-url_for
), you'll see if you pass a Hash (keyword parameters are cast into a Hash by Ruby), it actually calls super
, thus invoking the method of same name in it's ancestor.
ActionView::RoutingUrlFor.ancestors
reveals that it's first ancestor is ActionDispatch::Routing::UrlFor
.
Checking it's source code (https://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html#method-i-url_for), you'll read this:
Missing routes keys may be filled in from the current request's parameters (e.g. :controller, :action, :id and any other parameters that are placed in the path).
This is very nice, since it will build automatically a URL for you for the current page (or path, if you just invoke url_for
without the only_path: false
). It will also intelligently ignore the query string params; if you need to merge those, you can use url_for(request.params.merge({arbitrary_argument:'value'}))
.
It seems that this would work:
url_for(@book)
But it does not. The url_for method accepts only one argument, which can be either a string, an instance of a model, or a hash of options. This is rather unfortunate, as it would seem like you may need to link to @book and add options like :only_path or :host as well.
One way around it is to use polymorphic_url, which would render the correct absolute url even though your model is (likely) not actually polymorphic:
polymorphic_url(@book, :host => "domain.com")
Perhaps the best route would be to use a named route, which is set up automatically for you when declaring resources in your routes or using the :as option:
# in routes.rb:
resources :books
# or
get "books/:id" => "books#show", as: :book
# in your view:
book_path(@book, :host => "domain.com")
If it's a RESTful resource you'll be able to use this:
book_url(@book)