RESTful design/url question


#1

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?

/customers/1:orders
/customers/1?view=orders
/customers/1/orders/
/orders:filter?customer=1

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.

Thanks


#2

Thanks a bunch.

Follow-up question if you don’t mind…

You are on the page to view a customers orders:
/customers/1/orders/

User clicks edit, Would you replicate the edit, ala:

/customers/1/orders/1;edit

Or kick 'em to the orders resource?

/orders/1;edit

I’d like to be able to click “New Order” from within the customer view,
something like

/customers/1/orders/new

But the replication doesn’t feel very DRY.


#3

On Feb 14, 8:25 am, “Meech” removed_email_address@domain.invalid wrote:

New to rails and restful design, forgive me if this has been asked…

Not at all.

/orders:filter?customer=1
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.

Hope this helps
Jeff
softiesonrails.com


#4

you can use the builtin helper:

edit_order_path(@customer,@order)

that will create a link like “/customers/1/order/1;edit”

new_order_path(@customer) will create a link to “/customer/1/order/new”

ed


#5

I understand that,

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.


From: removed_email_address@domain.invalid
[mailto:removed_email_address@domain.invalid] On Behalf Of Ed Hickey
Sent: Wednesday, February 14, 2007 10:24 AM
To: removed_email_address@domain.invalid
Subject: [Rails] Re: RESTful design/url question

you can use the builtin helper:

edit_order_path(@customer,@order)

that will create a link like “/customers/1/order/1;edit”

new_order_path(@customer) will create a link to “/customer/1/order/new”

ed

On 2/14/07, Meech removed_email_address@domain.invalid wrote:

Thanks a bunch.

Follow-up question if you don’t mind…

You are on the page to view a customers orders:
/customers/1/orders/

User clicks edit, Would you replicate the edit, ala:

/customers/1/orders/1;edit

Or kick 'em to the orders resource?

/orders/1;edit

I’d like to be able to click “New Order” from within the customer
view,
something like

/customers/1/orders/new

But the replication doesn’t feel very DRY.

-----Original Message-----
From: removed_email_address@domain.invalid
[mailto:removed_email_address@domain.invalid
mailto:removed_email_address@domain.invalid ] On Behalf Of Jeff
Sent: Wednesday, February 14, 2007 9:43 AM
To: Ruby on Rails: Talk
Subject: [Rails] Re: RESTful design/url question

On Feb 14, 8:25 am, “Meech” < removed_email_address@domain.invalid
mailto:removed_email_address@domain.invalid > wrote:

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?

/customers/1:orders
/customers/1?view=orders
/customers/1/orders/
/orders:filter?customer=1

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.

Hope this helps
Jeff
softiesonrails.com


#6

On 2/14/07, Meech removed_email_address@domain.invalid wrote:

So, if we are viewing a customer/orders page, /customers/1/orders/ and
they should return after completing the edit.
Meech,

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?


Zack C.
http://depixelate.com


#7

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 B. recently posted
about
something related to your question:
http://weblog.jamisbuck.org/2007/2/5/nesting-resources

ed


#8

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


#9

On 2/14/07, Meech removed_email_address@domain.invalid wrote:

invoices has payments.

/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.

Good luck.


Zack C.
http://depixelate.com