I have an app I didn't write, that I have to work on to change a few stuff.
One of this stuff i have to work ok, is a weird issue where we have renamed a content's title - and the URL was changed too by doing so. Yet, the resourse is now available at the old and at the new URL alike - and google sees it as duplicated content.
Is this a knows issue with Rails?
Can I fix it by redirecting the page to the new one, kind of like a 301 redirect?
Is there any code I could post to make the issue more clear, or is there any direction you can point me to?
Are you using friendly_id gem by any chance?
If you are, simply redirect the page to the new one by adding something like this to the show action in your controller:
...
def show
#item = Item.find params[:id]
if request.path != item_path(#item)
redirect_to #item, status: :moved_permanently
end
end
...
Could be an issue in your Routes File. Check to see if the path is still there, and remove it.
Related
Is there a simple way to write a ruby if statement to redirect a dynamic page to a static page?
I’m writing this in my pages controller where the site pages are generated. This is what I’m attempting to do.
If “/index/page1”
redirect_to “page2”
return
end
This redirects all the pages created in the pages controller to “page2”. I know the syntax is incorrect. I need help in writing out the correct way to test for the first condition.
Any help is appreciated. Thank you!
Here is an update / more information to my question.
Here is my show action in the PagesController
def show
#page = Page.find_by_url_path("/#{params[:url_path]}")
layout = "templates/#{#page.pageable.class.name.underscore}"
respond_to do |format|
format.html { render layout: layout }
end
I need to write an if statement that looks for one specific URL that gets generated. This page is created by the show action.
e.g. https://host.com/products/page1
Then redirect it to another specific URL. This is a static page on the site.
e.g. https://host.com/page2
I am having difficulty in writing the if statement to find the first page. This is what I've tried.
if "/products/page1"
redirt_to "/page2"
return
end
Depending where I put the code within the show action, I either get a double render error (as subparry explains below). Or I redirect all the pages generated through the show action to "/page2".
This application was written by a more experienced Ruby developer and I'm doing my best to maintain / update it. If I need to post more detailed information, please let me know. Thank you.
Well, as usual with these kind of requirements, there are many ways to achieve it.
As you know, different pages (views) in controllers are represented by instance methods (or Actions), for example I can imagine your PagesController looking something like this:
class PagesController < ApplicationController
def page1
# do something...
end
def page2
#do something else...
end
end
So, the easiest way would be to trigger a redirect from page1 redirect_to "https://host.com/page2", I don't know the reasons behind the decision to redirect. If it is a temporary redirect, it might be the best solution because of ease of change later, but if it is a more permanent redirection, I would implement it at the web server level (Nginx for example)
It depends on your use case.
PS: Don't forget that if you redirect in your action, it does not imply a return, so if you have more code below and another call to render or redirect, it will fail (double render error) so either you remove further renders/redirects or insert an early return.
EDIT:
Ok, now I understand better your case. You have a model called Pages which has a column called url_path which details the location of each page.
So, if I understand correctly, you'll have to do the conditional statement like this:
def show
if params[:url_path] == 'page1'
redirect_to 'https://host.com/page2'
return
end
# Rest of action code...
end
I don't know for sure how are paths stored in url_path, but you get the idea!
PS2: When you write if 'products/page1' you are basically saying if true and always entering the condition because only nil and false are falsy values, everything else is truthy.
When a user makes an invalid create request for a resource, I want to send them back to the form and show them an error. As far as I can tell, calling render "new" is the standard way to do it.
This seems like a bad idea to me, because the create request has taken the user to /resources, whereas my "new" form is otherwise at /resources/new. If I use render "new", the URL in the address bar will not reflect what the user sees. If they make a GET request there, they'll end up on a different page.
I thought I could solve this problem by using redirect_to new_[resource]_path, but if I do that I lose access to the form data and errors. Surely this is not an uncommon problem. Is there a better way to deal with it?
I have the same problem with edit/update and other form/submit action pairs.
TL;DR:
class ResourcesController < ApplicationController
def new
#resource = Resource.new(resource_params)
if resource_params.present?
#resource.validate
end
end
def create
#resource = Resource.new(resource_params)
if #resource.save
redirect_to #resource, notice: 'Resource has been created'
else
redirect_to new_resource_url(resource: resource_params)
end
end
private
def resource_params
params.fetch(:resource, {}).permit(...)
end
end
I asked this myself as well in my early beginner days, on why Rails scaffold generator generates the def create action to render :new if saving failed, instead of redirecting to the correct URL just something like above, which would confuse the users because their URL would have changed from /resources/new into /resources even though they would still see the exact same Resource form on the page, and therefore they would not be able to reload the page or copy this /resources URL (for example, if they want to share this URL to someone else), because should they share this /resources URL, the others would see a list of Resources on the page instead of what the original user would have expected to see from the copied URL: which is the form page.
After the user submits the form, the URL they see on the address bar should have changed into POST http://localhost:3000/resources instead of just simply http://localhost:3000/resources. The browser hides the HTTP Method being used, that's why this leads to their possible confusion that /resources seems to have been both sometimes: a form page, sometimes a list of resources page. However, speaking of UX, every time anyone enters something or pastes something in the URL address bar of the browser, it is always automatically implied to be doing a GET request. Therefore, it makes sense for the browser-developers to just simply hide the HTTP method (i.e. GET in particular) from the users as to not confuse them.
From my answer above, I only used something like this once before (because there was a certain action that demanded me not to change the URL from the referrer form page). However, I normally render :new instead of redirect_to new_resources_url, simply because:
a redirect_to new_resource_url(resource_params) would take twice as much time and data-transmitted than simply rendering :new. Why? Because you redirect (opening up a new request) with the exact same parameters anyway. Just imagine if your form page is soooo big, and has so many input fields.
and also that there's a limit to how long a URL can be, of which won't guarantee to work if you have a very big form with very long text fields. See this SO
Updated:
As you have said though, why not just POST /resources/new instead of POST /resources when the form is submitted, right? This will solve the redirect_to new_resource_url(resource_params) problem I've shown above, because the URL after form-submit would have been the same and you can just simply render :new, then. And I actually agree on that, and I've used something like this also before long time ago. The main reason I don't use this is that it is not inline with REST standards. That is: POST /resources/new means that you're creating a Resource object "inside" the resources/new location, which then means by REST, after submitting the form, I would and should be able to access this newly created resource by doing something like GET /resources/new/the_newly_created_record, except that... you can't.
But you can still use POST /resources/new, although I would not recommend it on a normal Rails application like yours, and however strictly discourage it on an API-based Rails application.
You may be overthinking this. How about get /resources the index page vs post /resources the create action? Same url in the address bar!
It's not a problem. Neither a technical problem or an aesthetic problem.
render "new" means: render this template, not: go to this route. And although templates often have the name of the corresponding action, it's not a requirement.
I'm running an e-commerce using Rails 2.3.8 and spree 0.11.0 (I'm also rebuilding the whole site with the latest rails/spree version but this problem I need to fix right away). I need to redirect the user to a customized view at the moment that the he enters the creditcard information. I have something like this inside my orders_extension.rb:
CheckoutsController.class_eval do
update.after :redirect_to_thank_you
def redirect_to_thank_you
redirect_to '/somewhere'
end
end
It actually goes through this action, but I want it to be the LAST action. It keeps doing more requests after my call.
Any help would be appreciated.
I think what you're looking for is a completion_route. You can see it being used here. Right now, it redirects to the Order show page. What I would do:
Spree::CheckoutsController.class_eval do
def completion_route(_custom_params = nil)
redirect_to main_app.order_processed_path
end
end
I am trying to link my own app to the same page, but have it add #googtrans(en|fr) or some other language code to the end of the link so google will render it as a different language. It will work if it is going to a different page in the site, but for some reason if it goes to the same page it won't refresh. I have tried several different ways to do it, but so far have not had any success. Right now I have links that say <%= link_to "#googtrans(en|ko)" do %> Link Here <%end%>.
Any help would be appreciated.
I would do something along the lines of creating a helper method. Bear in mind I am relatively new to Ruby but I would attempt.
helper_method :translate(language)
def translate(language)
#whatever = params[:whatever]
respond_to do |format|
format.html { redirect_to #whatever_url(language) }
end
end
Then link to it with what you want the language to be.
Link Here
I may be way off base but that should get you going in the right direction. That way when you link to it, it will push it through an action that should refresh the page.
I've made mistake and allowed two different routes pointing at same place. Now I've got troubles with duplicated content.
News could be viewed in two ways:
http://website.com/posts/321 and http://website.com/news/this-is-title/321
I want to fix this mess and my idea is to check by what link user is coming. For example if someone will came through http://website.com/posts/321 I would like to redirect visitor to correct route: http://website.com/news/this-is-title/321
My very first idea is to validate request url at Post controller and then in if statement decide about redirecting or simply displaying proper view. Is it good conception?
I think it's not the best fit.
You should do this at routes level using the redirect methods.
I don't think you should bother, take a look at canonical url's if you're worried about SEO
In your posts_controller.rb show:
def show
return redirect_to post_path(params[:id]) if request.fullpath.match /(your regex)/i, :status => 301, :notice => 'This page has been permanently moved'
#post = Post.find(...)
end
return redirect_to is important because you can't call redirect or render multiple times
match the regex on request.fullpath
if you're super concerned about SEO, set the status to 301. this tells search engines that the page has been permanently moved
the notice is optional and only for asthetics after the redirect in case the user has bookmarked the old page url