<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -67,6 +67,13 @@ module ActionController
     #   record = Comment.new
     #   polymorphic_url(record)  #-&gt;  comments_url()
     #
+    #   # it supports extra flexibility for STI by walking the inheritance chain if the route is missing
+    #   # (note this only works for the last (leaf) argument in nested routes)
+    #   #
+    #   # an Editorial record, where Editorial is a subclass of Article and routes exist for article_* but not editorial_*
+    #   polymorphic_url(editorial_record) #=&gt; article_url(editorial_record)
+    #   polymorphic_url(editorial_record, comment_record) #=&gt; editorial_comment_url(editorial_record, comment_record) #not yet smart enough to find the article_comment_url
+    #
     def polymorphic_url(record_or_hash_or_array, options = {})
       if record_or_hash_or_array.kind_of?(Array)
         record_or_hash_or_array = record_or_hash_or_array.dup
@@ -138,9 +145,20 @@ module ActionController
             string &lt;&lt; &quot;#{RecordIdentifier.send!(&quot;singular_class_name&quot;, parent)}_&quot;
           end
         end
-
-        route &lt;&lt; &quot;#{RecordIdentifier.send!(&quot;#{inflection}_class_name&quot;, record)}_&quot;
-
+        
+        candidate_class = record.class
+        initial_candidate = candidate_route = build_candidate_named_route_call(route, namespace, inflection, candidate_class, options)
+        while (!respond_to?(candidate_route)) #walk up the inheritance chain to find an existing route, supports routing flexibility with STI
+          candidate_class = candidate_class.superclass
+          return initial_candidate if candidate_class == Object
+          candidate_route = build_candidate_named_route_call(route, namespace, inflection, candidate_class, options)
+        end
+        candidate_route || initial_candidate
+      end
+      
+      def build_candidate_named_route_call(route_base, namespace, inflection, candidate_class, options = {})
+        route = route_base.dup
+        route &lt;&lt; &quot;#{RecordIdentifier.send!(&quot;#{inflection}_class_name&quot;, candidate_class)}_&quot;
         action_prefix(options) + namespace + route + routing_type(options).to_s
       end
 </diff>
      <filename>actionpack/lib/action_controller/polymorphic_routes.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,6 +14,9 @@ class Response &lt; Article
   def post_id; 1 end
 end
 
+class Editorial &lt; Article
+end
+
 class Tag &lt; Article
   def response_id; 1 end
 end
@@ -29,6 +32,7 @@ uses_mocha 'polymorphic URL helpers' do
     def setup
       @article = Article.new
       @response = Response.new
+      @editorial = Editorial.new
     end
   
     def test_with_record
@@ -37,11 +41,35 @@ uses_mocha 'polymorphic URL helpers' do
       polymorphic_url(@article)
     end
 
+    def test_with_fallthrough_to_route_for_base_class
+      @editorial.save
+      stubs(:respond_to?).with('editorial_url').returns(false)
+      stubs(:respond_to?).with('article_url').returns(true)
+      expects(:article_url).with(@editorial)
+      polymorphic_url(@editorial)
+    end
+    
+    def test_with_no_matching_routes
+      @editorial.save
+      stubs(:respond_to?).with('article_url').returns(false)
+      stubs(:respond_to?).with('editorial_url').returns(false)
+      expects(:editorial_url).with(@editorial)
+      polymorphic_url(@editorial)
+    end
+    
     def test_with_new_record
       expects(:articles_url).with()
       @article.expects(:new_record?).returns(true)
       polymorphic_url(@article)
     end
+    
+    def test_fallthrough_with_new_record
+      @editorial.stubs(:new_record?).returns(true)
+      stubs(:respond_to?).with('editorials_url').returns(false)
+      stubs(:respond_to?).with('articles_url').returns(true)
+      expects(:articles_url).with()
+      polymorphic_url(@editorial)
+    end
 
     def test_with_record_and_action
       expects(:new_article_url).with()
@@ -49,54 +77,137 @@ uses_mocha 'polymorphic URL helpers' do
       polymorphic_url(@article, :action =&gt; 'new')
     end
 
+    def test_fallthrough_with_record_and_action
+      stubs(:respond_to?).with('new_editorial_url').returns(false)
+      stubs(:respond_to?).with('new_article_url').returns(true)
+      expects(:new_article_url).with()
+      @editorial.expects(:new_record?).never
+      polymorphic_url(@editorial, :action =&gt; 'new')
+    end
+
     def test_url_helper_prefixed_with_new
       expects(:new_article_url).with()
       new_polymorphic_url(@article)
     end
 
+    def test_fallthrough_with_url_helper_prefixed_with_new
+      stubs(:respond_to?).with('new_editorial_url').returns(false)
+      stubs(:respond_to?).with('new_article_url').returns(true)
+      expects(:new_article_url).with()
+      new_polymorphic_url(@editorial)
+    end
+
     def test_url_helper_prefixed_with_edit
       @article.save
       expects(:edit_article_url).with(@article)
       edit_polymorphic_url(@article)
     end
 
+    def test_fallthrough_with_url_helper_prefixed_with_edit
+      @editorial.save
+      stubs(:respond_to?).with('edit_editorial_url').returns(false)
+      stubs(:respond_to?).with('edit_article_url').returns(true)
+      expects(:edit_article_url).with(@editorial)
+      edit_polymorphic_url(@editorial)
+    end
+
     def test_formatted_url_helper
       expects(:formatted_article_url).with(@article, :pdf)
       formatted_polymorphic_url([@article, :pdf])
     end
 
+    def test_fallthrough_with_formatted_url_helper
+      stubs(:respond_to?).with('formatted_editorial_url').returns(false)
+      stubs(:respond_to?).with('formatted_article_url').returns(true)
+      expects(:formatted_article_url).with(@editorial, :pdf)
+      formatted_polymorphic_url([@editorial, :pdf])
+    end
+
     def test_format_option
       @article.save
       expects(:article_url).with(@article, :pdf)
       polymorphic_url(@article, :format =&gt; :pdf)
     end
 
+    def test_fallthrough_with_format_option
+      @editorial.save
+      stubs(:respond_to?).with('editorial_url').returns(false)
+      stubs(:respond_to?).with('article_url').returns(true)
+      expects(:article_url).with(@editorial, :pdf)
+      polymorphic_url(@editorial, :format =&gt; :pdf)
+    end
+
     def test_id_and_format_option
       @article.save
       expects(:article_url).with(:id =&gt; @article, :format =&gt; :pdf)
       polymorphic_url(:id =&gt; @article, :format =&gt; :pdf)
     end
 
+    def test_fallthrough_with_id_and_format_option
+      @editorial.save
+      stubs(:respond_to?).with('editorial_url').returns(false)
+      stubs(:respond_to?).with('article_url').returns(true)
+      expects(:article_url).with(:id =&gt; @editorial, :format =&gt; :pdf)
+      polymorphic_url(:id =&gt; @editorial, :format =&gt; :pdf)
+    end
+
     def test_with_nested
       @response.save
       expects(:article_response_url).with(@article, @response)
       polymorphic_url([@article, @response])
     end
+    
+    def test_fallthrough_for_child_with_nested
+      @editorial.save
+      stubs(:respond_to?).with('response_editorial_url').returns(false)
+      stubs(:respond_to?).with('response_article_url').returns(true)
+      expects(:response_article_url).with(@response, @editorial)
+      polymorphic_url([@response, @editorial])
+    end
+
+    def test_fallthrough_for_parent_with_nested #fallthrough only currently works for the targeted resource, not for parents it is nested inside
+      @response.save
+      stubs(:respond_to?).with('editorial_article_url').returns(false)
+      stubs(:respond_to?).with('editorial_response_url').returns(false)
+      expects(:editorial_response_url).with(@editorial, @response) #TODO: this should be expects(:article_response_url).with(@editorial, @response)
+      polymorphic_url([@editorial, @response])
+    end
 
     def test_with_nested_unsaved
       expects(:article_responses_url).with(@article)
       polymorphic_url([@article, @response])
     end
+    
+    def test_fallthrough_for_child_with_nested_unsaved
+      stubs(:respond_to?).with('response_editorials_url').returns(false)
+      stubs(:respond_to?).with('response_articles_url').returns(true)
+      expects(:response_articles_url).with(@response)
+      polymorphic_url([@response, @editorial])
+    end
 
     def test_new_with_array_and_namespace
       expects(:new_admin_article_url).with()
       polymorphic_url([:admin, @article], :action =&gt; 'new')
     end
 
+    def test_fallthrough_for_new_with_array_and_namespace
+      stubs(:respond_to?).with('new_admin_editorial_url').returns(false)
+      stubs(:respond_to?).with('new_admin_article_url').returns(true)
+      expects(:new_admin_article_url).with()
+      polymorphic_url([:admin, @editorial], :action =&gt; 'new')
+    end
+
     def test_unsaved_with_array_and_namespace
       expects(:admin_articles_url).with()
       polymorphic_url([:admin, @article])
     end
+    
+    def test_fallthrough_for_unsaved_with_array_and_namespace
+      stubs(:respond_to?).with('admin_editorials_url').returns(false)
+      stubs(:respond_to?).with('admin_articles_url').returns(true)
+      expects(:admin_articles_url).with()
+      polymorphic_url([:admin, @editorial])
+    end
 
     def test_nested_unsaved_with_array_and_namespace
       @article.save
@@ -106,6 +217,21 @@ uses_mocha 'polymorphic URL helpers' do
       polymorphic_url([:admin, @article, @response])
     end
 
+    def test_fallthrough_for_nested_unsaved_with_array_and_namespace
+      @editorial.save
+      stubs(:respond_to?).with('admin_editorial_url').returns(false)
+      stubs(:respond_to?).with('admin_article_url').returns(true)
+      expects(:admin_article_url).with(@editorial)
+      polymorphic_url([:admin, @editorial])
+      
+      #fallthrough only currently works for the targeted resource, not for parents it is nested inside
+      stubs(:respond_to?).with('admin_editorial_responses_url').returns(false)
+      stubs(:respond_to?).with('admin_editorial_articles_url').returns(false)
+      stubs(:respond_to?).with('admin_article_responses_url').returns(true)
+      expects(:admin_editorial_responses_url).with(@editorial) #TODO: this should be expects(:admin_article_responses_url).with(@editorial)
+      polymorphic_url([:admin, @editorial, @response])
+    end
+
     def test_nested_with_array_and_namespace
       @response.save
       expects(:admin_article_response_url).with(@article, @response)
@@ -117,6 +243,24 @@ uses_mocha 'polymorphic URL helpers' do
       expects(:site_admin_article_response_tag_url).with(@article, @response, @tag)
       polymorphic_url([:site, :admin, @article, @response, @tag])
     end
+    
+    def test_fallthrough_for_nested_with_array_and_namespace
+      @response.save
+      stubs(:respond_to?).with('admin_editorial_response_url').returns(false)
+      stubs(:respond_to?).with('admin_editorial_article_url').returns(false)
+      stubs(:respond_to?).with('admin_article_response_url').returns(true)
+      expects(:admin_editorial_response_url).with(@editorial, @response) #TODO: this should be expects(:admin_article_response_url).with(@editorial, @response)
+      polymorphic_url([:admin, @editorial, @response])
+
+      # a ridiculously long named route tests correct ordering of namespaces and nesting:
+      @tag = Tag.new
+      @tag.save
+      stubs(:respond_to?).with('site_admin_editorial_response_tag_url').returns(false)
+      stubs(:respond_to?).with('site_admin_editorial_response_article_url').returns(false)
+      stubs(:respond_to?).with('site_admin_article_response_tag_url').returns(true)
+      expects(:site_admin_editorial_response_tag_url).with(@editorial, @response, @tag) #TODO: this should be expects(:site_admin_article_response_tag_url).with(@editorial, @response, @tag)
+      polymorphic_url([:site, :admin, @editorial, @response, @tag])
+    end
 
     # TODO: Needs to be updated to correctly know about whether the object is in a hash or not
     def xtest_with_hash
@@ -129,6 +273,13 @@ uses_mocha 'polymorphic URL helpers' do
       expects(:new_article_path).with()
       polymorphic_path(@article, :action =&gt; :new)
     end
+    
+    def test_fallthrough_with_polymorphic_path_accepts_options
+      stubs(:respond_to?).with('new_editorial_path').returns(false)
+      stubs(:respond_to?).with('new_article_path').returns(true)
+      expects(:new_article_path).with()
+      polymorphic_path(@editorial, :action =&gt; :new)
+    end
 
     def test_polymorphic_path_does_not_modify_arguments
       expects(:admin_article_responses_url).with(@article)</diff>
      <filename>actionpack/test/controller/polymorphic_routes_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>9620372a6dc7eeebdb04f1fdb7f150d29e60fc00</id>
    </parent>
  </parents>
  <author>
    <name>Luke Melia</name>
    <login>lukemelia</login>
    <email>luke@lukemelia.com</email>
  </author>
  <url>http://github.com/lukemelia/rails/commit/4eecef63ece3927b2a432df217b180c9aa4d3df5</url>
  <id>4eecef63ece3927b2a432df217b180c9aa4d3df5</id>
  <committed-date>2008-04-13T15:52:34-07:00</committed-date>
  <authored-date>2008-04-13T15:49:08-07:00</authored-date>
  <message>Add extra flexibility for STI to polymorphic_url by walking the inheritance chain if the route is missing
  i.e. given an an Editorial record, where Editorial is a subclass of Article and routes exist for article_* but not editorial_*
  polymorphic_url(editorial_record) #=&gt; article_url(editorial_record)</message>
  <tree>521a8aa8f0a2999fb547a39520843a3f1d5029f3</tree>
  <committer>
    <name>Luke Melia</name>
    <login>lukemelia</login>
    <email>luke@lukemelia.com</email>
  </committer>
</commit>
