How to go 'back' 2 levels? - ruby-on-rails

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.

Related

Rails - Edit data on front-end like in Linkedin's profiles pages

Is it possible, in a RoR web application, to allow users to edit elements which are in a Show page?
The target would be something like on Linkedin, when you edit your own profile page (moving your mouse over a field gives you the ability to edit it). How do they manage to do that? Is it on a Show page or an Edit page? What kind of front-end technology do we need?
I'm not a big fan of the traditional 'Edit.html' vs 'Show.html'.
Many thanks! :)
Yes you can use your show page as an edit page. You could set up your controller to something comparable to this:
your_controller.rb
class YourController < Application Controller
before_filter :show_user
def show
render :edit
end
def edit; end
private
def show_user
#user = current_user
end
end
Also don't forget your 'update' method within this controller and params that you are passing. Then you can create your edit.html view that acts as a show page, but allows edits to take place. As far as editing comparable to LinkedIn, you can use the 'best_in_place' gem for inline editing. Found here: https://github.com/bernat/best_in_place

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"

Way to see which rails controller/model is serving the page?

This might be a slightly odd question, but I was wondering if anyone know a Rails shortcut/system variable or something which would allow me to keep track of which controller is serving a page and which model is called by that controller. Obviously I am building the app so I know, but I wanted to make a more general plugin that would able to get this data retroactively without manually going through it.
Is there any simple shortcut for this?
The controller and action are defined in params as params[:controller] and params[:action] but there is no placeholder for "the model" as a controller method may create many instances of models.
You may want to create some kind of helper method to assist if you want:
def request_controller
params[:controller]
end
def request_action
params[:action]
end
def request_model
#request_model
end
def request_model=(value)
#request_model = value
end
You would have to explicitly set the model when you load it when servicing a request:
#user = User.find(params[:id])
self.request_model = #user
There are a number of ways that I know of:
First you can do rake routes and check out the list of routes.
Second you could put <%= "#{controller_name}/#{action_name}" %> in your application.html.erb and look at the view to see what it says. if you put it at the extreme bottom you'll always get that information at the bottom of the page.
The controller can be accessed through the params hash: params[:controller]. There isn't really a way to get the model used by a controller though, because there is no necessary correlation between any controller and any model. If you have an instance of the model, you could check object.class to get the model's class name.

Passing instance variable from one form to the a different controller's action in Rails

Simple question - I have a form where I create an instance of an object. After I create that object (aka submit the form), I want to redirect to a new form that is associated with a different controller's action and carry that instance variable to populate some of that form's fields.
I know I typically have 2 options, store that instance variable in the session or pass it via params. I can't use sessions (for a variety of reasons I won't bore you with). The params option I am confused on.
I should know this. :( How would you go about doing this? Any examples greatly appreciated!!
Betsy
You'll have two methods on your controller. One for each form (rendered by the associated template). The first form should post to the second action. The second action can then transfer the request parameters into instance variables, to be available within the second template.
class FooController
def bar
# setup instance variables and render first form
end
def baz
#bar_values = params[:bar]
# setup other instance variables and render second form
end
end
UPDATE0 Do it across two controllers using session.
class FooController
def new_baz
# setup instance variables and render the first form
end
def create_baz
# respond to posting of form data
session[:current_baz_values] = params
redirect_to :action => "baq", :controller => "bar"
end
end
class BarController
def baq
#baz_values = session[:current_baz_values]
# setup other instance variables and render the second form
end
end
Could you somehow just do a find of the newly created record in the other controller, and then use that to populate the info you need?
Also, unless you are using AJAX you usually don't want to have modification actions on the show page for a record. Those belong on the edit or update page. If you always want people to be able to edit a record on the same page I would either use some AJAX on the show page, or just always return the edit/update page instead...
If you do not want to use sessions, you could use the flash variable to store your parameter. Something like, flash[:my_params] = params, and then reading it back in the next request with params = flash[:my_params]. The good thing about flash, is that persists for only the next request, and auto-clears after that.
If you are looking for passing values from the client side when using Ajax, then probably setting a hidden field with the parameters is going to pass them on to the next request.

Resources