Rails: redirect with params - ruby-on-rails

What's the best way to pass some params along with a redirect?
I saw examples that said if you just add them to your redirect hash they would pass along with the request, but that doesn't seem to work anymore in Rails 3.
In my example I have an 'edit multiple' page that lets a user change the category on multiple items at once. Because they're browsing so many items this form is paginated.
If a user is on items page 3, makes some changes and presses sumbit, then the controller action receives a post request with the ids of the records that were changed, makes the changes, and redirects to the edit_many_items_path.
So, that redirect looks like this:
redirect_to edit_multiple_items_path, :notice => 'items updated'
... but what I'd like it to do is something like:
redirect_to edit_multiple_items_path, :notice => 'items updated', :page => ##
The above code doesn't work, so does anyone have an example of what would?

Try this:
redirect_to(edit_multiple_items_path(:page =>2), :notice => 'items updated')

Related

Rails 3.2 - How to merge params without displaying everything in the URL?

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))

Rails: Conditional redirect in rails app controller

I have an action in a controller that I call from two different views. In each case, I want the action to redirect back to the page on which the link was clicked. At the moment I am doing this...
In this view I am passing a parameter like this...
%a.showtooltip#wprofile{:href => idea_vote_up_path(#idea, :source => 'idea'), :title => 'Awesome idea - vote up !', }
and in the controller...
if params[:source] == 'idea'
redirect_to idea
else
redirect_to ideas_path
end
This works fine, but does not feel elegant, especially as it ends up being in a few actions. Is there a better way?
You can rewrite it in following way:
redirect_to params[:source] == 'idea' ? idea : ideas_path
If you want to redirect back to the page (refresh current page)
redirect_to request.referer
Store the referrer in the session like so session[:previous] ||= request.referer and use it as redirect_to session.delete(:previous)
I find that a good way is to have a hidden input with the value you'd like to be as the return url. Seems like an easily manageable solution and has worked for me. This way you can create the hidden input in 1 or 1000 views and have a single line of code in the controller to do the redirects. I can't immediately think of what the cons to this approach would be.
In form
hidden_field_tag(:redirect_to, params[:redirect_to]) # in the form that is to be submitted, value determined by a query string
hidden_field_tag(:redirect_to, "/a/direct/value") # in the form, value specified directly
In controller
redirect_to params[:redirect_to].presence || idea_path(#idea)
Didn't test the code and don't know ruby sups well so double check but the logic should stand. The ".presence" takes care of situations where you don't want a custom redirect to and have no hidden input to specify.

Rails: redirect_to '#{user.role}_url' how do I accomplish this?

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

What is causing this redirect_to to fail?

I am trying to use this redirect_to
redirect_to :controller => :note_categories, :action => :destroy, :note_id => params[:id]
This is the URL that results
http://localhost:3000/note_categories/272?note_id=272
and this is the error message
Unknown action
No action responded to show. Actions: destroy
The reason I am redirecting to the note_categories destroy action, and passing in the note id, is that in the destroy action, I am finding all the note_categories related to note, running some code on them, then destroying them. I know this isn't a great way to be doing this, but I couldn't use :dependant => :destroy because the code I have to run on the note_category before I delete it needs access to current_user, which can't happen in the note_category model.
So yeah, can someone please tell me what am I doing wrong in my redirect_to? Thanks for reading.
The redirect_to method is essentially the Rails implementation of the Post/Redirect/Get (PRG) web design pattern. It's used to prevent duplicate form submissions caused by the user clicking the browser's Refresh button after submitting a form.
The typical Rails usage is like this for creating an object:
A form for creating an object is displayed (new action/HTTP GET)
The user fills in the form
The form is submitted (create action/HTTP POST)
The object is created and saved
A redirect_to is performed with an HTTP 301/302 status to the object's show view or perhaps index
—for editing an object it's:
A form for edit an existing object is displayed (edit action/HTTP GET)
The user fills in the form
The form is submitted (update action/HTTP PUT)
The object is updated and saved
A redirect_to is performed with an HTTP 301/302 status to the object's show view or perhaps index
You can't redirect directly to the destroy action because in RESTful Rails that's intended to be invoked as a result of an HTTP DELETE request and doesn't render a template when it's invoked. The redirect_to method always redirects to a template.
You haven't shown us the code for destroying notes, but I suspect that what you're trying to achieve can be done with a before filter and by having the controller passing the current user to a model method.

Repopulating page with previous values in rails

I have a validation that needs to be done in controller. If it fails I need to go back to the view action back again with all values populated as it is on the page.
Is there a simple way to do that (using incoming params map).
This is the basic way all Rails controllers and scaffolds work. Perhaps you should try generating scaffolds?
def create
#banner_ad = BannerAd.new(params[:banner_ad])
if #banner_ad.save
flash[:notice] = 'BannerAd was successfully created.'
redirect_to :action => "show", :id => #banner_ad
else
render :action => "new"
end
end
end
I populate a #banner_ad here, attempt to save it, if it fails, I return to the form and the #banner_ad object is available to me. I then need to have a form that uses the Rails form helpers to populate the values from the object.
Depends on the flow of your app, really.
If the validation fails, you could pull the data out fo the database ...
if invalid?
#model = model.find(:id
end
Otherwise you might need to store the original values in hidden fields in the view and use those.

Resources