New to rails and restful design, forgive me if this has been asked...
Lets say you have customers and orders models. orders belongs_to
customers.
When viewing a customer, (/customers/1/) I want to present the option
to view the customers orders (and eventually invoices, POs, etc).
What route would be within restful guidelines?
I think I would prefer each "page" of a customer detail have it's own
controller method -- this will allow me to keep the security decisions
completely within the controller easily.
New to rails and restful design, forgive me if this has been asked...
Not at all.
Lets say you have customers and orders models. orders belongs_to
customers.
When viewing a customer, (/customers/1/) I want to present the option
to view the customers orders (and eventually invoices, POs, etc).
What route would be within restful guidelines?
I believe it would be /customers/1/orders/ . You achieve this by
specifying that orders are nested within customers in your routes.rb:
map. resources :customers do |customer|
customer.resources :orders
end
and then, in your OrdersController class, use a before_filter to
identify the customer, something like:
before_filter :get_customer
def get_customer
@customer = Customer.find(params[:customer_id])
end
The customer_id key is automatically created for you when you nest the
routes.
I think I would prefer each "page" of a customer detail have it's own
controller method -- this will allow me to keep the security decisions
completely within the controller easily.
That's how Rails works anyway - each "page" is an "action". An action
is a coupling of a controller method and a template (.rhtml page). So
you're on the right track.
But in my instance orders is not only a child of customers, it's a bonafide
resource of it's own, accessible via:
/orders/
/orders/1/
/orders/1;edit
So, if we are viewing a customer/orders page, /customers/1/orders/ and
they click on "Edit Order". Do we goto:
/customers/1/orders/1;edit #edit order #1
Or
/orders/1;edit #edit order #1
Do we implement both methods for the same function?
Syntactically, I think I like the both approach. If a user clicks on "Edit
Order" from within a customer orders details view, its pretty apparent where
they should return after completing the edit.
Why do you want to expose orders as a first level resource
(/orders/1)? If an order is always associated with a customer then
the nested way (/customers/1/orders/1) makes more sense.
What is it you're trying to accomplish by exposing orders via two
resource paths?
It depends on your model associations. If Order belongs_to Customer, then I would go the “/customers/1/orders/new” because you’ll need to reference to the Customer to create the Order.
You can use nested routes to acheive this. Jamis Buck recently posted about something related to your question: http://weblog.jamisbuck.org/2007/2/5/nesting-resources
It just seems nicer to be able to view open/active orders across
customers to perform order-related functions. The user could goto:
/orders/?q=active
Click on the order and manipulate it, instead of remembering the
customer, clicking on the orders tab, then clicking on the order.
But lets take this another level deep. Orders have invoices,
invoices has payments.
customer
--order
----invoice
------payment
A person in accounts receivable would like to see unpaid invoices (as
a whole, not specific to a customer) in order to perform collection
activities. Or be able to see payments within a deposit instead of
by customer/invoice, etc, etc...
While somebody can view invoices via /customer/1/invoice/1/ how
would they see all open invoices for the company? via: /invoices/
This is why I posed the original question. Is it restfull to
duplicate functions like this?
Is it?
/customers/1/invoices
/invoices/customers/1/
/invoices/?customer=1
I understand where you're coming from now. I think you could do this
a few ways. One is to just expose the additional route in routes.rb
map. resources :customers do |customer|
customer.resources :orders
end
map.admin_orders '/orders', :controller => 'orders'
You can also make an admin controller for handling workflow types of
things like order approval (in non-REST fashion). Or you can view
status changing of orders (aka pending, verified, charged, shipped,
etc) as an OrderStatus resource and expose this via a REST controller.