0

Let's say I have a receipts model, and I want to offer a controller action to print one... The un-restful way would be to do:

# receipt_controller.rb
  def print
    ...
  end

#routes.rb
  resources :receipts do
    get :print, :on => :member
  end

... The restful way would be:

# receipt_printings_controller.rb
  def create
    ...
  end

#routes.rb
  resources :receipts
  resources :receipt_printings, :only => :create

My question is..... Let's say I wanted to have the following structure:

/app
  /controllers
     receipts_controller.rb
     /receipt
       printings_controller.rb

That would mean my class would look like: class Receipt::PrintingsController < ActiveRecord::Base def create ... end end

But I don't know how to properly route in this context because I still need to be able to do:

receipt_printings_path(123) to get /receipts/123/printings

The only way I know how to accomplish this is to do:

#routes.rb
  match "/receipts/:id/printings" => "receipt/printings#create", :as => :receipt_printings
  resources :receipts

But, I am wondering if there is a better way?

patrick
  • 9,290
  • 13
  • 61
  • 112

3 Answers3

0

If i'm right, you need a nested resource, have look in this rails guide

bonyiii
  • 2,833
  • 29
  • 25
  • as far as I understand, a nested resource will not work with a namespaced controller... (unless the parent resource is also namespaced, which in this case it should not be) – patrick May 07 '12 at 07:32
0

I think you can do something like this:

resources :receipts do 
  resources :printings, :controller => "receipt/printings", :only => :create
end

It will generate :

receipt_printings POST /receipts/:receipt_id/printings(.:format) receipt/printings#create

Then to access to your route :

receipt_printings_path(:receipt_id => @receipt.id)

I hope it helps

CupraR_On_Rails
  • 2,449
  • 1
  • 19
  • 24
0

You can use nest routes, but the way I read your question it sounds to me like you want namespaces. Namespaces might look like the following:

resources :receipts
namespace :receipts do
  resources :printings
end

This would route /receipts/printings/:id to app/receipt/printings_controller.rb with an id for the printing (not the receipt).

You might really want nested routes. If you want to use the receipt id, and have only one print action (per receipt), you could use a singular resource.

resources :receipts do
  resource :printing
end

This will route /receipts/:id/print to app/printings_controller.rb as show.

To organize the printings controller in a namespace, I would leave it out of the routes, because that will try to insert another receipts namespace in the URL. Instead, use,

resources :receipts do
  resource :printing, :controller => "receipt/printings"
end

This is how to be RESTful. However, you might not have a RESTful case. Is printing really doing a create? Is it really doing a show or update? If it's a service which doesn't fit into a CRUD operation, then it's time to deviate from the golden path, and go ahead and use a non-RESTful verb.

Marlin Pierce
  • 9,931
  • 4
  • 30
  • 52