I'm trying to redirect to a location based on a param on a submitted form.
If params[:route] = group , I want to redirect to groups_path.
I tried the following method to redirect but obviously enough the groups_path is a variable and not a string. How can I redirect based off the param?
redirect_to "#{params[:route]}s_path"
Edit:
realised I can redirect to the actual path but this doesn't seem like a very rails way of doing it.
redirect_to "/#{params[:route]}s"
redirect_to send("#{params[:route].pluralize}_path")
But I'd rather write a wrapper-helper returning appropriate url helper based on the params[:route] value. params[:route] could potentially have any value and you may want to rescue in these cases.
send can calls private method, therefore better is public_send
and instead "#{params[:route]}s" use "#{params[:route].pluralize}
redirect_to public_send("#{params[:route].pluralize}_path")
Related
In my app I have a /thanks page that users were originally redirected to when completing a certain action. Now I want to redirect them to this page after multiple kinds of events and render different partials based on what the event was. So I added this to the /thanks page:
- case #event
- when "reservation"
= render 'thanks_job_created'
- when "charge"
= render 'thanks_job_charged'
Then, in the the JobsController#create action, I changed redirect_to thanks_jobs_path to this:
redirect_to thanks_jobs_path(params.merge(event: "reservation"))
...and added #event = params[:event] to JobsController#thanks.
The behavior works as intended, but I've found that using params.merge this way now displays every paramter in the URL, including authenticity token of the #create form, all of the Job attributes, etc. Before the URL looked correct (/jobs/thanks) because the only params were action and controller which are already indicated in the URL.
Is there a way for me to use params.merge without displaying all of that info in the URL?
If you just want to pass the event as a parameter, you don't need to use params.merge at all.
redirect_to thanks_jobs_path(event: "reservation")
will give you the path /jobs/thanks?event=reservation.
You could simply use except:
params.merge.except(:auth_token)
In your situation:
redirect_to thanks_jobs_path(params.merge(event: "reservation").except(:auth_token))
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.
Is there a way in rails/ruby to simplify my routing code to be elegant like:
redirect_to user.role + _url
This way if the user is an admin they will be routed to the admin page so on so forth for other user types...
Sure!
redirect_to send("#{user.role}_url")
in ruby, the send will execute the method on the receiver, and that's exactly what you want. Usually, that would look like:
#receiver_object.send(:admin_url)
But the url-helpers work in the global namespace, so you can send to global and have it work.
Easy way to test: Add this to a controller and watch it redirect you home:
redirect_to send("root_path")
Probably the best way would be to use the url_for helper. For example.
redirect_to url_for( :controller => users, :action => user.role )
This would generate a path /users/admin or /users/guest etc.
If you want to do it a hackish way you could use
redirect_to eval("#{user.role}_url")
Be careful with that though. The reason your string isn't working is it isn't evaluated, so redirect_to "admin_url" doesn't do anything, it's just a meaningless string and redirect is expecting the string to be a URL.
If you evaluate the string it would work, because redirect_to eval("#{user.role}_url") is going to first convert "admin_url" into calling the admin_url method, which returns some path like users/admin, and THAT string is useable by the redirect method.
You can use render "#{user.role}". Just be sure to have corresponding views with the names admin.html.erb' and so on.
I really like Andrew's answer, but you could also do something like
redirect_to send(user.role.to_s + '_url')
There are several things that you could do, but nothing built in and nothing that would be significantly simpler than send("#{user.role}_url"). Be sure to use send() - otherwise it will redirect to the URL "/admin_url" instead of calling the admin_url helper.
One such other solution would be to create an action called 'home' that would redirect to the current_user's role's page. That would add an extra redirect (slightly increase the page load time), but it would make your redirects simpler
redirect_to home_url
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 :)
Assume, there's a standard books_controller where I need to modify index method. If params[:value] is nil I need to assign not_nil value to it and then reload the same page. What I do within index method is
redirect = params[:value].nil?
params[:value] ||= some_value_which_is_not_nil
redirect_to books_path if redirect
The problem is that after redirecting the params[:value] is nil again! How can I pass params variable to the redirect_to method or is there any other way to store this value?
The params hash doesn't work that way. HTTP is stateless - assignments won't persist across requests.
What this means is, the params hash is populated from the GET/POST parameters in the request each time a request is made. If you want to redirect to the same page and have that parameter persist, you must pass it as a GET parameter.
redirect_to books_path(:value => some_value_which_is_not_nil) if redirect
I'm not exactly sure if this is what you're looking for but you can pass parameters into path methods.
books_path(:value => 1) results in /books?value=1.
def index
## RELOAD same page if params value is nil
params[:value] || redirect_to books_path(:value => "some_value_which_is_not_nil")
# Do my own processing!
end
If you're setting the nil value to something it should be in the same action that you're going to reload ... why not just continue processing with the value you set without reloading?
I can't see that you need to reload the action at all.