Exposing a Specific Action of a Nested Route - ruby-on-rails

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.

Related

Two routes with multiple parameters to single controller's method?

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?

How to change a route name rails 4

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'

rails routing nested resources duplicate

I want to support:
POST images/1/comments/2/like
and
POST comments/2/like
They both point to same resources with same action. How can I do that in rails route file?
resources :images do
resources :comments do
member do
post 'like'
end
end
end
This will work for
POST images/1/comments/2/like
but how can I also for when I don't specify the images/1 part?
You can make it more beautiful actually. According to http://ruby-journal.com/how-to-dry-your-rails-routes/, this also works:
comments = Proc.new do
member do
post 'like'
end
end
resources :comments, &comments
resources :images do
comments.call
end
and in Rails 4 you could use concerns
concern :comments_concern do
member do
post 'like'
end
end
resources :comments, concerns: :comments_concern
resources :images, concerns: :comments_concern do
#do more stuff here
end
I didn't test this, but it might help. Have a look at the website mentioned. Good luck
-frbl
I would consider reworking which RESTful routes for Comment you're nesting, and which you're not. I'm assuming your models look something like this:
# app/models/image.rb
class Image < ActiveRecord::Base
has_many :comments
end
# app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :image
end
Because your Image and Comment models possess a one-to-many relationship, I can see why you'd think to nest the comments resource route within the images one. However, of all the CRUD actions in comments_controller.rb, only create actually requires that a parent image ID be explicitly passed in. From a RESTful perspective, only the new and create actions require that a image_id is passed to the action. The edit, update, delete, and like actions can all take place independently of the parent image.
Consider the alternative routing schematic instead:
# config/routes.rb
resources :images do
resources :comments, :only => [:index, :new, :create]
end
resources :comments, :only => [:show, :edit, :update, :destroy] do
member do
post 'like'
end
end
Now, only the comment actions that are explicitly depended on a parent ID are actually nested within the images routes. The remainder of the comment actions are directly routed to the comments controller without passing in the parent ID. Your routes are no longer duplicated, and each action will have exactly one route declared for it.
simply add resources :images it may work
Not sure there is a much more beautiful way than repeating this below:
resources :comments do
member do
post 'like'
end
end
Like so:
resources :images do
resources :comments do
member do
post 'like'
end
end
end
resources :comments do
member do
post 'like'
end
end

Rails routes- get a form and post the results at the same url

I have a page /sessions that displays a form.
I want to to post to itself and then display the results.
My routes currently look like this
namespace :api do
namespace :v1 do
resources :users do
match :all_users, :on => :collection, :as => "/users"
end
resources :sessions, :only => [ :index ]
resources :user_info do
match :user_info, :on => :collection
end
resources :user_schedule do
match :user_schedule, :on => :collection
end
end
so sessions now only shows the index, but I want it to respond to both get and post requests, and display my json results if it is a post request.
Eventually I'd like all other routes to follow the same
Thanks
Use
resource :sessions
Singular. That creates singular resources, as explained in here
You still go to the different actions in the controller depending on the http method, so you can choose what to render in each case.

Namespaced resources

This is an excerpt from my config/routes.rb file:
resources :accounts do |account|
account.resource :profile, :except => [:new, :create, :destroy]
account.resources :posts,
:collection => { :fragment => :get },
:has_many => [:comments, :likes]
# even more code
end
I would like that each nested resource to be loaded from from the account namespace such as Account::PostsController instead of PostsController.
Using resources :accounts, :namespace => 'account' tries to load AccountPostsController.
Trying to nest the structure doesn't really work all that well:
map.namespace :account do |account|
..
end
The previous code will load the files from the locations I want, however it does add the namespace to the url and the generated paths so I'll have methods such as account_account_posts_url and similar paths.
Another alternative is to use something like:
account.resource :profile, :controller => 'account/profile'
I really don't like this as it involves both code duplication and forces me to remove some of the rails magic helpers.
Any thoughts and suggestions?
Changing my routes.rb and running rake routes I came up with the following:
map.resources :accounts do |accounts|
accounts.namespace :account do |account|
account.resource :profile, :except => [:new, :create, :destroy]
end
end
This gets you what you want. The correct url and pointing to account/... controller.
See Rails Routing for more detailed info and options on what can be done with Rails Routes.
So what's specifically wrong with namespacing? I think this is what you're trying to do:
map.namespace :account do |account|
account.resource :profile
end
This will try to load the controller at app/controllers/account/profiles_controller.rb and will generate routes such as account_profile_path.
Updated based on comment:
map.resources :accounts do |account|
account.resource :profile
end
Will give you /accounts/22/profile.

Resources