I’m currently wrestling with a problem. My application has Attendees that either belong to PrivateCourses or Bookings. It uses a polymorphic association for this: has_many :attendees, :as => :attendable.
However, in both cases the UI is pretty much identical. So I figured I could set up routes like so:
map.resources :private_courses do | private_course | private_course.resources :attendees, :name_prefix => 'private_course_'endmap.resources :bookings do | booking | booking.resources :attendees, :name_prefix => 'booking_'endmap.resources :attendees
This gives me three options: either reference the attendee in the context of a PrivateCourse private_course_attendees_path(@private_course), in the context of a Booking booking_attendee_path(@booking) or all on its own attendee_path(@attendee). I was thinking I could examine the supplied parameters to figure out what the Attendable should be:
if !params[:booking_id].blank? @attendable = Booking.find params[:booking_id]elsif !params[:private_course_id].blank? @attendable = PrivateCourse.find params[:private_course_id]endif @attendable.blank? @attendee = Attendee.find params[:id]else @attendee = @attendable.attendees.find params[:id] end
Looks good so far.
But it turns out my view code is turning into a conditional nightmare. Take the “new” form:
if @attendee.attendable.is_a?(PrivateCourse) form_for :attendee, :url => private_course_new_attendee_path(@attendee.attendable) do | form | ... endelse form_for :attendee, :url => booking_new_attendee_path(@attendee.attendable) do | form | ... endend
Of course, not only is this ugly but there needs to be code in the controller to set up the new Attendee’s Attendable. In which case I should just make the controller look like this:
@attendee = @attendable.attendees.buildif @attendable.is_a?(PrivateCourse) render :action => 'new_attendee_for_private_course'else render :action => 'new_attendee_for_booking'end
Yet as I went through this, I kept thinking that every single action needs the same conditional logic - actual form definitions aside, there is actually nothing that is shared between the two conditions.
So, my answer, barring a flash of inspiration, is “No, you cannot use the same controller in two places at once”.
Now I need to rework my body of code to have two controllers - PrivateCourseAttendees and BookingAttendees that both make use of a set of shared partials, probably in an Attendees folder.
We’ve been wresting with similar issues.
Check out resources_controller at http://plugins.ardes.com
Cheers Ian,
That looks useful (although it could do with an overview page!)