This project is archived and is in readonly mode.

#3765 ✓committed
Steve St. Martin

Missing shallow routes in new router DSL

Reported by Steve St. Martin | January 21st, 2010 @ 03:16 PM | in 3.0.2

It seems that shallow routes have been removed from the new router dsl. I attempted to dig through the tests source, and havent seen anything leading me to believe its implemented.

Is this an oversight, or planned removal?

Comments and changes to this ticket

  • Rizwan Reza

    Rizwan Reza January 21st, 2010 @ 03:42 PM

    • Milestone cleared.
    • State changed from “new” to “open”
    • Assigned user set to “josh”

    I've confirmed that shallow routes aren't present in Rails 3 as of now.

  • josh

    josh January 21st, 2010 @ 05:35 PM

    Why do we need them again?

  • Rizwan Reza

    Rizwan Reza January 21st, 2010 @ 05:49 PM

    
    map.resources :users, :shallow => true do |user|
      user.resources :articles do |article|
        article.resources :comments
      end
    end
    
    user_articles_path(1) #=> '/users/1/articles'
    article_path(2) #=> '/articles/2'
    article_comments_path(3) #=> '/articles/3/comments'
    comment_path(4) #=> '/comments/4' -- using shallow routes
    

    Don't you think they add more flexibility to nested resources?

    Reference: http://ryandaigle.com/articles/2008/9/7/what-s-new-in-edge-rails-sh...

  • josh

    josh January 22nd, 2010 @ 01:07 AM

    • Assigned user changed from “josh” to “DHH”

    Hand off to DHH who is guiding the new API design.

  • DHH

    DHH January 22nd, 2010 @ 01:10 AM

    I think it can work just like it did in 2.3.x:

    resources :users, :shallow => true do
    resources :articles end

  • Balazs Nagy

    Balazs Nagy February 7th, 2010 @ 12:01 PM

    It seems to me it doesn't work:

    ike:~/Code/rails3-demo>>% ruby --version
    ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-darwin10.2.0]
    ike:~/Code/rails3-demo>>% rails --version 2>/dev/null                   
    Rails 3.0.0.beta
    ike:~/Code/rails3-demo>>% grep -v '^ *#' config/routes.rb | grep -v '^$'
    Rails3Demo::Application.routes.draw do |map|
      resources :users, :shallow => true do
        resources :articles
      end
    end
    ike:~/Code/rails3-demo>>% rake routes 2>/dev/null                       
    (in /Users/js/Code/rails3-demo)
                      GET    /users/:user_id/articles(.:format)          {:controller=>"articles", :action=>"index"}
        user_articles POST   /users/:user_id/articles(.:format)          {:controller=>"articles", :action=>"create"}
     new_user_article GET    /users/:user_id/articles/new(.:format)      {:controller=>"articles", :action=>"new"}
                      GET    /users/:user_id/articles/:id(.:format)      {:controller=>"articles", :action=>"show"}
                      PUT    /users/:user_id/articles/:id(.:format)      {:controller=>"articles", :action=>"update"}
         user_article DELETE /users/:user_id/articles/:id(.:format)      {:controller=>"articles", :action=>"destroy"}
    edit_user_article GET    /users/:user_id/articles/:id/edit(.:format) {:controller=>"articles", :action=>"edit"}
                      GET    /users(.:format)                            {:controller=>"users", :action=>"index"}
                users POST   /users(.:format)                            {:controller=>"users", :action=>"create"}
             new_user GET    /users/new(.:format)                        {:controller=>"users", :action=>"new"}
                      GET    /users/:id(.:format)                        {:controller=>"users", :action=>"show"}
                      PUT    /users/:id(.:format)                        {:controller=>"users", :action=>"update"}
                 user DELETE /users/:id(.:format)                        {:controller=>"users", :action=>"destroy"}
            edit_user GET    /users/:id/edit(.:format)                   {:controller=>"users", :action=>"edit"}
    
  • Balazs Nagy

    Balazs Nagy February 9th, 2010 @ 12:39 PM

    So far the tests are done. I'm working on :shallow => true support, but what I found so far are a ton of dead ends. A dead easy and elegant solution, anyone?

  • Balazs Nagy

    Balazs Nagy February 9th, 2010 @ 05:25 PM

    Here it comes. I know it's not as elegant as it would be, but hey, it works, it passes tests, and doesn't break anything.

  • Balazs Nagy
  • Rizwan Reza

    Rizwan Reza February 12th, 2010 @ 12:33 PM

    You can unify the code and test as a single patch.

  • Balazs Nagy

    Balazs Nagy February 12th, 2010 @ 02:24 PM

    Sure. It's attached. I learned the usage of git from git developers, and they have strict rules about the subject: put refactoring, failing tests, and solutions for in separate patches :)

    The typo issue which was mentioned in my earlier second patch is reported too :)

  • Balazs Nagy

    Balazs Nagy February 15th, 2010 @ 10:17 PM

    The patch was not added yet. Good. I was not satisfied with the patch myself too: it was not aware of inherited resources:

    resources :a do
      resources :b, :shallow => true do
        resources :c
      end
    end
    

    should have generated (among others)

    • as_path,
    • a_bs_path,
    • a_b_cs_path,
    • c_path

    instead of

    • as_path,
    • a_bs_path,
    • a_b_cs_path,
    • a_b_c_path

    But fret not, here's my new patch. It's now aware of this situation as well.

  • Balazs Nagy

    Balazs Nagy February 19th, 2010 @ 10:36 AM

    I have fixed shallowing in subresources, which broke shallowing the outmost resources. You can find the patch here, or have a look on http://github.com/julian7/rails .

  • Balazs Nagy

    Balazs Nagy February 24th, 2010 @ 09:41 AM

    • Tag changed from :shallow_routes, rails3, router to :shallow_routes, patch, rails3, router

    Oops, Should I have added 'patch' tag?

  • jolohaga

    jolohaga February 25th, 2010 @ 03:59 PM

    The 2.3.x way doesn't work for me either. The argument :shallow => true is just ignored.

    Now that the new routing API is void of Hashes, this old syntax looks awkward. It should probably be a method.

    I appreciate the effort being made to get this working, but I think I'll wait to switch my projects until this is officially resolved.

  • jolohaga

    jolohaga February 26th, 2010 @ 10:21 PM

    Other options are not being processed either, specifically :has_many and :has_one are not processed.

    This ticket should be renamed 'Router options ignored in new router DSL'.

  • DHH

    DHH February 26th, 2010 @ 10:43 PM

    has_one and has_many are no longer relevant with the new API. But shallow routes is.

  • jolohaga

    jolohaga April 10th, 2010 @ 02:30 PM

    Sorry for the late suggestion, but it seems to me that shallow should be the default and :shallow => false should be required to override it. Assuming most people want shallow, it should have the simpler interface.

  • jolohaga

    jolohaga April 11th, 2010 @ 07:37 PM

    The :only and :except hash arguments work fine. Shallow actions seem to me to be the equivalent of applying :only => [:index,:create,:new] to the nested resource. Am I wrong in that interpretation?

    One thought is creating a method returning :only => [:index,:create,:new]. An untested and simplistic sketch of this is:

    application_extensions = %q{
      def shallow
        {:only => [:index, :create, :new]}
      end}
    ActionDispatch::Routing::Mapper.module_eval(application_extensions)
    

    In the resource definition:

    resources :roles do
      resources :rights, shallow
    end
    
  • Balazs Nagy

    Balazs Nagy April 11th, 2010 @ 11:45 PM

    Close, but no cigar. What about the other half? (err, the larger half...)

    we have to have another half of this:

    def shallow_root
      { :only => [:show, :edit, :update, :destroy] }
    end
    def shallow
      { :only => [:index, :create, :new] }
    end
    

    and doing our homework in routes.rb:

    resources :roles do
      resources :rights, shallow
    end
    resources :rights, shallow_root
    

    Moreover, it would need more type if it's deeper:

    resources :publishers, :shallow => true do
      resources :magazines do
        resources :photos
      end
    end
    

    vs.

    resources :publishers do
      resources :magazines, shallow
    end
    resources :magazines, shallow_root do
      resources :photos, shallow
    end
    resources :photos, shallow_root
    

    I'd say it's not cleaner than it was, nevertheless it can be implemented this way. I could write all of my codes in Fortran too, of course.

  • Yehuda Katz (wycats)

    Yehuda Katz (wycats) April 13th, 2010 @ 05:59 AM

    • State changed from “open” to “needs-more-info”

    Can someone explain the use-case for shallow routes to me? Specifically, why you wouldn't just make your routes shallow to begin with?

  • Andrew White

    Andrew White April 13th, 2010 @ 11:33 AM

    Basically you want to be able to scope your collection action to a parent resource but the actual member actions can be performed on a shallow route as the id is unique across all parents. It helps prevent loads of long url helper method calls, e.g:

      resources :posts do
        resources :comments
      end
    
      # Edit comment with shallow route
      <%= link_to('Edit', edit_comment_path(@comment)) %>
      # vs. non-shallow route
      <%= link_to('Edit', edit_post_comment_path(@post, @comment)) %>
    

    Since you can get this behaviour using :only and :except I'm not sure that it's worth adding the complexity to the mapper, e.g:

      resources :posts do
        resources :comments, :only => [:index, :new, :create]
      end
    
      resources :comments, :only => [:show, :edit, :update, :destroy]
    

    This to me has a clearer intent than a magical option called :shallow

  • Balazs Nagy

    Balazs Nagy April 13th, 2010 @ 03:21 PM

    I have two answers for wycats' question:

    You can nest resources with no end like:

    resources :users do
      resources :shipping_orders do
        resources :consignments
      end
    end
    

    It's very handy to write it like this, however, you don't want to have all the long paths this route generates. What you really want is this:

    resources :users do
      resources :shipping_orders, :only => [:index, :new, :create]
    end
    resources :shipping_orders, :only => [:show, :edit, :update, :destroy] do
      resources :consignments, :only => [:index, :new, :create]
    end
    resources :consingments, :only => [:show, :edit, :update, :destroy]
    

    This latter is, while creates the routes we need precisely, is full with repeated code, it's not as readable as the previous format, therefore more error-prone (my bad, I don't have route tests).

    Sure, it's not bullet-proof, and my argument can be defeated by just asking whether is this the only way you want to categorize, let's say shipping orders? Maybe you want to bind it to a route too, which will require GET /routes/NNN/shipping_orders path?

    Not too convincing, I know, but here's my another answer:

    Shallow nesting is in Rails since version 2.2, and the release notes describes shallow route nesting. We have to give users at least an upgrade path.

  • Steve St. Martin

    Steve St. Martin April 15th, 2010 @ 02:54 PM

    It's primarily a way of simplifying nested routes so rather then having /project/1/comments/2/edit you can use /comments/2/edit without loosing /projects/1/comments. As Balazs demonstrated with the existing API its still possible, just not as clean.

    I'm all for if shallow is on by default.

  • Balazs Nagy

    Balazs Nagy April 16th, 2010 @ 11:43 AM

    This is the most clean version I can come up with.

  • Andrew White

    Andrew White April 16th, 2010 @ 05:37 PM

    Balazs, when you use the routes from the old shallow testing you get an error:

    resources :threads, :shallow => true do
      resources :messages do
        resources :comments do
          member do
            post :preview
          end
        end
      end
    end
    
    $ ruby dispatch/routing_test.rb
    /actionpack/lib/action_dispatch/routing/mapper.rb:644:in `member': can't use member outside resources scope (ArgumentError)
    from dispatch/routing_test.rb:118
    from /actionpack/lib/action_dispatch/routing/mapper.rb:589:in `resources'
    from dispatch/routing_test.rb:117
    from /actionpack/lib/action_dispatch/routing/mapper.rb:589:in `resources'
    from dispatch/routing_test.rb:116
    from /actionpack/lib/action_dispatch/routing/mapper.rb:589:in `resources'
    from dispatch/routing_test.rb:115
    from /actionpack/lib/action_dispatch/routing/route_set.rb:216:in `instance_exec'
    from /actionpack/lib/action_dispatch/routing/route_set.rb:216:in `draw'
    from dispatch/routing_test.rb:17
    from ./abstract_unit.rb:174:in `stub_controllers'
    from dispatch/routing_test.rb:15
    

    It looks as though your patch is getting the scope_level wrong somehow.

  • Balazs Nagy

    Balazs Nagy April 17th, 2010 @ 08:19 AM

    • Tag changed from :shallow_routes, patch, rails3, router to :shallow_routes, rails3, router

    Ouch. Then, IMHO it's safe to say my second try is a dead end too. My second patch's core was to move the yield out of resources' scope setting. We can either patch all the dsl stuff to honor this setting, or we have to find another way. It was a nice try, nevertheless.

  • Diego Carrion

    Diego Carrion April 19th, 2010 @ 12:41 AM

    I worked on this today and Im attaching a patch covering the following scenarios:

    resources :users, :shallow => true do
      resources :photos do
        resources :types do
          member do
            post :preview
          end
          collection do
            delete :erase
          end
        end
      end
    end
    
    scope :shallow => true do
      resources :teams do
        resources :players
      end
    
      resources :countries do
        resources :cities do
          resources :places
        end
      end
    end
    

    I can take a time to do more refactoring in the code case the behavior is ok and the patch accepted.

  • Diego Carrion

    Diego Carrion April 19th, 2010 @ 12:58 AM

    • Tag changed from :shallow_routes, rails3, router to :shallow_routes, patch, rails3, router
  • Balazs Nagy

    Balazs Nagy April 19th, 2010 @ 12:02 PM

    Hmm, changing the other part. Nice. It seems there's a problem though (I'll try it out later today), your patch sets @scope[:name_prefix] to nil if we have @scope[:shallow], and setting @scope[:path] directly is a bit messy to me. What if resources ... :shallow => true is embedded in another resources block? My previous patch tried to handle this by cutting out the middle of path and name_prefix, but I think it was ugly.

    Anyways, the more I'm thinking about the solution, the more I feel this functionality should go to a separate gem instead.

  • Diego Carrion

    Diego Carrion April 19th, 2010 @ 04:18 PM

    I think the problem doesn't exists because at the end of the scope, the name_prefix and path are restored.

    I think if for this reason the other tests didn't break.

  • Balazs Nagy

    Balazs Nagy April 19th, 2010 @ 05:08 PM

    After applying your patch, the following test fails:

    ...
          resources :hosts do
            resources :publishers, :shallow => true do
              resources :magazines do
                resources :photos
                resources :columns
              end
            end
          end
    ...
    
      def test_shallow_nesting_with_a_twist
        with_test_routes do
          assert_equal '/hosts/1', host_path(1)
          assert_equal '/hosts/1/publishers', host_publishers_path(1)
          assert_equal '/hosts/1/publishers/1', host_publisher_path(1, 1)
          assert_equal '/hosts/1/publishers/1/magazines', host_publisher_magazines_path(1, 1)
          assert_equal '/hosts/1/magazines/2', host_magazine_path(1, 2)
          assert_equal '/hosts/1/magazines/2/photos', host_magazine_photos_path(1, 2)
          assert_equal '/hosts/1/magazines/2/columns', host_magazine_columns_path(1, 2)
          assert_equal '/hosts/1/photos/3', host_photo_path(1, 3)
          assert_equal '/hosts/1/columns/4', host_column_path(1, 4)
        end
      end
    

    It says:

    ike:~/Code/vendor/rails/actionpack/test [master]>>% ruby -I. dispatch/routing_test.rb
    Loaded suite dispatch/routing_test
    Started
    ...................................................E........
    Finished in 0.359437 seconds.
    
      1) Error:
    test_shallow_nesting_with_a_twist(TestRoutingMapper):
    NoMethodError: undefined method `host_publisher_path' for #<TestRoutingMapper:0x00000100d30b70>
        /Users/js/Code/vendor/rails/actionpack/lib/action_dispatch/testing/assertions/routing.rb:174:in `method_missing'
        /Users/js/Code/vendor/rails/actionpack/lib/action_dispatch/testing/integration.rb:369:in `method_missing'
        dispatch/routing_test.rb:769:in `block in test_shallow_nesting_with_a_twist'
        dispatch/routing_test.rb:1073:in `with_test_routes'
        dispatch/routing_test.rb:766:in `test_shallow_nesting_with_a_twist'
        /Users/js/.rvm/gems/ruby-1.9.2-head/gems/mocha-0.9.8/lib/mocha/integration/mini_test/version_131_and_above.rb:26:in `run'
        /Users/js/Code/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb:32:in `block in run'
        /Users/js/Code/vendor/rails/activesupport/lib/active_support/callbacks.rb:418:in `_run_setup_callbacks'
        /Users/js/Code/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb:31:in `run'
    
    60 tests, 259 assertions, 0 failures, 1 errors, 0 skips
    
    Test run options: --seed 57098
    

    This is why I'm telling setting things directly doesn't solve all of the problems.

  • Diego Carrion

    Diego Carrion April 19th, 2010 @ 05:35 PM

    Now I understand your point, sorry.

    Btw, if the resource publisher is shallow, I think the named route should be:

    publisher_path

    do you agree with me?

    Anyway, does this case make sense and is relevant? By the given arguments for the functionality, I think doesn't it make much sense to have some resources with shallow routes and others without. Tell me if I wrong.

  • Balazs Nagy

    Balazs Nagy April 19th, 2010 @ 08:47 PM

    The real point is to do the same as rails 2.3.5 does. And it seems you're right.

    This is my test router.rb:

    ActionController::Routing::Routes.draw do |map|
      map.resources :hosts do |host|
        host.resources :publishers, :shallow => true do |publisher|
          publisher.resources :photos
          publisher.resources :columns
        end
      end
    end
    

    and here's a list of routes (I filtered create, update, and destroy routes out):

    
    ike:~/Code/rails2-test/config>>% rake routes | egrep -v 'create|update|destroy'
    (in /Users/js/Code/rails2-test)
        publisher_photos GET    /publishers/:publisher_id/photos(.:format)      {:controller=>"photos", :action=>"index"}
     new_publisher_photo GET    /publishers/:publisher_id/photos/new(.:format)  {:controller=>"photos", :action=>"new"}
              edit_photo GET    /photos/:id/edit(.:format)                      {:controller=>"photos", :action=>"edit"}
                   photo GET    /photos/:id(.:format)                           {:controller=>"photos", :action=>"show"}
       publisher_columns GET    /publishers/:publisher_id/columns(.:format)     {:controller=>"columns", :action=>"index"}
    new_publisher_column GET    /publishers/:publisher_id/columns/new(.:format) {:controller=>"columns", :action=>"new"}
             edit_column GET    /columns/:id/edit(.:format)                     {:controller=>"columns", :action=>"edit"}
                  column GET    /columns/:id(.:format)                          {:controller=>"columns", :action=>"show"}
         host_publishers GET    /hosts/:host_id/publishers(.:format)            {:controller=>"publishers", :action=>"index"}
      new_host_publisher GET    /hosts/:host_id/publishers/new(.:format)        {:controller=>"publishers", :action=>"new"}
          edit_publisher GET    /publishers/:id/edit(.:format)                  {:controller=>"publishers", :action=>"edit"}
               publisher GET    /publishers/:id(.:format)                       {:controller=>"publishers", :action=>"show"}
                   hosts GET    /hosts(.:format)                                {:controller=>"hosts", :action=>"index"}
                new_host GET    /hosts/new(.:format)                            {:controller=>"hosts", :action=>"new"}
               edit_host GET    /hosts/:id/edit(.:format)                       {:controller=>"hosts", :action=>"edit"}
                    host GET    /hosts/:id(.:format)                            {:controller=>"hosts", :action=>"show"}
    

    What else I can say? I approve this patch ;)

  • Daniel Libanori

    Daniel Libanori April 24th, 2010 @ 10:08 PM

    Balazs Nagy,

    I have applied your patch and I am having an exception. It is not working with member and collection but Rails 2.3.5 does. It needs some change to bring the same functionality as 2.3.5.

  • Balazs Nagy

    Balazs Nagy April 30th, 2010 @ 05:04 PM

    Daniel,

    Have you tried Diego's patch? I strongly recommend that, which is working.

  • Daniel Libanori

    Daniel Libanori April 30th, 2010 @ 05:50 PM

    I don't want to be rude, but I really don't like how Routes API was implemented.

    I think it should use something like an abstract syntax tree instead of change a more general scope variable. This implementation is error prone and hard to understand and debug.

    Routes are generated at boot time, we don't need to have a hard to read code just to it be fast.

    Am I alone?

  • Anthony Chivetta

    Anthony Chivetta June 6th, 2010 @ 09:22 AM

    bump

    What's the status of this issue? Lighthouse says "needs-more-info", is that really the case? If so, what additional information is needed?

  • Simon Hafner

    Simon Hafner June 7th, 2010 @ 09:40 AM

    By REST theory, every resource should have an unique URL. Probably generate short helpers that create the same long URL? There are a bunch of URL shorteners out there.

  • Darren Hinderer

    Darren Hinderer June 7th, 2010 @ 11:32 PM

    I just ran into this when converting an app to rails 3. My application has 3 tiers of resources and the shallow nesting made things nice.

    Honestly, I can deal if it goes away but I'd just like to know one way or the other so I can finish my upgrade.

  • Repository

    Repository June 8th, 2010 @ 12:09 AM

    • State changed from “needs-more-info” to “committed”
  • Andrew White

    Andrew White June 8th, 2010 @ 12:56 AM

    I don't think this is fixed correctly - the attached patch is the old shallow routing tests ported to the new mapper and they don't pass.

  • Darren Hinderer

    Darren Hinderer June 8th, 2010 @ 01:13 AM

    Ya it's broken for me too. The thing that will break the current tests is if you add a singular "resource" to one of the shallowly next routes.

    
          shallow do
            resources :teams do
              resources :players
            end
          
            resources :countries do
              resources :cities do
                resources :places
                resource :break_me
              end
            end
          end
    
  • DHH

    DHH June 8th, 2010 @ 08:39 PM

    • State changed from “committed” to “open”
    • Assigned user changed from “DHH” to “josh”

    This is broken in various ways still. JP looking into it.

  • josh

    josh June 8th, 2010 @ 09:25 PM

    We're going to revert 67a60ee314f53abcde78f8ecd2a1f7c9ef8264e1.

    1) It didn't work with singleton resources
    2) It was a kind of hacky way to inject shallowing into scope merging.

    I think we could implement it cleaner on top of a "exclusive_scope" method that would reset the current scope and put you at the root for just those member actions.

    We'd like to see this in before the RC, so please post implementations.

  • Diego Carrion

    Diego Carrion June 8th, 2010 @ 10:09 PM

    Maybe somebody can add the new tests, make them pass and then refactor.

  • Diego Carrion

    Diego Carrion June 9th, 2010 @ 06:13 AM

    I made a new patch with support for singleton resources and with some refactors.

  • Diego Carrion
  • Andrew White

    Andrew White June 10th, 2010 @ 06:41 PM

    Okay here's my stab at it. I've had to rework how the resource route names were being built - whilst the new way is a fairly meaty block of code and isn't as clever as it was previously, I think it's easier to patch and there's no magic setting :as to "" to get things to work. There's also been some other refactoring as well. I've also taken account of namespaces which I don't think Diego's patch does.

  • Repository
  • DHH

    DHH June 17th, 2010 @ 03:54 PM

    • State changed from “open” to “committed”
  • Rolf Bjaanes

    Rolf Bjaanes June 18th, 2010 @ 03:37 PM

    This commmit creates conflicts for us.
    Same method points to both steps and section related member actions.

    rake routes:

    
       sector_add_document        /sectors/:sector_id/steps/:id/add_document/:document_id(.:format)       {:conditions=>{:method=>:post}, :controller=>"steps", :action=>"add_document"}
    sector_remove_document        /sectors/:sector_id/steps/:id/remove_document/:document_id(.:format)    {:conditions=>{:method=>:post}, :controller=>"steps", :action=>"remove_document"}
    
                                  /sectors/:sector_id/sections/:id/add_document/:document_id(.:format)    {:conditions=>{:method=>:post}, :controller=>"sections", :action=>"add_document"}
                                  /sectors/:sector_id/sections/:id/remove_document/:document_id(.:format) {:conditions=>{:method=>:post}, :controller=>"sections", :action=>"remove_document"}
    
    

    routes gist (relevant parts): https://gist.github.com/ca9301d1ff00acb3c5c0

  • Andrew White

    Andrew White June 18th, 2010 @ 05:07 PM

    The routes are still correct, it's just that they're named the same so the later ones win. You route definitions need rewriting firstly as :conditions => { :method => :post } is no longer the correct way to restrict the HTTP method - you can either use the :via option or the HTTP method helpers:

      # Using HTTP method helpers
      post "add_document/:document_id(.:format)" => "sections#add_document", :as => :add_document
      post "remove_document/:document_id(.:format)" => "sections#remove_document", :as => :remove_document
    
      # Using :via option
      match "add_document/:document_id(.:format)" => "steps#add_document", :as => :add_document, :via => :post
      match "remove_document/:document_id(.:format)" => "steps#remove_document", :as => :remove_document, :via => :post
    

    Onto the question of the names of the url helpers. I refactored how the resource url helper names were built so that the correct name were generated for shallow url helpers - otherwise the namespace_prefix had already been updated by the time the member actions were generated and it got really messy to try undo the name prefix. This refactored naming is triggered when you pass a symbol a method, e.g:

      resources :documents do
        member do
          post :remove_document
        end
      end
    

    By specifying the path, controller and action you bypass this automatic naming. The quickest fix is for you to specify the full helper name using :as (e.g. :as => :step_add_document). The question is whether to automatically prefix the :as option and whether to add the resource name before or after the :as option. Since we're in the member scope it could be argued that the previous behaviour is a bug since member actions are added to the beginning of the name (e.g. add_document_step_path, not step_add_document_path). By not automatically prefixing the :as option you can decide which you prefer whereas automatically doing it takes that option away from you.

  • Rolf Bjaanes

    Rolf Bjaanes June 18th, 2010 @ 05:27 PM

    They are nested differently, but this is ignored since this commit.

    The original path methods was:

    
    sector_section_add_document
    sector_step_add_document
    

    and the gisted routes are nested within:

    
    resources :sections do
       # gist content here
    end
    
  • Andrew White

    Andrew White June 18th, 2010 @ 05:46 PM

    Rolf, my previous answer still applies - if you use :as => :section_add_document then it will come out as sector_section_add_document. However it'll likely be changing to automatically prefix the :as onto the (nested) resource name, e.g.

    
      resources :sectors do
        resources :sections do
          resources :documents
          member do
            # Helper method will become add_document_sector_section_path
            post "add_document/:document_id(.:format)" => "sections#add_document", :as => :add_document
          end
        end
      end
    
  • Andrew White

    Andrew White June 19th, 2010 @ 07:59 AM

    Attached patch to scope custom resource routes using match

  • Repository
  • Rolf Bjaanes

    Rolf Bjaanes June 20th, 2010 @ 01:19 PM

    @Andrew:

    I agree that your reply offers a solution, but I didn't think the extra configuration should be necessary.

    Thanks for your fix.

    It changes the default methods from

    sector_step_add_document_path
    

    to the following
    add_document_sector_step_path
    

    I am not sure what reads best.
    Your fix is probably the better.

    What do you think?

  • Rolf Bjaanes

    Rolf Bjaanes June 20th, 2010 @ 01:44 PM

    On second thought:

    
    action_resource_resource_path
    

    seems much more consistent.

    Thanks, Andrew.
    Really appreciate it.

    Updating our code now.

  • Ryan Bigg

    Ryan Bigg October 9th, 2010 @ 10:05 PM

    • Tag cleared.
    • Importance changed from “” to “Low”

    Automatic cleanup of spam.

  • Aditya Sanghi

    Aditya Sanghi October 9th, 2010 @ 10:05 PM

    Automatic cleanup of spam.

  • Jeremy Kemper

    Jeremy Kemper October 15th, 2010 @ 11:01 PM

    • Milestone set to 3.0.2
  • Ryan Bigg

    Ryan Bigg October 21st, 2010 @ 03:35 AM

    Automatic cleanup of spam.

  • Jeff Kreeftmeijer
  • Jeff Kreeftmeijer
  • Alex

    Alex January 3rd, 2011 @ 09:48 AM

    Until shallow routes are implemented in Rails 3, are there any recommended workarounds when 2 levels deep nested resources are required?

    Official Rails guidance identifies that 'Resources should never be nested more than 1 level deep.', but does not mention shallow routes at all. (http://bit.ly/fmibN1)

  • DHH

    DHH January 3rd, 2011 @ 10:22 AM

    Alex, shallow was added back before release:

    • Add shallow routes back to the new router [Diego Carrion, Andrew White]

      resources :posts do shallow do

      resources :comments
      

      end end

      You can now use comment_path for /comments/1 instead of post_comment_path for /posts/1/comments/1.

  • bingbing
  • klkk

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Referenced by

Pages