Getting a loop when using link_to :back - ruby-on-rails

I have this structure for the table course:
Search page -> Result Page -> Edit Page -> Show page
When i go from result page to a specific course edit page, i edit it, and end up on the show page, but when i hit back, i get a loop from show to edit, and back to show and so on.
I want the edit page to back to the result page if it came from there.
im using this on both:
<%= link_to "Back", :back %>

When you actually update your record having edited it you're likely to be doing a redirect from an update action via a put request to show. Even if you're not, and if you're defying convention and updating from the show action, you're trying to navigate to a post action with a get request. If I understand you correctly, you want to be able to edit from either the search result or the show page. What you should do is define a method that allows you to store a location in the session on demand. Put it in the application controller and it will be available to all of your controllers.
# copy this into your application_controller.rb file :
private
def store_location
session[:return_to] = request.request_uri
end
#copy this to the top of your item_controller.rb file:
before_filter :store_location, :only => [:search, :show]
#replace your <%= link_to "Back", :back %> with
<%= link_to 'back', session[:return_to] -%>

Related

Rails link_to :back redirect itself in a loop on form submission error

Using Rails 6, but this should be applicable to any Rails version that supports the Rails back link with referrer. Here's the code:
# posts/new.html.erb
<%= link_to "Back", :back %>
<%= form_with model: #post do |form| %>
...
<% end %>
Here's the page flow:
Homepage -> View Post New -> Click Back -> Go back to Homepage
Homepage -> View Post New (/posts/new) -> Submit empty form -> Returns to Post New (/posts/new) with error (because validation fails) -> Click Back -> Goes back to Post New page (/posts/new) again -> Click Back -> Goes back to Post New page (/posts/new) again
On case 2, when I check the href of Back link, it keeps pointing back to /posts/new. This is due to referrer I think. But what is the workaround, so that it should go back to Homepage instead?
In Rails you don't redirect back when the user submits an invalid form - you render the view containing the form and send it back in the response body.
class PostsController < ApplicationController
# ...
# POST /posts
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
# renders the posts/new.html.erb template
render :new
end
end
# ...
end
When the user submits the form they are send a non-idempotent POST request. You should show them the results of performing that action whether if it's creating a new resource (usually a redirect to the new resource) or by displaying the form again with errors.
You should not redirect back to the idempotent GET /posts/new route. That would require you to pass any parameters back as query string parameters or lose any user input.
This is not just a question of REST semantics or following conventions - this avoids the browser history issues that plague redirecting after a form submission and cache issues that could arise if you are using a reverse proxy to serve GET requests.

Rails: How to redirect from home page and keep possibility to open it from navbar

How i can redirect logged users from home page and same time keep possibility to open home page by clicking it in the menu.
I using high_voltage gem and my pages controller looks like:
private
def redirect_logged_user
case params[:id]
when 'home'
if user_signed_in?
redirect_to books_path
end
end
end
So when user open http://example.com and he is logged he will redirected to books page (http://example.com/books), but same time i need to keep possibility to open home page if user click "home" at the navigation bar.
For such kind of functionality you need to pass extra variable while calling from navigation bar and in your redirect_logged_user method you need to manage redirect accordingly.
<% link_to Home, home_path(:nav => true)%>
This will pass extra parameter nav=true with request http://example.com?nav=true
Now you method should be like :
def redirect_logged_user
case params[:id]
when 'home'
if user_signed_in? && !params[:nav]
redirect_to books_path
end
end
end

Rails form that redirects to show page

I'm using Rails 4 and have a Policy model with a field policy_number.
I'd like to create a (search-like) form where you input a policy_number and it redirects you to that Policy's show page. I'm not sure how to go about this, should the form's action be policy_path or something?
Thanks!
The biggest problem here is that the user is inputting the policy number in the search form, so you don't have access to it at the time the form is rendered. Without using JavaScript, you won't be able to go directly to the policy by policy number entered.
Here's a possible starting point, though. Create a PolicySearchController with an index method, add a route for it, and create a simple form.
app/controllers/policy_search_controller.rb
class PolicySearchController < ApplicationController
def index
policy = Policy.where(policy_number: params[:policy_number]).first
if policy.present?
redirect_to policy
else
redirect_to :policies, alert: "No matching policy found."
end
end
end
config/routes.rb
resources :policy_search, only: :index
app/views/policies/index.html.erb
<%= form_tag policy_search_index_path, method: :get do -%>
<%= text_field_tag :policy_number -%>
<% end -%>
Now you can iterate on this to add JavaScript, fuzzy matching, etc. if desired.

destroy controller routing to show view (rails 4.1.8)

Been struggling through the rails guide build a blog tutorial. Have, I think, everything working aside from the destroy link on the index page. When clicked, it routes to the show view for that article that's clicked on to be deleted. this is from the index.html.erb. any help is greatly appreciated.
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
private
def article_params
params.require(:article).permit(:title, :text)
end
Code:
<%= link_to 'Destroy', articles_path(#article), method: :delete %>
The reason why the method option is required is because a browser cannot send a DELETE command necessary to perform the action. Providing the option sets an extra attribute and lets rails know the action you are about to perform should be routed to the deletion route instead of a simple show
Have a look at:
Are the PUT, DELETE, HEAD, etc methods available in most web browsers?

Redirecting to different actions without using a query string

I am trying to figure out the best way to do the following (there are a few ways I can think of, but I want to know what the best way to handle it is):
A user is putting together a shipment, and then clicks the "Send" link, which sends him to the /shipments/:id/confirm page. The confirm action checks to see if the user has a completed ShippingAddress; if not, it sends him to the ShippingAddress#new. (If he does, it render the confirm page.
I want the user to be able to complete the ShippingAddress#new page, submit it, and then be redirect back to the /shipments/:id/confirm. How can I do that? How can I pass the :id to the ShippingAddress#new page without doing something like redirect_to new_shipping_address_path(shipment_id: #shipment.id) in the Shipment#confirm action? Or is that the best way to do that?
class ShipmentsController < ApplicationController
def confirm
#shipment = Shipment.where(id: params[:id]).first
unless current_user.has_a_shipping_address?
# Trying to avoid having a query string, but right now would do the below:
# in reality, there's a bit more logic in my controller, handling the cases
# where i should redirect to the CardProfiles instead, or where I don't pass the
# shipment_id, and instead use the default shipment.
redirect_to new_shipping_address_path(shipment_id: #shipment.id)
end
end
end
class ShippingAddressesController < ApplicationController
def new
#shipment = Shipment.where(id: params[:shipment_id]).first
end
def create
#shipment = Shipment.where(id: params[:shipment_id]).first
redirect_to confirm_shipment_path(#shipment)
end
end
[In reality, there is also a CardProfiles#new page that needs to be filled out after the shipping address is].
Try calling render instead of redirect_to, and set the id into an instance variable. Adjust the view logic to pull that instance variable if it exists.
#shipment_id = #shipment.id
render new_shipping_address_path
In the view
<%= form_for #shipment_address do |f| %>
<% if #shipment_id %>
<%= hidden_field_tag :shipment_id, #shipment_id %>
<% end %>
I don't know your view logic entirely, but giving an example.

Resources