Rails 3, shallow routes

2019-04-06 12:42发布

问题:

In rails 2.x I used shallow routes, but this seems to be missing from rails 3 (at least in the API http://apidock.com/rails/ActionController/Resources/resources).

When I pass this option in rails 3 it doesn't throw any errors, but I'm also not getting all of the routes I expected.

Rails 3 routes.rb

  resources :users, :shallow=>true do
    resources :recipe do
      resources :categories do
        resources :sections do
          resources :details do
          end
        end
      end
    end
  end

The routes missing that were generated with the rails 2.x equivalent are (just a sample for the recipe resource):

GET new_recipe (I only have new_user_recipe), and

POST recipe (to create a new recipe, I only have POST user_recipe)

It kind of makes sense that these routes wouldn't be generated, but my old code worked around it by passing the user_id in each form (less elegant, agreed).

Question is: Is there documentation for 'shallow' routes in rails 3? Is there a way to generate the routes I'm missing from rails 2.x?

Thanks, Mike

回答1:

You need to apply the :shallow option to the nested resources. This should give you what you want:

  resources :users do
    resources :recipe, :shallow=>true do
      resources :categories do
        resources :sections do
          resources :details do
          end
        end
      end
    end
  end  


回答2:

If you look at the Rails 3 docs, you'll see that shallow is an instance method on ActionDispatch::Routing::Mapper::Resources, just like resource, resources, match, etc. You should be able to nest shallow routes with something like this:

shallow do
  resources :users do
    resources :recipe do
      resources :categories do
        resources :sections do
          resources :details
        end
      end
    end
  end
end

Though it only seems to expand them to 2 levels rather than the full nested route. Check out rake routes for more.



回答3:

You can find Rails 3 documentation relating to nested or shallow routes on the Rails Guides site.

While offering advice on how to nest routes, it specifically says that, "Resources should never be nested more than 1 level deep."



回答4:

It's reasonable that you only have new_user_recipe instead of new_recipe. Why? Because from the recipe's perspective, each and every recipe much belongs to a user.

Another point is that

resources :users, :shallow=>true do
  resources :recipe do
    resources :categories do
      resources :sections do
        resources :details do
        end
      end
    end
  end
end

is exactly the same as

resources :users do
  resources :recipe, :shallow=>true do
    resources :categories do
      resources :sections do
        resources :details do
        end
      end
    end
  end
end

:shallow is inherited as other users pointed out. Think about it, :shallow means you can omit the left part of the URL pattern once you are sure which exactly resource you are working on. If you put :shallow on the outer-most layer of your resource, it should have the same effect as you put it on the second layer (recipe in your example). Because you have nothing to omit when you are working on the outer-most resource (users in your example), it's already the left-most part of the URL pattern and it can't be omitted.