1

So that's a mouthful.

Let's assume that you're a vehicle manufacturer and you want a webapp for stuff. Part of that webapp is used for your designers to collaborate on their designs. You design cars, trucks, and suv's let's say. Let's say you have inherited updating this thing, and that the prior developer decided to use Single Table Inheritance as the Design pattern. You read up on STI and you agree that the design pattern used was the right one, but you want to refactor a bunch of controllers and views because they're practically identical.

The Models you inherited look like this:

class Design < ActiveRecord::Base
class DesignVersion < ActiveRecord::Base

class DesignCar < Design
class DesignCarVersion < DesignVersion

Assume that your models for SUV and Truck Designs / Design Versions follow the same pattern as laid out here for car. Also assume that the appropriate relationships have been set up since the application works, it's just got some redundant code you're trying to DRY up.

You initially started out with having a controller for each of car, car design, truck, truck design, etc. So you read up on STI with One Controller, and routing for STI. As a result, you make a Designs and DesignVersions controller (to match your Design and DesignVersion base models), and in your routes you come up with something like the following:

resources :cars, :controller => "designs", :type => 'DesignCar' do
  resources :car_versions, :controller => "design_versions", :type => 'DesignCarVersion'
    member do
      post 'approve'
      #various other things besides new, show, etc
    end
  end
end

This helpfully generates routes like new_design_car_car_versions_path, approve_design_car_car_versions_path, etc. Assume you do the same for the trucks and the suvs. You do a rake routes, look at your routes -- the routes are identical to the ones you had before when you were just doing

resources :cars
  resources :car_versions
    member do
      post 'approve'
    end
  end
end

so all looks good. You create a really basic view that just lists the designs (so if you go to /cars you only see car designs) and all looks well when you look at /cars, /trucks, etc. All you see is the specific type of Design. Then you start adding in the old _paths and refactoring them to be generic rather than specific.

No problem, you think. I'll just use polymorphic_path!

And here is where I hit my problem.

The routes generated from config/routes.rb generate as approve_design_car_car_versions_path. The equivalent polymorphic_path generates as approve_design_car_design_car_versions_path. When I try to view the page for /cars (which lists each design and then under that, some data about the various versions including links to those specific versions of the design), as one would expect, it bails because "approve_design_car_design_car_versions_path" does not exist.

Let's also assume that even though DesignCar and DesignCarVersion seem clunky for model names, that we also have a Car model for another part of the webapp. As a result, we had to differentiate. For this example, CarDesign and CarDesignVersion might make more sense, but in the problem that I am modeling this after, what I actually have (that I am replacing with DesignCar here) makes more sense.

Things I've tried:

A LOT of reading. I first thought that maybe polymorphic_url wasn't what I wanted, so I did my best to try to read up on how to generate routes for STI. Unfortunately, most of the answers I found either didn't include the :type stuff, or didn't include nested routes like I have.

Then I thought maybe I might actually want to change from STI to polymorphism. I watched an older Rails Cast on it, did some reading, but came to the conlusion that STI really is the right thing.

Then I thought "Well, I'll just specify the name of the routes to be whatever the polymorphic generates, and that should work" so I did something like the following:

resources :cars, :controller => "designs", :type => 'DesignCar' do
  resources :car_versions, :controller => "design_versions", :type => 'DesignCarVersion'
    member do
      post 'approve', :as => 'approve_design_car_car_versions'
    end
  end
end

When I did a rake routes, that became 'approve_design_car_car_versions_design_car_versions'

So, what do I need to do to make it so that the routes that get generated, match the polymorphic_path that gets generated when I hand it a car and car_version? Not use polymorphic_path? Fix my routes? Go back to a controller for all my children even though that creates a lot of duplication?

I suspect that it has something to do with the reflection on the model for polymorphic_path returning the model name, and the reflection? that is being done for the routes generation is for some reason returning something else. However, I'm puzzled by why that would be if this wasn't a bug (I am assuming this is not a bug and I'm just doing something wrong) Or I'm missing a key value I'm supposed to be passing somewhere. I'm still relatively new to rails yet, so I believe the error most likely lies with me (~ 1.5 years now).

Thank you in advance for your time.

Leanan
  • 732
  • 7
  • 13

1 Answers1

0

So, after continuing to read (and deciding to go reread the Rails Routing from the Outside In Page since I haven't done that in a few months) I have come upon the following solution:

resources :cars, :controller => "designs", :type => 'DesignCar' do
  resources :car_versions, :controller => "design_versions", :type => 'DesignCarVersion', :as => 'design_car_version' do
    member do
      post 'approve'
    end
  end
end

Note that in the question above I was missing the 'do' on :car_versions, but that it was actually there in the code. The solution was adding the :as to the resources level, not to each individual member.

If there's a better way, I'm all ears.

Leanan
  • 732
  • 7
  • 13