Should RoR urls look like /users/register or /user/register? - ruby-on-rails

Should urls have pluralized words in them or singular?
I personally like:
/user/register
Is this against the 'convention'?

I think it depends on the way you think what it is.
From the perspective of syntax, it seems to me /user/register make more sense. While from the perspective of resources, the /users/register make sense.

Is there more than one User in your application?
If so, the standard /users/register would be the conventional REST url scheme for registering a new user - assuming this results in a user being created.
You might consider the more convention /users/new unless "register" really is a different action than creating a new user somehow.

Yes, that's against the RESTful convention of /users/new. However, I don't see much of an issue with using more user-friendly URLs, especially if you preserve the original REST URLs too. In all my applications, the first thing I do is setup routes to /signup, /login and /logout.

Plural form controllers are the convention, because it makes the most sense, it implies /users/ will be an index of users etc.
However, the only time I would consider using a singular form controller name here is if, for example: your application is a little more closed, and users cannot view/modify each other (no index), and you were using this controller only to allow users to register and view/update their own details. In that case the singular form can be a sensible option, but it's still a matter of preference.

Related

How to be RESTful in Ruby on Rails?

I have a decent amount of experience with rails, but I've always been a bit ad hoc with my development methods. I'm curious about how to be properly RESTful in rails. Here's an example of an app I'm working on now:
I have a few models, including a User, Pack, and Product model. The models each have a controller associated with them. If I want to create a new page called 'Dashboard', on which the User can create new records on the Pack model, as well as see their account information, how do I do this in a restful way? Do I create a new controller called Dashboard? Or do I add it to a controller that defines my 'Static Pages'? What's the best practice regarding pages that aren't exclusive to the actions on one model?
Thank you in advance!
Yes, basically you want one controller per resource. In this case the resource is a combination of things but since you've identified a singular meta-resource (a "dashboard") it makes sense. So, I'd create a DashboardsController and then have a route like:
resource :dashboard, only: :show
Then you can use dashboard_url for links to the dashboard.
NOTES: The singular resource in the routes file is important because it indicates you don't have a list of resources, just a single one. This means there won't be an index action and the show action will be the default -- thus dashboard_url doesn't require a resource to show to be passed to it. And, regardless, controllers are named in the plural -- thus DashboardsController.
I would create a DashboardsController despite not having Dashboard model. Then to maintain REST principles have a controller method :new and controller method :create. Simply disply the information on the dashboards/new.html.erb but have the form post to the :create controller action.
To supplement the answers already given, REST really exists to make an easily-consumable API. (Notably, Roy Fielding's work is in the area of APIs, and REST is built on top of HTTP methods that HTML doesn't allow.)
This has been a common stumbling block since RESTful routing debuted in Rails; people get the impression that every controller now needs to be RESTful and that the front end and API should never diverge. Frequently, though, the front end and API have different needs.
For resources you want to be accessible via an API—Products, Users, Packs—trying to be RESTful is ideal. For those sorts of uses, pdobb's advice to have one controller per resource is generally exactly what you're looking for. They make sense in the context of an API being consumed by a machine.
But what about the dashboard? Dashboards are generally an HTML view intended to be rendered in a browser and viewed by a human being.
Does a "dashboard" resource make sense in the context of an API? Would it make more sense to instead make that data available in other resources? Is that data available in other resources?
Even if a "meta-resource" aggregating data still makes sense, would it be more logical if the API version had another name, like AccountSummary?

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.

Rails - What is right way to do a show page for a nested resource

since I am only going to be showing that one item, do I just have (example)
/the_thing/23
or do I still go with the /the_group/1/the_thing/23
I know I need to appropriately nest and have associations for forms and using nested routes for links, but for a show page is my link to it nested or not?
i.e. should I still show it within the context of its master or just on it's own. In this case the resource cannot be updated without the nesting i.e. on it's own.
Will a main intent be to show links back to the group?
This question is ONLY about the show page.
This is just a matter of choice, you can even create both routes depending on the context.
You should just ask yourself if it makes more sense for the user to see one url or the other: it's sheer user experience here.
It's true that it's only a matter of choice.
But consider a case, you have a Post model and Comment model, and Comment is a nested resource of Post. It does not make sense to have a separate route for show action of Comment, as showing comments without the relevant post makes no sense.
Hence, it's case specific as well.

ASP.NET Multi tenant route configurations

This is not a question of how to implement multi-tenancy. What I am looking for is the ability to optionally override the default application routes when required.
A simple case is that I have a route that generates a blog url like so:
http://[domain]/blog/post-slug
My configuration is blog/{slug}
However, some tenants do wish to call their blog "news". Although I can change all references blog in their views, I can't do it in the URL.
I would like a simple way of overriding these route configurations without changing the "core" codebase.
One thought I had would be to use named routes and then use this to swap out route configurations when the app starts. I should add that multiple tenants will not be using the same application instance, just the same codebase.
Thanks,
Ben
You can always add a route using a regular expression. There is also a great tool on figuring out what routes to add to get what you want.
http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
What about if you have a filter that detects which type of user is accessing the action. If it is one who wants the word news, you can redirect them to a controller called news - which inherits all the functionality from blog.
I can't say I'm 100% confident, but I think it might work.

Resources