Abhi9
Abhi9

Reputation: 320

How to create hierarchial routes in rails?

Problem at hand

I want to create a rails app where a manager can choose an event and manage attendance for that. I have my managers model, events model, registrations model and attendees model set up.

Manager (resources :m)

Events  (resources :event)

Registrations (resource :registration)

Attendees (resources :attendee)

where,

manager => has_many :events

events  => belongs_to :manager
events  => has_many :registrations
events  => has_many :attendees through: :registrations

registration => belongs_to :event
registration => belongs_to :attendee

attendee => has_many :registrations
attendee => has_many :events through: :registrations

What I want is to generate a URL like this

localhost:3000/m/1/event/attendance

What I have tried

resources :m, :only => [:index] do
    member do
        get :event
        collection do 
          get :attendance
        end
    end
end

But this gives the error

rake aborted!
ArgumentError: can't use collection outside resource(s) scope

Can anyone suggest a proper way of achieving this or any alternative way which is more optimal?

Upvotes: 0

Views: 68

Answers (2)

Pavan
Pavan

Reputation: 33542

I want to create a rails app where a manager can choose an event and manage attendance for that.

So an attendance belongs to a particular event and the manager manages it. For this, you can simply go with the below

resources :managers, only: [:index] do
  resources :events do
    get :attendance, on: :member
  end
end

This will generate attendance_manager_event GET /managers/:manager_id/events/:id/attendence(.:format) events#attendance as on of the routes which will map to attendance action of events controller.

#events_controller
def attendance
  #your logic
end

Upvotes: 2

max
max

Reputation: 102213

First you may want to consider that the route /m/1/event/attendance is not RESTful at all. Unless you have a true one to one relation or a singleton object you should be using the plural form. event/attendance also lacks an identifier telling which event it works on.

You can nest routes simply by nesting resources (or resource) blocks:

resources :managers
  resources :events
    resources :attendances
  end
end

Which would give you /managers/1/events/1/attendences.

However a good rule of thumb is:

Resources should never be nested more than 1 level deep. A collection may need to be scoped by its parent, but a specific member can always be accessed directly by an id, and shouldn’t need scoping (unless the id is not unique, for some reason).
- Jamis Buck

Which means that a better design is something along these lines:

resources :events
  resources :attendences
end

resources :managers
  resources :events
end

See also:

Upvotes: 1

Related Questions