Let's assume I have models: Article, Post, and Comment. For these models I need to map CommentsController#show in articles and posts. Something like this:
resources :articles do
resources :comments, :only => [:show]
end
resources :posts do
resources :comments, :only => [:show]
end
And this works perfectly, i.e. it'll generate routes something like this:
/articles/:article_id/comments/:id
/posts/:post_id/comments/:id
Both pointing to the same controller's single method: CommentsController#show
What I need is to include more/multiple parameters for posts while retaining the same URL routes to CommentsController:
/articles/:article_id/comments/:id
/posts/:post_id/:post_title/:post_year/comments/:id
I tried match but first occurrence at resources :articles do... overrides it.
resources :articles do
resources :comments, :only => [:show]
end
match '/posts/:post_id/:post_title/:post_year/comments/:id', :to => 'comments#show', :as => :show_post_comments
It throws an error:
No route matches {:controller=>"comments", :action=>"show",
:post_id=>10, :post_title=>"some title", :post_year=>"1995", :id=>"1"}
So, is it possible to create such a route with multiple parameters to single controller's method in two resources using get or something?
Related
I'm actually having trouble finding the documentation for this so if you have a link handy that would be really appreciated too.
So I have:
resources :users do
resources :posts, only: [:index, :create, :show]
end
I wanted to access the index action of posts through a named route. I tried this: <%= link_to 'User Posts', user_posts_path %> but it said it was missing user_id. Any ideas?
When using the nested resource routes, you would need to provide the reference id of the parent resource. In your case resource user. You could do: user_posts_path(user). The route generated would be something like: /users/1/posts where 1 is the :user_id or if you would rather want a route like: /users/posts you should do:
resources :users do
collection do
resources :posts
end
end
Find full routing documentation here
it's asking for user_id because you're defining :users as a resource, change it for a namespace instead:
namespace :users do
resources :posts, only: [:index, :create, :show]
end
I changed the routing of posts#index to match blog and I now get /blog in the URL which I was trying to accomplish.
I've tried several different things to get my actual blog post which the route currently looks something like /posts/this-is-a-test to also use blog rather than posts in the URL.
Below is my current route file. I am using the friendly_id gem, if that makes any difference in answering this question.
resources :posts do
resources :comments
end
resources :contacts, only: [:new, :create]
root "pages#home"
get "/home", to: "pages#home", as: "home"
get "about" => 'pages#about'
get "pricing" => 'pages#pricing'
get "contact_us" => 'pages#contact_us'
match 'blog', to: 'posts#index', via: :all
end
path option along with resource must help.
resources :posts, :path => 'blogs' do
resources :comments
end
This will change all /posts and /post to /blogs/ and /blog.
If you want to change your route's helper methods such as posts_path to blogs_path and new_post_path to new_blog_path etc, you can change it with as tag.
resources :posts, :path => 'blogs', :as => 'blogs' do
resources :comments
end
Or yet better, you can specify the controller and route blogs directly as:
resources :blogs, controller: 'posts' do
resources :comments
end
This is the awesomeness of Rails! :)
match 'blog/:id' => 'posts#show'
should work. But if you want to match every method in posts controller to blog (and you don't want to use the posts path), I would just rename the controller to blog instead and add resource :blog in the routes.
This helped me, from official guides documentation, add this in your routes.rb file:
get '/patients/:id', to: 'patients#show', as: 'patient'
In Ruby on Rails, is there a way to add another RESTful action to the base URL of a plural resource? I'm looking for something like this:
resources :groups do
resources :users do
put on: :base, to: 'users#update_all'
end
end
Which would generate the route: [PUT] groups/:group_id/users => users#update_all
I've already tried doing this:
resources :groups do
resources :users
put 'users', on: :member, to: 'users#update_all'
end
But that doesn't preserve the value of params[:group_id] in the controller.
resources :users do
collection do
put '' => 'users#update_all' ## PUT /users
end
end
UPDATE
It would be recommended to do this though:
resources :users do
collection do
put 'update_all' ## PUT /users/update_all
end
end
Both route to the update_all action of the users controller.
RESOURCES
http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
Using this as an example contexted:
Post has_many comments
Comment belongs_to post
I have a route that looks like:
resources :posts do
resources :comments
end
How do i create a route that exposes comments#index?
An example use case would be... I want to list ALL comments in the system on a page. Essentially using the comments resource as if it's not nested when a user hits /comments
thank you!
Try this.
resources :posts do
resources :comments, :except => :index
end
match 'comments' => 'comments#index', :as => :comments
That said, I usually look to avoid routes like this because I like a tidy RESTful routes file, but sometimes it can't be helped.
Second option:
resources :posts do
resources :comments, :except => :index
get :comments, :on => :collection
end
In the second option, you'd want to remove the index action from the comments controller and create a comments action in your posts controller.
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"