Resource mapping in a Ruby on Rails URL (RESTful API) - ruby-on-rails

I'm having a bit of difficulty coming up with the right answer to this, so I will solicit my problem here. I'm working on a RESTFul API. Naturally, I have multiple resources, some of which consist of parent to child relationships, some of which are stand alone resources. Where I'm having a bit of difficulty is figuring out how to make things easier for the folks who will be building clients against my API.
The situation is this. Hypothetically I have a 'Street' resource. Each street has multiple homes. So Street :has_many to Homes and Homes :belongs_to Street. If a user wants to request an HTTP GET on a specific home resource, the following should work:
http://mymap/streets/5/homes/10
That allows a user to get information for a home with the id 10. Straight forward. My question is, am I breaking the rules of the book by giving the user access to:
http://mymap/homes/10
Technically that home resource exists on its own without the street. It makes sense that it exists as its own entity without an encapsulating street, even though business logic says otherwise.
What's the best way to handle this?
EDIT! In spirit of becoming a good StackOverflow citizen, I've come back with a supported code block for how to implement they above.
map.resources :streets,
:has_many => :homes
:shallow => true
This will create both types of routes that I was looking for.

If your Home records can only belong to one Street, then the relationship won't be confused when you're examining a Home individually. You'll still be able to back-track to the associated Street record for whatever reason.
It's in situations where you have a many-to-many relationship that de-nesting your REST structure can get you into trouble. If a particular record only makes sense in a particular context, and you remove that context, obviously there is confusion.
I think in your particular case you may not need to implement both approaches, but instead go with the "flatter" approach that reduces the complexity of the URL.

Nope, that is how shallow routes work and are used a lot.

I really like this approach. I recomend to read it. In short this article says that you shouldn't nest your resources more then 1 level. And if it is possible that nested resource can be shallowed, then do it.
In one of my applications I really messed things up with nested resources. I go even to 3 or 4 deep and it become a nightmare...
Nesting is really nice if it makes things simpler. If not, give it up!

Related

Should resource ids be present in urls?

In situations where the resource id can be identified by other means (such as current_user for pages that require authentication), is it a good idea to omit the id from the url? (For example, /students/1/homework to /students/homework).
Also, would this have any impact on the restfulness of the urls? I am suspecting it does for HTTP verbs, but for custom actions I am not so sure.
I suppose it is down to your application and what is useful for clients to see. If your connecting user is an admin who can see all students homework, then the /students/1/homework path makes sense, however if it will only ever be students using this resource then the /students/homework makes more sense.
Essentially the latter could be thought of as a namespace for all student resources.
I have found it very useful to split these resources by namespaces as to not confuse client writers and keep your authorisation very clear (who can see/do what).
In your example, the 2 URIs identify different resources:
the homework of user #1,
the homework of the current user.
The choice depends a lot on which resource you think people will want to refer to (by e-mail or by bookmark for example).
I don't think the second solution is unRESTful, but I would prefer the first one, since it is compatible with a lot of additional features (e.g. teachers could access the representation of students' homework).
URLs should always point to one specific resource. They can either be absolute or relative. Think of it as a filesystem. In some cases (security/scalability) you can't allow listings.
Session-based / Relative resources /students/me, /students/latest, /students/latest/homework/lastest
Absolute resources /students/3, /students/3/homework, /teachers/3/homework/3

Best practice for choosing nested resources in Rails?

What criteria do you use to decide whether or not to nest resources?
In the past, I have chosen to nest when the index action on a resource makes no sense without scoping to an associated resource (the parent).
Even as I write the above criteria, I realize it is ambiguous at best.
A colleague has stated:
Nest resources because it captures the relationship of the associated models visually in the url structure... And it makes it easy to modify the url to get back to just the post. If I see /posts/123/offers/555 -- I know that I can go to /posts/123 to see my post. Where as if I just saw /offers/555, I'd have no way to get back to the post other than manually navigating through the site.
To me, manipulation of the url by users should have no bearing on the architecture of the application, and flies against what I understand to be the generally held principle that nested resources should be avoided if at all possible. Additionally, this argument would seem to support multiple levels of nesting, which again, pretty much every article I read advises against.
What has been your experience?
I nest routes, as you put it first, when the later things in the route doesn't make sense without the former. Comments on a blog would be nested under resources articles because, though perhaps you want display an individual comment on it's own page (who knows why...), a comment belongs to an article.
This also has controller implementations. If you know the article, then you can find the specific comment scoped to the article. This makes for more effective queries.
Also, your colleague was correct that you have to deal with users messing around with your routes, though he had the wrong reason. It isn't for their convenience, but for their security.
Let's take an Amazon-like app with users and orders. If I am at users/5/orders/2 then I think "hey! I can just change that 5 to a 4 and then see someone else's orders!" If you don't scope orders, then the controller-level logic for authorizing a user to view orders/2 becomes far trickier. Scoping to the user allows for current_user.orders.find(params[:id]) in the orders controller. Current user can be found based on authentication so that they cannot just swap ids in the URL and become someone else.

RAILS 3.2 - Nested resources has many : through relationship

Guys I am becoming completely nut on this...and can't figure out at all how come out of all this troubles.
I really need an holy help, or at least some suggestions about tutorial and guides about this problematic.
I believe that this is a very common task in many app, but I can't find nothing that help in this sense, not on stackoverflow, not on google, not on other rails forums that I know...I start to feel like a dumb!!!
Problem
(1) Models (the models that are involved)
User.rb
Item.rb (is nested in user: e.g. user/3/item/5)
(2) What I'd like to do
The current_user (the user that is logged in) can create an Item, and in the same form can decide to share it or no with many other users.
In this way, the item will be visible and accessible also for this users that we shared it with.
I understand that what is going to be involved here is:
(a) has_many :through relationship between item and user
(b) a joint table that we can call sharing (with item_id and user_id)
(c) eventually using different name for the user and use a :class_name to point to user
This is not hard to implement (and there are plenty of examples around).
What is really a mess, instead, is how build the controller (item controller), in order to perform in one shot, the creation of a new item, and the sharing operation (this means setting up the parameter in the joint table, and eventually create as many records as many users we are sharing with - array?)
And the other problem, that obviously is related with the controller, will be the view...how put all this in a single form, and allow the current_user to just click the button, and perform the item creation + the sharing operation?
Last thing, but not the least, how I need to deal with the fact that User is the same model of current_user??
I really don't know what I need to read or look up in order to let this work, I would love to see some example code,but at the same time I'd love to really understand the logic in all this, in order to be able to replicate it in other scenarios.
Please someone help me...I can't really move on in my app development without doing this, and this is also a crucial part of all the project.
Thanks so much for every small bit of help that I will receive.
Ok I have solved all my problems...that was not an hard task at the end (it's always easy saying that when you solved the issue:))
The only doubt that I still have is with the rails name convention:
Can be possible that using a name like sharing, for the joint model, that the final -ing is not very well handled by rails?
After many tentativeness performed to try to fix my problem, I discovered that everything was set up properly, and that just changing the joint table name from sharing to share, let the magic works!!!

Is it OK to create meaningless singleton resources just to stay RESTful? Rails

In the process of making an ebook, users have to edit its content, edit its metadata, choose marketing options, (such as pricing and distribution) and publish.
I started to put each everything inside the Book resource (contents, metadata, marketing options etc)
Then each step of the process (contents, metadata, marketing) is an action inside BooksController.
But Books started to grow a lot in terms of attributes and actions.
I'm wondering if it is better to force RESTfulness by creating singleton resources, each associated to their respective book.
The routes would be:
/book/12/content/edit
/book/12/metadata/edit
/book/12/marketing/edit
This seems more elegant, as each of these "resources" are RESTful and have few attributes each. But the resources are not objects (Marketings?).
Do you thing it's OK to create meaningless resources just to be RESTful and keep code in order?
Is there a better way to group similar attributes than create resources out of them? Thanks.
I'm porting a large PHP application to Rails and we have a fair few "ad-hoc"resources, such as admins have the ability to log in as another user with their permission, in order to correct issues etc. I would always complain that features such as logging in as other users should not be bundled into a huge monolithic AdminController as actions loginAsUser and logOutOfUserAccount. In our Rails app we try to visualize as much as we can in terms of resources, so using the example I just gave, we have an Admin namespace, under which there is a UsersController (/admin/users/:id) and as a sub-resource of users, we have a UserOverride resource (/admin/users/:user_id/override)... it feels really logical that we just POST and DELETE to this resource.
So getting back to your example, yes, I think you should break those sections down into separate resources. It certainly seems like BookContent should be a sub-resource of Book, and MarketingOptions too.
resources :books do
resource :content
resources :marketing_options
end
etc
This is both nicer to work with (more modular) and easier to visualize just from looking at the routes alone. You also get the benefit of really predictable path helpers:
<%= link_to("Marketing Options", book_marketing_options_path(#book)) %>
You can't try to force every conceivable route into a RESTful resource ideology though... if it feels like it's forced, then it probably is.
There's a decent blog post I wanted to link to that (despite some poor grammar) actually does a pretty good job of showing you how to think about your application in terms of resources... I can't find it though. I'll add a comment if/when I do.
EDIT | Just re-reading your original question and wanted to clarify: resource != row in database. A resource is anything you can conceive as a "thing"... I know that's a very broad statement, but just like an Object in OOP doesn't have to represent something concrete/material, nor does a resource in a RESTful design.

Rails 3 RESTful design preferred?

I'm pretty new to Rails 3 and I'm trying to understand the advantage of designing an application in a RESTful way. I don't need an API/Web Service. Don't need XML or JSON.
The application I'm building uses no CRUD at all. It is an app that gathers trade data via a socket connection and displays it to a user in many different ways.
I would like to visualize trades in different ways such as:
Most recent
Highest Yielding
Trades by State
Most active trades
Million dollar trades
Trades that are general obligation bonds
etc…
In the "Rails way" it seems that I would have a very overloaded index action. Or I could go against convention and just create methods in the trades controller like most_recent, highest_yielding, most_active, etc. But that seems to go against the whole philosophy of designing an app in Rails 3.
It just seems like the idea behind a RESTful approach in Rails is based around CRUD and falls short when CRUD isn't involved. Is there really an advantage to designing your app to be "RESTful" besides following a convention? I'm not really seeing the advantage here.
Plus, if I ever do need an API, I would imagine that it would be much better to design an API with an API in mind. My API wouldn't be a direct 1 to 1 match of my website which is built for human consumption vs a machine.
I'd appreciate any insight on this. Maybe I'm missing something here?
CRUD is actually involved when resources are involved. And since virtually every application has resources CRUD can be involved and is usually(if you ask me), the best way to do it.
The idea is that a resource has certain actions. You view a resource, you edit it, you delete it and some more. The methods like most_recent(or scope for this one) should be used in models and not controllers. Then, if you need to use that collection, you would just call something like :
#recent_posts = Post.most_recent
in your controller. Your controllers should not have much code, actually no business logic at all.
RESTful is very nice because it handles resources naturally. A controller should actually be handling a resource. If you think that something can be edited or created, then it should be handled by a controller.
Generally, i highly suggest that you take a deeper look and you will definitely see the advantages on your own.
I have idea how to do it. Code is not tested, I just wrote it without running.
Controller:
# trades_controller.rb
def index
# all scopes defined in model will be allowed here
# not good idea if you don't want it
if Trade.scopes.has_key?(params[:scope].to_sym)
#trades = Trade.send(:params[:scope])
else
# render error or what you want
end
end
Model
# trade.rb
scope :most_recent, order(:created_at)
# more scopes
View
# index.html.erb
link_to 'Most recent', trades_path(:scope => 'most_recent')
Your design should always take into account the requirements of your application first and the philosophy of the framework second.
If the philosophy doesn't fit your requirements or what you believe is the best way to develop your application then either ignore it, or, if the framework makes it too difficult for you to build like you think you should (which isn't the case in Rails imho), switch to another framework.
All of that doesn't have much to do with REST. For more info on why REST is considered a good idea (for some, not all, things), see the following SO Q&A's: Why would one use REST instead of Web services and What exactly is RESTful programming.

Resources