Rails - How to create a 'previous page' object/method? - ruby-on-rails

How can I obtain the path of the previous page so I can use it in an if-statement like so:
if previous_page == example_path
...
else
...
end
Edit:
For clarification, I'm setting custom redirects for User Updates with Devise. The redirects go through a method called after_update_path_for(resource) and I'm adding playing around with that.

You could work with the referer from the request object in your controllers.
request.referer
=> http://localhost:3000/contacts

Use the session to store the current page, so that you can check later (on the next page) which one it was.

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 how to save the requested url?

I have two different ways to access the url "localhost:3000/childrens/new".
I have a drop down in childrens/new page and when the user selects an option through the drop down, it shows the different partials using ajax to call the childrens#new method.
accessing the childrens new page from url "localhost:3000/parents"
accessing the childrens new page from url "localhost:3000/parents1"
After the children have been successfully created, the user should be redirected to the relevant url (either localhost:3000/parents or localhost:3000/parents1)
Store the value in session like session[:last_request] in parent
After create children redirect it to session[:last_request] || session[:return_to] and after that clear the session[:last_request]
There are more than one way of how you can achieve this.
One solution would be to store the referrer inside of the session/cookie when the childrens/new is requested: (inside children_controller)
def new
session['children_new_referrer'] = request.env["HTTP_REFERER"]
#....YOUR CODE....
end
And then using that referrer value stored in session/cookie to redirect appropriately:
def create
#.....YOUR CODE....
if #child.save
format.html {redirect_to (session['children_new_referrer'] || parents_path)}
#.....YOUR CODE....
end
where #child is the object which I assume you are building with the parameters, and parents_path is being defined through your routes. Feel free to adjust these two based on your needs.
An alternative solution would be to not use sessions, but instead save the referrer uri/path inside of the children/new form page itself. This alternative has the benefit of making the solution session/request scope independent with handling the requirement of storing the referral uri/path within the page scope.
Do something like this
def create
redirect_to :back
end
redirect_to :back should come after save.
Pass the referrer as a parameter in the link. I would much prefer this solution to using the session store.
<%= link_to "New child", new_child_path(referrer: #parent.id) %>
.. or whatever you want to call it. Then you can inspect params[:referrer]. You're not wanting to persist data across a 'session', so why use the session store.
request.url
in your controller gives the url you are asking for.
So,
def create
if #child.save
redirect_to request.url
end
end
will do the job perfectly

How to setup routes when the controller only has edit and update?

I can't seem to figure out how to get my routes setup properly.
In my app, I have a view that lets site owners update their address information. The new and create actions are part of the signup process and are located in the signups_controller. The edit and update actions are in the settings_controller.
When the user goes into the settings area, he/she sees only the edit form. When filled out, the user is then returned to the same form with a flash message, or error message. Here is what the controller looks like:
class SettingsController < ApplicationController
def edit
#account = current_account
#account.companies.first
#account.companies.first.addresses.first
#account.companies.first.phones.first
end
def update
#account = current_account
if #account.update_attributes(params[:account])
redirect_to edit_setting_path
flash[:notice] = "Success!"
else
render :edit
end
end
end
In my routes, I simply have:
resources :settings
The link to this area of the site is a basic RESTful named linke, with the parameter options:
edit_setting_path(:id => current_account.id)
When the user arrives to this page, they see the following URL:
http://domainname.com/settings/1/edit
When they submit the form and get errors, the URL changes to:
http://domainname.com/settings/1
Why is the URL changing -- I'd rather it not? Is there a way to make it stay the same as the initial edit view? I've tried doing a redirect on a failed update, but then I don't get the error messages.
Any ideas?
To answer your "why" question: The URL is changing because it's reflecting the URL of the failed request - which in this case is a PUT request to that URL (/settings/1). You've submitted the form and the submission of that form (correctly) points to that URL. This is a result of the RESTful routes that the helper gives you. Since the logic in your action, falls through to the render :action, there is no redirect and the form simply re-renders on the page using the same data available in this action (which is why you can see the errors).
If you want to redirect back to the edit page, yes, you will lose the errors that have been set in the #account instance variable since the redirect will reset (re-query for) the account.
You could add a route that matches a PUT to /settings/1/edit and point it to your update action and change your form etc. In short, I wouldn't recommend this, but it should work.
completely untested but attemptable:
routes.rb
put "/settings/:id/edit", :to=>"settings#update", :as=>"update_setting"
resources :settings, :except=>:update
your form would also have to submit to the update_setting_path (which also means it's not reusable for a new object... ew)
First you should read up on The Rails Guides for Routing. They will help a lot to understand why its working like that.
Secondly, to accomplish what you are trying to do, you will need to add manual routes via the match call. You'll need something like this.
match '/settings/:id/edit' => "settings#edit"

How to go 'back' 2 levels?

From the list view of my app, I can view a list of records or drill down and edit/update a record. After updating, I want to go directly back to the list view, bypassing a couple of intermediate pages - but I don't simply want to link_to(:action => list) - there's pagination involved. I want to go back to the exact 'list' page I came from. What's the best way? Pass a hidden arg somewhere with the page number? Is there an elegant way to accomplish this?
I'm just going to throw this one out there with the disclaimer that there may be security considerations or existing gems.
On your edit action, you could store the previous page in a session. Then in your update action, redirect to it.
class MyController < ApplicationController
def edit
session[:prev_url] = request.referer
end
def update
redirect_to session[:prev_url]
end
end
As an alternative to use the session, you could carry the referer through the actions using a hidden form field.
class MyController < ApplicationController
def edit
#prev_url = request.referer
end
def update
redirect_to params[:prev_url]
end
end
Form using hidden_field:
f.hidden_field :prev_url, :value => #prev_url
If you do not want to carry along the whole referer url you could also do the same with the page parameter instead and append the parameter to the url in the update action. I would also expect Rails' url helpers to accept parameters.

Resources