This is confusing me so much,
I have 2 models client has_many :invocies
and invoice belongs_to client
,
I have my root
set up to index all invoices
and invoices
can also be accessed through the clients show
View. I have a back button in my invoice show view
that links back to the client:id
that the invoice
belongs to
Back link form invoices/show
<%= link_to 'Back', client_path(@invoice.client), class: "btn btn-primary" %>
This works fine but its really awkward to launch invoice show
from the root path and then click back
and be re-directed to the client show
view. Is there a way to go back to the root_path
or show 2 buttons in an if statement and show one depending on how a user launched the invoice show view
in the first place? Completely stuck.
Here is my routes file
resources :invoices, only: [:new, :create, :destroy, :index]
resources :clients do
resources :invoices, shallow: true
end
root 'invoices#index'
A simple backlink:
link_to 'Back', :back, class: "btn btn-primary"
should do in this case. It will use the HTTP_REFERER
or a Javascript function to get to the previous page. See the documentation for more info.
Update:
I you need some exceptions to the "simple back link" rule, you must create a custom solution. One such solution might be that you use link_to :back
by default but override it by accepting a custom "back_path" parameter in special cases. You can create a custom helper to do that.
The following example uses the standard back link by default but allows the previous page to set a back_path
parameter that will be understood by the back_link
helper.
# application_helper.rb
def back_link(params, name: "Back", class: "btn btn-primary")
if params[:back_path].present?
link_to name, params[:back_path], class: class
else
link_to name, :back, class: class
ens
end
Now you use the link normally in your views:
<%= back_link(params) %>
And when you want to override the default behavior, simply pass the back_path
param. You will pass this parameter typically at the page that you want to return to. Then you'll have to pass this parameter on through all further pages and/or redirects.
Say, for a non-trivial example, that from the client show
page you can click a link to create a new invoice and then be redirected to the invoice show
page and from there you want to click the back link and get to the client show
page again.
So, add a link to the clients show page, with the back_path
param pointing back to this page:
# views/clients/show.html.erb
<%= link_to 'New invoice', new_invoice_path(@client, back_path: client_path(@client)) %>
In the new
page form, you'll have to add a hidden_tag
to pass on the back_path
param:
# views/invoices/_form.html.erb
<%= hidden_field_tag 'back_path', params[:back_path] %>
Next, in the controller's create
action, you will also have to pass this param upon redirect:
# controllers/invoices_controller.rb
redirect_to invoice_url(@invoice, back_path: params[:back_path])
And finally, you can now use the back_link
helper to display the correct link:
# views/invoices/show.html.erb
<%= back_link(params) %>
I know it's ugly but that's the way it is... Moreover it's not an ideal solution as typically you want a hierarchy of back links as you browse the pages (and come to a page from different paths) and this solution solves only the first back link. But I think it's something to build upon.