-2

Say that I have a Customers and an Orders tables, where each Customer may have many Orders.

Since in rails we are encouraged to represent these resources in a RESTful style, each of our resources, will respond to the following actions

  • index
  • show
  • edit
  • new
  • create
  • delete

So far, it all is very fair and plain. But now say that each time i open the show page of my Customer, i want to show a detail table containing all his/her orders.
This is a very common need, but doesn't this "unclean" the correctness of restful approach?
Is there some workaround, like "mashing" the two resources at a "view level", leaving them separate from the rest point of view?

AgostinoX
  • 6,923
  • 18
  • 72
  • 120
  • 1
    I don't understand : REST does not prevent you from showing a list of associated resources in show view. And rails has support for [nested resources](http://guides.rubyonrails.org/routing.html#nested-resources) – m_x Apr 19 '13 at 09:51

2 Answers2

1

Rails' default conventions ensure a RESTful application, and the only way this might become non-restful would be if you used custom-names on the routes, in which case you would have you add an extra bit of code to specify the HTTP method.

So, to accomplish what you're suggesting, at the view level, you may have something like this:

app/views/customers/show.html.erb

....
<% if customer.orders.any? %>  #the orders method is provided on `customer` by defining the `has_many` and `belong_to` associations
  <%= render @orders $>

And you would make sure to define @orders in the show action of the customers_controller.rb file.

This not only is RESTful, but also works within Rails' default conventions.

aceofbassgreg
  • 3,543
  • 2
  • 28
  • 41
  • Sorry, i don't get it working. I get an error: "ActionView::MissingTemplate in Customers#show" and "Missing partial orders/order". This puzzles me. The worst, i don't find documentation about rendering a model or a relation such as render @orders. I've looked here: http://api.rubyonrails.org/classes/ActionView/Helpers/RenderingHelper.html and here: http://api.rubyonrails.org/classes/ActionController/Base.html#M000658. No trace of this. Can you expand on this topic? tnx – AgostinoX Apr 26 '13 at 14:18
  • The obvious questions are: do you have a file in app/views titled show.html? And, if you're calling a partial from app/views/orders, is it saved as _order.html.erb? Add the code you already have to your question above, and we can go from there. – aceofbassgreg Apr 26 '13 at 16:52
  • 1
    To clarify (because I was missing a directory above), your `show.html.erb` file should be in your appp/views/customers directory. As far as a documented example, [Hartl](http://ruby.railstutorial.org/chapters/user-microposts#sec-augmenting_the_user_show_page) walks readers through a good example of setting up a page to display users' microposts. This ought to help. – aceofbassgreg Apr 28 '13 at 11:49
  • ok, eventually i get it working, starting from scratch a new project; maybe some concept may require a bit of expansion, i will come back on them. – AgostinoX May 04 '13 at 11:08
1

Those actions you list are not what makes something RESTful. There are a bunch of characteristics an application must have to be considered RESTful. Some of these characteristics are:

  • it is thought of as a repository of resources
  • resources are identified by a URI
  • there is a uniform interface for interacting with resources - the HTTP verbs of GET, POST, PUT, DELETE, etc.

Rails takes care of receiving HTTP requests and calling your application's functionality, regardless of whether it is RESTful in nature or not, through routing. Rails routing takes those HTTP verbs I mentioned, in combination with a URI, and determines which controller to call. By default Rails follows the RESTful paradigm, and by convention will map verb/URI combinations to those actions you listed - but the actions themselves, and the fact that they are lumped into a single controller, are not part of REST - they are just the rails convention.

In fact, the rails default routing maps 4 different resources to that single controller and its actions:

/customers             // the list of all customers, GET/POST -> index/create
/customers/new         // a form for creating a customer, GET -> new
/customers/{id}        // a single customer, GET/PUT/DELETE -> show/update/destroy
/customers/{id}/edit   // a form for editing a customer, GET -> edit

Resources can contain sub-resources, and Rails completely supports that. A sub-resource might be:

/customers/{id}/orders // the list of all orders for a particular customer

Another key part of REST is that it supports a resource having different representations, whether that is HTML, XML, JSON, etc. Clients use HTTP headers to convey what representation they are passing into the app (using the Content-Type header) and (usually) what they will accept in response (using the Accept header).

Its up to the application to determine what a resource representation looks like. Typically a resource will either be "thin" or "fat". A "thin" resource is one that simply has links to its sub-resources and further calls must be made to get them. A "fat" resource will contain the fully-fleshed out sub-resources it contains. Typically with an HTML representation, an application will return some form of "fat" resource. There is nothing non-RESTful about this - and is exactly what you are describing you want for your application.

So that was my long way of saying "don't be afraid of not being RESTful by displaying sub-resources - it's perfectly OK" :-)

SingleShot
  • 17,762
  • 13
  • 66
  • 100