Can you use the same controller in two places at once?
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_'
end
map.resources :bookings do | booking |
booking.resources :attendees, :name_prefix => 'booking_'
end
map.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]
end
if @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 |
...
end
else
form_for :attendee, :url => booking_new_attendee_path(@attendee.attendable) do | form |
...
end
end
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.build
if @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.
2 comments:
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!)
Post a Comment