What is the difference between resources and namespace in rails nested routing - ruby-on-rails

What is the difference between
namespace :alpha do
resources :posts
end
and
resources :alpha do
resources :posts
end

Check out the difference using rake routes.
This definition with a namespace:
namespace :alpha do
resources :posts
end
results in the following routes:
Prefix Verb URI Pattern Controller#Action
alpha_posts GET /alpha/posts(.:format) alpha/posts#index
POST /alpha/posts(.:format) alpha/posts#create
new_alpha_post GET /alpha/posts/new(.:format) alpha/posts#new
edit_alpha_post GET /alpha/posts/:id/edit(.:format) alpha/posts#edit
alpha_post GET /alpha/posts/:id(.:format) alpha/posts#show
PATCH /alpha/posts/:id(.:format) alpha/posts#update
PUT /alpha/posts/:id(.:format) alpha/posts#update
DELETE /alpha/posts/:id(.:format) alpha/posts#destroy
As you can see, the only thing that is different from a plain resources route set is the addition of /alpha prefix.
Now for the two-level resources routes definition:
resources :alpha do
resources :posts
end
which results in:
Prefix Verb URI Pattern Controller#Action
alpha_posts GET /alpha/:alpha_id/posts(.:format) posts#index
POST /alpha/:alpha_id/posts(.:format) posts#create
new_alpha_post GET /alpha/:alpha_id/posts/new(.:format) posts#new
edit_alpha_post GET /alpha/:alpha_id/posts/:id/edit(.:format) posts#edit
alpha_post GET /alpha/:alpha_id/posts/:id(.:format) posts#show
PATCH /alpha/:alpha_id/posts/:id(.:format) posts#update
PUT /alpha/:alpha_id/posts/:id(.:format) posts#update
DELETE /alpha/:alpha_id/posts/:id(.:format) posts#destroy
alpha_index GET /alpha(.:format) alpha#index
POST /alpha(.:format) alpha#create
new_alpha GET /alpha/new(.:format) alpha#new
edit_alpha GET /alpha/:id/edit(.:format) alpha#edit
alpha GET /alpha/:id(.:format) alpha#show
PATCH /alpha/:id(.:format) alpha#update
PUT /alpha/:id(.:format) alpha#update
DELETE /alpha/:id(.:format) alpha#destroy
As you can see, alpha becomes a top-level resource with all 8 RESTful routes. posts, in turn, become second-level resource, accessible only through the route to a specific alpha object.
Read more in Rails Routing from the Outside In.
You might also find interesting the scope option. Read about the difference between scope and namespace in Scoping Rails Routes blog post.

Related

Rails routes index for nested resource

I'm searching a reason why rake routes doesn't match the index path of my nested resource.
Here is my code:
namespace :api do
resources :photos do
resource :comments
end
end
Here is the result of the command: rake routes | grep comment
batch_action_admin_user_comments POST /admin/user_comments/batch_action(.:format) admin/user_comments#batch_action
admin_user_comments GET /admin/user_comments(.:format) admin/user_comments#index
POST /admin/user_comments(.:format) admin/user_comments#create
new_admin_user_comment GET /admin/user_comments/new(.:format) admin/user_comments#new
edit_admin_user_comment GET /admin/user_comments/:id/edit(.:format) admin/user_comments#edit
admin_user_comment GET /admin/user_comments/:id(.:format) admin/user_comments#show
PATCH /admin/user_comments/:id(.:format) admin/user_comments#update
PUT /admin/user_comments/:id(.:format) admin/user_comments#update
DELETE /admin/user_comments/:id(.:format) admin/user_comments#destroy
admin_comments GET /admin/comments(.:format) admin/comments#index
POST /admin/comments(.:format) admin/comments#create
admin_comment GET /admin/comments/:id(.:format) admin/comments#show
api_photo_comments POST /api/photos/:photo_id/comments(.:format) api/comments#create
new_api_photo_comments GET /api/photos/:photo_id/comments/new(.:format) api/comments#new
edit_api_photo_comments GET /api/photos/:photo_id/comments/edit(.:format) api/comments#edit
GET /api/photos/:photo_id/comments(.:format) api/comments#show
PATCH /api/photos/:photo_id/comments(.:format) api/comments#update
PUT /api/photos/:photo_id/comments(.:format) api/comments#update
DELETE /api/photos/:photo_id/comments(.:format) api/comments#destroy
I tried to add only: [:create, :index] to my comments resource but only the create route is visible.
According to the documentation about nested-resources I don't understand what's happening.
Thank you for your help.
It's because you are using a singular resource (resource :comments)
From the docs:
Sometimes, you have a resource that clients always look up without
referencing an ID. For example, you would like /profile to always show
the profile of the currently logged in user. In this case, you can use
a singular resource to map /profile (rather than /profile/:id) to the
show action
You'll need to use the standard resources method to get this working (resource omits the index action):
#config/routes.rb
namespace :api do
resources :photos do
resources :comments
end
end
My mistake. A "S" was missing on my resource.
namespace :api do
resources :photos do
resources :comments
end
end
Now it works.

Rails nested resources and paths

in my routes.rb I have:
resources :boards do
resources :items
end
now in boards#show I want to show a link to http://mysite/baord/:board_id/items/new, running rake routes I get:
new_board_item GET /boards/:board_id/items/new(.:format) items#new
and so I should be able to use new_board_item_path but this works only from site.com/board/:board_id/items but i want to use this link in boards#show action but it tells me that:
No route matches {:action=>"new", :controller=>"items"}
while that's not true!
Pass the parent resource into the path, so in this case:
new_board_item_path(#board)

Rails 3 restful route problem

The following link works in my app:
<%= link_to "invitation", :controller => :invitations, :action => :index %>
To follow restful conventions i changed the link to:
<%= link_to "invitation", index_invitation_path %>
The error that i get is:
undefined local variable or method `index_invitation_path'
Rake routes yields:
invitations GET /invitations(.:format) {:controller=>"invitations", :action=>"index"}
The page name is index.html.erb. The model is invitation.rb. The controller is invitation_controller.rb. Routes has resources :invitations. What am i missing?
Thanks!
Assuming you have the routing correct:
resources :invitations
Then the correct helper for the index action (with the url /invitations.html) is
invitations_path
You can see more information by running rake routes. It will display text like the following:
lists GET /lists(.:format)
{:action=>"index", :controller=>"lists"}
POST /lists(.:format)
{:action=>"create", :controller=>"lists"}
new_list GET /lists/new(.:format)
{:action=>"new", :controller=>"lists"}
edit_list GET /lists/:id/edit(.:format)
{:action=>"edit", :controller=>"lists"}
list GET /lists/:id(.:format)
{:action=>"show", :controller=>"lists"}
PUT /lists/:id(.:format)
{:action=>"update", :controller=>"lists"}
DELETE /lists/:id(.:format)
{:action=>"destroy", :controller=>"lists"}
root /(.:format)
{:controller=>"lists", :action=>"index"}
The above was from a route of my own (for a model called List). The route helper method is shown immediately before the HTTP method. You have to remember to append the _path to each helper method. For example the helper methods I could use are:
list_path(list)
edit_list_path(list)
new_list_path
lists_path
You'll need a route in your routes.rb file that defines a mapping to the invitations controller and the index action.
Typically this is created with a resources call
resources :invitations
Which creates several default routes, which you can see by running rake routes.
For single resources, you can also define it using a match call
match "invitations/:id" => "invitations#index", :as => index_invitation
The rails site has a great resource on routing that provides all the details: Routing from the Outside In
Update: Based on your updated question, your route includes an invitaions (notice the trailing 's') route - nothing with index or invitation. The index_ prefix is generated by the resources call when it creates the default routes for :invitations.
It looks like you've defined a custom get mapping for an invitation. While this may technically work, if you're aim is to support restful routes, use the resources method. And have a read of the Routing guide from rails it's very easy to follow and quite detailed.
type rake routes in your console and look at listing of available routes. Seems to be there is no such route index_invitation_path? maybe it named differently
I think you need "invitations_controller.rb" to contain InvitationsController. Plural.

Rails 2 Namespace and Shallow Routes Issue

I've written the admin area of a particular rails app and now I'm ready to set it as own section within the website.
Therefore, it will be /admin
However, I didn't want to have it as /admin within the route itself I wanted to have something less common, so I added a couple of hyphens before and after it.
So the route is /-admin-/ and the namespace is Admin.
After setting this up using :path_prefix => "/-admin-", I have the following code block:
map.namespace "/-admin-/", :name_prefix => "", :path_prefix => "/-admin-" do |admin|
This works for all but shallow routes, instead, in the rake routes output the output is:
new_page GET /-admin-/areas/:area_id/pages/new(.:format) {:action=>"new", :controller=>"admin/pages"}
edit_admin_page GET /admin/pages/:id/edit(.:format) {:action=>"edit", :controller=>"admin/pages"}
admin_page GET /admin/pages/:id(.:format) {:action=>"show", :controller=>"admin/pages"}
PUT /admin/pages/:id(.:format) {:action=>"update", :controller=>"admin/pages"}
DELETE /admin/pages/:id(.:format) {:action=>"destroy", :controller=>"admin/pages"}
areas GET /-admin-/areas(.:format) {:action=>"index", :controller=>"admin/areas"}
POST /-admin-/areas(.:format) {:action=>"create", :controller=>"admin/areas"}
new_area GET /-admin-/areas/new(.:format) {:action=>"new", :controller=>"admin/areas"}
Notice how the shallow-routed routes are prefixed as /admin/ and not as /-admin-/ (as are their parent routes).
Any ideas on how to get around this? Is this a bug in rails or do I need to work around it? I tried adding the :path_prefix to each nested route but it doesn't do anything?
Any ideas?
I'm not sure about your rationale on not using /admin - security through obscurity isn't really security - you should be using something like authlogic to keep out unauthorised users.
Try the following to namespace your admin controllers:
map.namespace :admin, :path_prefix => "-admin-" do |admin|
admin.resources :users
admin.resources :pages
end
A sample generated route:
admin_users GET /-admin-/users(.:format) {:controller=>"admin/users", :action=>"index"}
There is no way to get around this. Turns out that all versions of Rails will break down the URL and its resource names to their lowest points when they're set to shallow. The only solution to this is to set all of your resource routes manually without using map.resources.

difference between collection route and member route in ruby on rails?

What is the difference between collection routes and member routes in Rails?
For example,
resources :photos do
member do
get :preview
end
end
versus
resources :photos do
collection do
get :search
end
end
I don't understand.
A member route will require an ID, because it acts on a member. A collection route doesn't because it acts on a collection of objects. Preview is an example of a member route, because it acts on (and displays) a single object. Search is an example of a collection route, because it acts on (and displays) a collection of objects.
URL Helper Description
----------------------------------------------------------------------------------------------------------------------------------
member /photos/1/preview preview_photo_path(photo) Acts on a specific resource so required id (preview specific photo)
collection /photos/search search_photos_path Acts on collection of resources(display all photos)
Theo's answer is correct. For documentation's sake, I'd like to also note that the two will generate different path helpers.
member {get 'preview'} will generate:
preview_photo_path(#photo) # /photos/1/preview
collection {get 'search'} will generate:
search_photos_path # /photos/search
Note plurality!
1) :collection - Add named routes for other actions that operate on the collection. Takes a hash of #{action} => #{method}, where method is :get/:post/:put/:delete, an array of any of the previous, or :any if the method does not matter. These routes map to a URL like /users/customers_list, with a route of customers_list_users_url.
map.resources :users, :collection => { :customers_list=> :get }
2) :member - Same as :collection, but for actions that operate on a
specific member.
map.resources :users, :member => { :inactive=> :post }
it treated as /users/1;inactive=> [:action => 'inactive', :id => 1]
Short Answer:
Both the member and collection blocks allow you to define additional routes for your resources than the seven standard routes that Rails will generate for you.
A member block creates new routes on a single member of the resource.
A collection block creates new routes for a collection of that resource.
Long Answer
Rails provides the member and collection blocks so you can define custom routes for both the resource collection and the individual resource.
Here's how you'd typically define routes for the article resource.
resources :articles
This creates the following routes.
➜ bin/rails routes -g article
Prefix Verb URI Pattern Controller#Action
articles GET /articles(.:format) articles#index
POST /articles(.:format) articles#create
new_article GET /articles/new(.:format) articles#new
edit_article GET /articles/:id/edit(.:format) articles#edit
article GET /articles/:id(.:format) articles#show
PATCH /articles/:id(.:format) articles#update
PUT /articles/:id(.:format) articles#update
DELETE /articles/:id(.:format) articles#destroy
But let's say you are writing your articles in markdown, and need to see a preview of the article as you write it.
You could create a PreviewController and display the article's preview using its show action, but it's convenient to add a preview action on the ArticlesController itself.
Custom Member Routes
Here's how you define the preview route on the ArticlesController using the member block.
resources :articles do
member do
get 'preview'
end
end
It adds a new route that directs the request to ArticlesController#preview action. The remaining routes remain unchanged. It also passes the article id in params[:id] and creates the preview_article_path and preview_article_url helpers.
➜ bin/rails routes -g article
Prefix Verb URI Pattern Controller#Action
preview_article GET /articles/:id/preview(.:format) articles#preview
... remaining routes
If you have a single member route, use the short-hand version by passing the :on option to the route, eliminating the block.
resources :articles do
get 'preview', on: :member
end
You can go one step further and leave out the :on option.
resources :articles do
get 'preview'
end
It generates the following route.
➜ bin/rails routes -g preview
Prefix Verb URI Pattern Controller#Action
article_preview GET /articles/:article_id/preview(.:format) articles#preview
There are two important differences here:
The article's id is available as params[:article_id] instead of params[:id].
The route helpers changes from preview_article_path to article_preview_path and preview_article_url to article_preview_url.
Custom Collection Routes
To add a new route for the collection of a resource, use the collection block.
resources :articles do
collection do
get 'search'
end
end
This adds the following new route. It will also add a search_articles_path and search_articles_url helper.
search_articles GET /articles/search(.:format) articles#search
If you don't need multiple collection routes, just pass :on option to the route.
resources :articles do
get 'search', on: :collection
end
This will add the same route as above.
Conclusion
Rails allows you to break out of its convention of using seven resourceful routes using the member and collection blocks. Both allow you to define additional routes for your resources than the standard seven routes.
A member block acts on a single member of the resource, whereas a collection operates on a collection of that resource.
Source: Define New Routes Using the Member and Collection Blocks

Resources