Rails 3 change path to url - ruby-on-rails

I am passing a path as a parameter, so params[:path] would be name_path(:username => #user.name (I want to pass it as a path and not a url, so putting name_url in the params isn't what I want).
Since you can only use redirect_to with a url, I need to change the path to a url before I can use redirect_to. How would I do this?
I found this method here
def path_to_url(path)
"http://#{request.host_with_port_without_standard_port_handling}/#{path.sub(%r[^/],'')}"
end
But, this was written in 2008, and I want to know if there is a better way in Rails 3?

Updated copy from original path to url post btw: also works on Rails 2
# abs or /abs -> http://myx.com/abs
# http://grosser.it/2008/11/24/rails-transform-path-to-url
def path_to_url(path)
"#{request.protocol}#{request.host_with_port.sub(/:80$/,"")}/#{path.sub(/^\//,"")}"
end

I think you can use a redirect_to with a path as long as its a route defined in the routes file for the current application. Thats seems to be the case from your question.
ie, name_path(:username => #user.name)
So the following should be valid.
redirect_to params[:path]

I ended up using
def path_to_url(path)
"http://#{request.host}/#{path.sub(%r[^/],'')}"
end

Related

Replace GET params in redirect_to request.referer

I'm trying to Replace GET params in:
redirect_to request.referer
My request.referer already contains one parameter:
http://www.foo.com/bar?par=10
When i try:
redirect_to request.referer, :par => 5
it doesn't work. It redirects to referer but doesn't change :par from 10 to 5.
When i do redirect to url_path, e.g.
redirect_to root_path, :par => 5
This works ok, redirects to:
http://www.foo.com/?par=5
So my question is how to replace params in request.referer URI. Additional question is whether should I use request.referer or :back ?
Thanks
The problem is that redirect_to ultimately just takes a string, ie the url. If you were to do something like
redirect_to edit_foo_path(#foo, :bar => "qux")
then you're using a path helper to generate that string. ie, edit_foo_path(:bar => "qux") is the helper and it will be converted to "/foo/123/edit?bar=qux" which is just a "dumb" string. If you were working with the helper you can switch the params around but with the string it's already finished, if you know what i mean.
request.referer is a string as well, so what you'll need to do is to break it down into its constituent parts, modify those parts as required, and then reassemble it into a string again. The parts in question are protocol, host, path & params. You don't need to change the protocol, host or path in this case so you can keep them the same. params will be most easily manipulated when converted to a hash. Rails has various url-processing functions which you can use here, so there's probably a few different ways of doing this. I would do this like follows, which probably isn't the most efficient.
url = URL(request.referer)
#you could get this via a regex but i'm doing it "formally" with the Url object
host_and_path = "#{url.scheme}://#{url.host}#{url.path}"
params = CGI.parse(url.query)
#now you've got params as a hash you can do what you want to it.
params["par"] = 5
new_url = "#{host_and_path}?#{params.to_param}"
redirect_to new_url
like i say there's probably more efficient (in terms of lines of code, there's no issues with it speed-wise) ways to do this, but it's useful to see the step-by-step approach anyway i guess.

how do you determine if request.referrer matches a Rails restful path?

As we know from this post, in Rails, you can get the previous url by calling
request.referrer
But how do you check if the previous url matches one of the restful paths in
your Rails application?
By restful paths, I mean paths provided by Rails, such as,
books_path
book_path(book)
edit_book_path(book)
Of course I can do a regular expression string match on request.referrer, but I think it's a bit ugly.
One particular case, in my application, is that request.referrer can be
"localhost:3000/books?page=4"
and I want to it to match
books_path
which returns "/books"
In this case, how can I check if there's a match without doing regular expression string
match? (if this is at all possible)
Thanks
P.S. I have tried regular expression string match, and it works. I just thought there might be a better way in Rails.
You could extract the path portion of the request.referer using the following:
URI(request.referer).path
You can then use Rails.application.routes.recognize_path to check if path maps to a controller and action, e.g.:
my_path = URI(request.referer).path
# => /books
Rails.application.routes.recognize_path(my_path)
# => {:action=>"show", :controller=>"books", :page=>"4"}
Though not certain of what you want to do with that, pretty sure rails support better ways of controlling redirects. Nevertheless, I guess this is what you are looking for:
request.referer == books_url(page: params[:page])
UPDATED:
This way, even if there's no params[:page]. This would still work properly.
Since recognize_path was deprecated, this is another way of doing it:
Name your route in your routes config using the as keyword:
get 'foo/bar' => 'foo#bar', as: :foo_bar
Then you can do the check like this:
if URI(request.referer).path == foo_bar_path
do_something()
end

Custom path generator

I thought I knew how to override a path helper, but I'm not getting my expected behavior.
I tried adding something like this to my ApplicationHelper:
def post_path(post)
"/posts/#{post.id}/#{post.url}"
end
But for some reason, in one of my controllers when I try to use post_path(#post) it just returns the full url, something like /posts/4faddb375d9a1e045e000068/asdf (which is the current url in the browser) rather than /posts/4faddb375d9a1e045e000068/post-title-here.
In my routes file:
get '/posts/:id/:slug' => 'posts#show', :as => 'post'
The strange thing is if I use post_path(#post, #post.url), it works correctly. And if in a view I use post_path(#post) it works correctly. (#post.url returns the url friendly title)
In case you can't tell, I'm trying to eventually get the behavior similar to stackoverflow's where the url contains the id and a slug at the end and if the slug doesn't match the model with the given id, it'll redirect to the correct url.
What I'd try would be to put the whole def post_path in the application_controller.rb and make it a helper with helper_method :post_path. You'll get the best of both worlds.

Rails redirect_to with params

I want to pass parameters (a hash) to redirect_to, how to do this? For example:
hash = { :parm1 => "hi", :parm2 => "hi" }
and I want to redirect to page /hello
URL like this: /hello?parm1=hi&parm2=hi
If you don't have a named route for /hello then you'll have to hardcode the params into the string that you pass to redirect_to.
But if you had something like hello_path then you could use redirect_to hello_path(:param1 => 1, :param2 => 2)
Instead of:
redirect_to some_params
You can do:
redirect_to url_for(some_params)
You're turning the params into a url with url_for before passing it to redirect_to, so what you pass redirect_to ends up being a URL as a string, which redirect_to is happy to redirect to.
Note well: I don't understand why redirect_to refuses to use params. It used to be willing to use params. At some points someone added something to Rails to forbid it. It makes me suspect that there are security reasons for doing so, and if so, these security reasons could mean that manually doing redirect_to url_for(p) has security implications too. But I haven't yet been able to find any documentation explaining what's up here.
update: I've found the security warning, but haven't digested it yet: https://github.com/rails/rails/pull/16170
The easiest way (if it's not a named route) will be:
redirect_to "/hello?#{hash.to_param}"
See: http://apidock.com/rails/Hash/to_param
Simply, pass the hash into an argument in the URL, and in your code parse it to get out all needed values.
param_arr = []
hash.each do |key , val|
param_arr << "#{key}=#{val}"
end
params_str = param_arr.join("&")
redirect_to "http://somesite.com/somepage?#{params_str}"
I know this might be very basic way to do it, but hey, it'll get you somewhere :)

How do I get the current absolute URL in Ruby on Rails?

How can I get the current absolute URL in my Ruby on Rails view?
The request.request_uri only returns the relative URL.
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.
I think that the Ruby on Rails 3.0 method is now request.fullpath.
You could use url_for(only_path: false)
DEPRECATION WARNING: Using #request_uri is deprecated. Use fullpath instead.
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).
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
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
In Ruby on Rails 3.1.0.rc4:
request.fullpath
I needed the application URL but with the subdirectory. I used:
root_url(:only_path => false)
url_for(params)
And you can easily add some new parameter:
url_for(params.merge(:tag => "lol"))
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!
It looks like request_uri is deprecated in Ruby on Rails 3.
Using #request_uri is deprecated. Use fullpath instead.
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
This works for Ruby on Rails 3.0 and should be supported by most versions of Ruby on Rails:
request.env['REQUEST_URI']
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
If by relative, you mean just without the domain, then look into request.domain.
You can use the ruby method:
:root_url
which will get the full path with base url:
localhost:3000/bla
(url_for(:only_path => false) == "/" )? root_url : url_for(:only_path => false)
In Rails 3 you can use
request.original_url
http://apidock.com/rails/v3.2.8/ActionDispatch/Request/original_url
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}"
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"
You can either use
request.original_url
or
"#{request.protocol}#{request.host_with_port}"
to get the current URL.
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
if you want to be specific, meaning, you know the path you need:
link_to current_path(#resource, :only_path => false), current_path(#resource)
For rails 3 :
request.fullpath
request.env["REQUEST_URI"]
works in rails 2.3.4 tested and do not know about other versions.
To get the request URL without any query parameters.
def current_url_without_parameters
request.base_url + request.path
end
You can set a variable to URI.parse(current_url), I don't see this proposal here yet and it works for me.
You can use:
request.full_path
or
request.url
Hopefully it will resolve your problem.
Cheers
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

Resources