Resource route members. Plural url with singular method name? - ruby-on-rails

I have the following resource block
resources :projects, :except => [:destroy] do
resources :tasks, :except => [:index]
get "tasks/:id/change_state" => "tasks#change_state", :as => "task_change_state"
get "tasks/:id/assign_user" => "tasks#assign_user", :as => "task_assign_user"
get "tasks/:id/unassign" => "tasks#unassign", :as => "task_unassign"
end
I'm wondering how I can refactor those routes a bit without touching the path. I tried doing the following:
resources :projects, :except => [:destroy] do
resources :tasks, :except => [:index] do
member do
get 'change_state'
get 'assign_user'
get 'task_unassign'
end
end
end
But that leaves the route method names with tasks as plural. I need the URL to be plural, much like in the original get method call. But I need the method name to be singular, as I would prefer to not change the implementation across the app.

Related

Rails Adding New Page to Resource (with parameter)

I am trying to add a few new pages to a rails resource that I am creating.
What I am doing in my routes file is as follows:
resources :users, :only => [:index, :show] do
collection do
get :show_subpage1
end
end
When I look at my routes, show_subpage1 shows up, but not in the format I want. What shows up in the routes is:
show_subpage1_users GET /users/show_subpage1(.:format)
When what I WANT the route to be is:
show_subpage1_users GET /users/:id/show_subpage1(.:format)
(with the ID).
How would I go about doing that in rails?
To get:
show_subpage1_users GET /users/:id/show_subpage1(.:format)
do not define :show_subpage1 as a collection route:
resources :users, :only => [:index, :show] do
get :show_subpage1
end
or you could define it as a member route as follows:
resources :users, :only => [:index, :show] do
member do
get :show_subpage1
end
end
Also, I'm unsure why you have :only => [:index, :show] defined if you are also going to have a member route :show_subpage1. I assume you do want to add add :show_subpage1 to the only array, i.e. resources :users, :only => [:index, :show, :show_subpage1] do.
Please take a read on "Adding More RESTful Actions"
there are two ways with resources member or collection
resources :users, :only => [ :index, :show ] do
# /users/:id/profile
get 'profile', :on => :member
# /users/profile
get 'profile', :on => :collection
end
hope this helps

add new routes to a resource without the added param?

I would like to add a url to my comments route so I can call "post_comments_latest_path". I added something like 'get "comments/latest" => "comments#latest", :as => "latest"' but the route adds and the :commend_id to the path that is not needed. Any suggestions?
resources :posts, :except => [:index] do
resources :comments, :except => [:index, :show] do
post "replies" => "comments#create_reply", :as => "create_reply"
get "replies/new" => "comments#new_reply", :as => "new_reply"
end
end
This should work:
resources :posts, :except => [:index] do
resources :comments, :except => [:index, :show] do
post "replies" => "comments#create_reply", :as => "create_rely"
get "replies/new" => "comments#new_reply", :as => "new_reply"
get "latest", :on => "collection"
end
end
A Member route is one that links to a specific resource; requires an id.
A Collection route is one that links to a resource collection; does not require an id.
See the Rails Routing Guide for more information.

Rails 3 Routes: Override Topics#show with Posts#index

Pretty simple question, but I can't seem to figure out how to do this, even after scouring the Rails Routing guide.
Assume Topics has nested resource Posts.
The Posts for a Topic are all listed in Posts#index (/topics/:topic_id/messages). Topics#show does not serve any purpose. I would like Posts#index to be retrieved when the request is for /topics/:topic_id, without having to stick a redirect in the Topics controller.
Thank you!
UPDATE
I was able to get the desired result with this:
routes.rb
match 'forums/:forum_id' => 'topics#index', :as => 'forum_topics', :via => :get
match 'topics/:topic_id' => 'messages#index', :as => 'topic_messages', :via => :get
resources :forums, :shallow => true, :except => :show do
resources :topics, :shallow => true, :except => :show do
resources :messages
end
end
However, I'm not sure if this is the best method.
UPDATE 2
My method above breaks the other CRUD methods (like #create). Still looking for a solution to keep /messages out of the url.
add this route
get "/topics/:topic_id" => redirect("/topics/%{topic_id}/messages")
UPD
without redirecting:
get "/topics/:id" => "topic::Messages#index"
Or, if you're using shallow:
get "/topics/:id" => "messages#index"
resources :forums, :shallow => true, :except => :show do
resources :topics, :shallow => true, :except => :show do
resources :messages
end
end

Renaming path helpers in Rails 3 routing

I have a projects controller/model. Instead of listing projects on the #index page, I show a list of drop downs, which submits to projects#select, which finds the right Project (I've made sure there can only be 1 for each combination of options) and forwards the user to the #show page for that Project.
So for my routes I do this...
resources :projects, :only => [:index, :show] do
collection do
get 'select'
end
end
And thats fine, but the helper method for #select is 'select_projects', which is understandable but in my case I really want 'select_project'. And I really don't want to alias this in another file. No problem I can use :as...
resources :projects, :only => [:index, :show] do
collection do
get 'select', :as => 'select_project'
end
end
But now my helper is 'select_project_projects'. So I cheat a little (still better than aliasing in another file)...
resources :projects, :only => [:index, :show]
match '/projects/select', :to => 'projects#select', :as => 'select_project'
This looks like it might work, but it doesn't because /project/select actually matches the route for 'project#show'. Changing the order of the lines does the trick.
match '/projects/select', :to => 'projects#select', :as => 'select_project'
resources :projects, :only => [:index, :show]
But is there a more elegant way of handling this? I realize this is borderline OCD, but I'd like to be able to have complete control over the route name within the resources block.
use resource instead of resources
you probably don't want to make it a collection route but a member route:
resources :projects, :only => [:index, :show] do
member do
get 'select'
end
end
This way you'll have the select_project helper.
For those that want to rename the helper method side of things (as the title suggests):
resources :posts, as: "articles"

Multiple Nested Routes, is there a better way to do this?

So In my rails app I have two resources (rentals, and reservations) which belong to a user. This is the code in my routes.rb to set up the nested routes.
map.resources :users, :has_many => :reservations, :shallow => true
map.resources :users, :has_many => :rentals, :shallow => true
map.resources :rentals, :only => [:index]
map.resources :reservations, :only => [:index]
Is there a more perferred way to do this. I've done some googling but I can't find a clear answer.
Thanks in advance.
-ray
Your method duplicates the routes for users, as you can see by running rake routes. You can fix that by passing a block to map.resources:
map.resources :users, :shallow => true do |user|
user.resources :reservations
user.resources :rentals
end
The nested routes created will assume that you always want to access those resources in a nested fashion.
If you really need all the routes you've defined (including the non-nested rentals and reservations index) then you will need to add:
map.resources :rentals, :only => [:index]
map.resources :reservations, :only => [:index]
And I don't know of a DRYer way to do that.
Nests the two resources under users:
map.resources :users, :shallow => true do |users|
users.resources :reservations, :only => :index
users.resources :rentals, :only => :index
end
Edit: Sorry, forgot the :shallow option.
You can define nested routes with blocks
map.resources :users, :shallow => true do |user|
user.resources :reservations, :only => [:index]
user.resources :rentals, :only => [:index]
end
I feel that this way is a bit more clear and can more easily be adjusted later when you need additional options on one of the nested resources.
The different options and the details are at the ActionController Resources API page

Resources