Rails 3 respond_to :html and preventing double content - ruby-on-rails

I'm trying to prevent double content in combination with respond_to. So I added to my controller:
respond_to :html
In combination with respond_with this works great so far, butt he user can still access my pages using either:
/my/page
/my/page/ or
/my/page.html
I'd like to limit this to one of them (preferring the first one). Removing formats fully is not a solution, because I might like to respond_with json or xml someday.
Thank you in advance for any tip!

Doing this will be pretty unpleasant and will also make your site more difficult for users to, well, use. Unless there's a really, really compelling reason for you to do this, I would just work with the Rails defaults and accept the fact that you have a lot of different URLs pointing to one resource. Doing so really shouldn't hurt you.
Again, you should probably not do this. But if you really wanted to, you could play with routes.rb to manually create the routes you wanted. Check out the Rails routing guide for more information on how to generate Rails routes that look more like what you want.
That said, that still probably won't be enough to get rid of my/page/ and my/page pointing to the same place. If that is really, truly necessary, I would consider dropping Rails entirely and using a different framework like Sinatra, where you have very fine-grained control over routing (since the framework makes no routing assumptions at all).
But the best thing to do is probably just accept the routes as they are and move on.

Related

Rails Mass 301 redirect - will it cause routes.rb issues?

I have a large set of URLs that I need to redirect (over 600), which are all unique. They're all named URLs (i.e. example.com/this-shoe-name and example.com/that-blue-product), so I can't use something like this to semi-dynamically do this, and they also don't redirect to anything similar (i.e. www.example.com/this-shoe-name redirects to newexample.com/catalog/shoes vs. newexample.com/this-shoe-name).
I guess I'm fine writing 600 redirect rules (though I'd rather avoid it), but that seems to me like it's going to make the routes.rb file rather unwieldy.
Short of writing 600 rules in routes.rb, is there a best practice way to do this? Is having 600 rules in the routes.rb going to make my app slow/break things?
I don't know if it will slow routing processing down, but I doubt it. As long as you put them at the end, do you really care? Like you I don't like the messiness it causes.
An alternative would be to create a catch all route or rescue the 404 and then look up the URL in a "old urls" table and if a match is found redirect to the new url.
You might even be able to tie that "old url" into your Product or Category model as an attribute. Then search that and if found redirect to the correct url for that model. I've done that in the past with pretty good success. Bonus is that you can expose it in an admin tool and make the client enter them all in :-)

Does Rails automatically keep track of page name changes and create 301 redirects?

Is there a gem that does this or is it baked in even? My understanding of things now is that anytime I change the path for a page (perhaps I do it for SEO) I need to create a new 301 redirect. Shouldn't this be handled automatically?
If so, how is it handled automatically and how do I make use of it?
Thanks!!!
This is a rather complicated question and depends a lot on how your routes look right now. The simple answer is: no, this is not handled automatically by Rails.
The easiest way to handle redirects like this is in the routes.rb file, redirect from the old path to the new one. Something like this:
match '/products/:id', redirect("/new_products/%{id}")
You can learn more about this kind of redirect at the Rails routing guide.
If you're changing just one instance of a product, then obviously this doesn't make a whole lot of sense -- you can't do this for every changed object. In this case, we'll assume that you aren't using standard ID-based routing; if you were then this wouldn't be a problem. (Since the ID wouldn't change, instead it seems likely your routing is based off of a field that does change -- like name or date or something.)
In this case, you probably want to extract the routing field away from whatever it currently is and into a slug column of its own. I recommend the really excellent friendly_id gem for this: it allows you to automatically generate slugs, and its history module allows you to perform lookups with an object's old slug.
Then, you can look up an object by its ID, its slug, or any of its old slugs, if you find it necessary to do so.

How can I omit controllers for two models in rails 3 routes?

I'm building a rails3 application and at the moment I have the following line in my routes.rb file:
get "/:id" => 'tapes#show'
In other words, you can show a Tape using website.com/tapes/1 and also by using website.com/1
(I am also using friendly_id gem so the user sees in fact a friendly URL in the form of website.com/tapename)
Now, what I would like to achieve is to do the same thing for Users pages. So instead of showing a User page using website.com/users/alex I want to be able to also use website.com/alex.
Is there a way to implement this 'users' logic in routes.rb together with the existing 'tapes' rule and somehow set a priority?
So if someone accesses website.com/alex my app would search if there is a User record with id 'alex' and if none is found then look for a Tape with id 'alex'.
Could I use some kind of Advanced Constraints in routes?
Any ideas?
Many thanks for the help,
Alex
Rails would have no way to determine which controller you were trying to access. The only way that this would be possible, is if either:
you could determine which model it would resolve to based upon some regular expression on the name.
or
You knew that user names and tape names never conflicted, and were willing to suffer the cost of hitting the database to resolve the correct controller.
This is probably a bad idea for a number of reasons, it would have performance implications, it also doesn't conform to RESTful principles, and it would probably be confusing to users.

Create RESTful resource manually

in order to better understand how RESTful works in Rails and thus become better at producing such code, i would like to manually create a resource from scratch. I generally know how to setup routes, controllers and the likes, but i would be interested in checking out some tutorial(s) that describe just that in detail.
Do you happen to know of anything ?
I would first advise you to get your REST concepts cleared. In my opinion, REST is fairly misunderstood concept in the community. I would recommend understanding it first without sticking to rails or any other technology for that matter. Ryan Tomayko has written a killer blog post about it. You also might want to read Roy Fielding's paper, if you are into it.
Once you understand the concept clearly, implementing it in a technology is not so hard. For rails, create a blank controller and start adding the actions one by one based on your understanding of REST. Think about exactly are you doing in the action. Are you fetching the data and showing it to the user? In that case, you need to make sure that the action can only be called with a HTTP GET verb. Are you updating a record in that action? You probably should only be accepting a HTTP PUT verb for that action and so on... Here are some resources found on some quick googling which look good to me.
http://blogs.sitepoint.com/2008/02/04/restful-rails-part-i/
http://s3.amazonaws.com/ozonesoft.net_public/RESTfulRails.pdf
I would recommend reading the standard documentation of routes in rails. I think that's enough. But to understand what makes an app a RESTful app and what doesn't is the key.

Rails: RESTful resources: Worth using or inflexible/overrated?

I've been messing about in rails the past 2 months and so far everything's going well - but there's one area I'm a little doubtful on.
I keep hearing about the joys of RESTful rails resources: that is, a 'resource :foo' in config/routes, and your 7 restful actions in the controller.
Except for very simple things (eg stuff that's 99% done by running 'generate scaffold'), I find it's less convenient to try squeeze my project functionality into that approach than to just match urls in config/routes one-by-one and do each action as needed.
But I keep getting the sense that I'm wrong, and that in all but the most extreme circumstances, RESTful resources are the way to go.
So:
(a) Can anyone offer an opinion on this?
(b) For experienced rails folks, what % of your routes in a typical project are :resources and what % are coded action-by-action?
Cheers...
Resources are convenient, but they are not a "one size fits all" feature. Some things just don't make sense with the 7 methods.
Keep in mind that you can:
Exclude specific methods with :except.
Include only specific methods with :only.
Add your own methods to the resource.
So they aren't as inflexible as you may think. But if, after taking those 3 points in mind, the resource just doesn't "feel right", skip it! REST was never meant to replace regular routing, it just tries to abstract away the most common use case.
If you skip out on RESTful resources completely, you'll be missing a ton of free functionality. Use it wisely and you'll be fine.
Generally I start a project with the REST architecture in mind. I build out my basic functionality this way, but as the project/website progresses I write more and more views that do not fit into the RESTful architecture. Marketing sites and parallel functionality are perfect examples of this.
Here is an article on the approach:
http://ablogaboutcode.com/2010/11/22/to-be-or-not-to-be-restful-ruby-on-rails-best-practices/
Before you get started, here are some questions you might want to ask yourself:
Does this controller/view deal primarily with an object/entity like a Post, Blog?
Are create, update, delete, edit and new actions all going to be available on the web?
As a guideline, if you answer YES to these two questions, then it’s probably best to start with REST and expect that you will eventually use the architecture as a building block for additional actions and views you might want to perform. Otherwise, pick a URL that best represents what the action will show or do (/archives, /tour, /december-offer) and make sure you use the proper HTTP Protocols (GET for display, PUT for update, DELETE for removing and POST for creating).

Resources