I am wondering how to access routes in nested resources in rails. I added categories and it as broken my application.
Routes:
resources :categories do
resources :posts do
resources :comments
end
end
It errors out in this:
<% #posts.each_with_index do |post, index| %>
<%= link_to post do %> # originally, this used to work but now it says 'undefined method "post_path"'
<li class="post-title"><%= truncate post.title, length: 50 %></li>
<li class="post-content"><%= truncate post.content, length: 400 %></li>
<li><span class="post-comments"><%= post.comments.count %> comments</span></li>
<% end %>
My root is set to posts#index and has a listing of posts. However, the route nesting (originally I didn't have categories) has broken the routes.
Running rake routes I get in part this:
category_posts GET /categories/:category_id/posts(.:format) posts#index
POST /categories/:category_id/posts(.:format) posts#create
new_category_post GET /categories/:category_id/posts/new(.:format) posts#new
edit_category_post GET /categories/:category_id/posts/:id/edit(.:format) posts#edit
category_post GET /categories/:category_id/posts/:id(.:format) posts#show
PATCH /categories/:category_id/posts/:id(.:format) posts#update
PUT /categories/:category_id/posts/:id(.:format) posts#update
DELETE /categories/:category_id/posts/:id(.:format) posts#destroy
How can I adjust routes to compensate for nesting? Or is there a better way to nest?
You'd need to define another block that nests posts under category resource:
# Existing
resources :posts do
resources :comments
end
# Additional block
resources :categories do
resources :posts do
resources :comments
end
end
With the additional block, your existing routes remain unchanged so existing routes don't break!
It is always better to restrict the routes to only what you need/use. For example if you only need /categories/:category_id/posts, i.e. just the index method on the posts_controller, then your route will be updated to:
resources :categories do
resources :posts, only: [ :index ]
end
This way you have more control on your routes and greater maintainability of the application.
vee's answer is correct if you want to use the nested routes and still preserve the original URLs. This is recommend this if your site is live and changing the URLs would affect links to your indexed pages.
Otherwise, you should point your links to the nested resource, like this:
<%= link_to post.title, [post.category, post] %>
See: Rails - link_to, routes and nested resources
Related
I keep getting the following error. I'm trying to develop my own blogging platform as a way for me to learn and get better.
Error:
Showing /home/ubuntu/workspace/app/views/posts/show.html.erb where
line #36 raised:
undefined method `post_comments_path' for
<#:0x007f88f0044248> Did you mean? posts_path
app/views/posts/show.html.erb
<h2>Add a comment:</h2>
<%= form_for([#post, #post.comments.build]) do |f| %>
<div class="field">
<%= f.label :author %><br />
<%= f.text_field :author %>
config/routes.rb
Rails.application.routes.draw do
get 'welcome/index'
resources :posts
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root :to => "posts#index"
end
You do not have a comments resource nested in a posts resource (or at all) so you cannot create URLs using a comment within a post.
You need to define your comments routes before you can generate URLs for them.
If you want to nest them within posts, you should modify your current resources :posts line:
resources :posts do
resources :comments
end
resources in your routes files generate helper methods that Rails uses to produce URLs for models, in this case, post_comments_path.
You probably need to update it to look like
routes.rb
resources :posts do
resources :comments
end
after doing so you should be able see the new routes using rake routes or rails routes in the console.
You have to edit following changes to routes.rb file and try again
resources :posts do
resources :comments
end
Your route file is not correct. Place below code in your routes.rb
Rails.application.routes.draw do
get 'welcome/index'
resources :posts do
resources :comments
end
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root :to => "posts#index"
end
In the following code segment
.comment
%p= comment.comment
%p= comment.user.email
= link_to 'Edit', edit_post_comment_path(comment.post, comment)
= link_to "Delete", [comment.post, comment], method: :delete, data: {confirm: 'Are you sure"'}
why do both Edit and Delete take in comment.post as a parameter? What does it mean?
It require comment.post because you have made nested routes, check your routes.rb file where you have define routes as below:
resources :posts do
resources :comments
end
and your routes is for EDIT and DELETE is
edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit
DELETE /posts/:post_id/comments/:id(.:format) comments#destroy
That's why you always need to pass comment.post as a parameter.
If you don't want comment.post as parameter you can change your routes as:
resources :posts
resources :comments
OR if you don,t want to pass comment.id in any particular action do your routes as
resources :posts do
resources :comments, :except => [:delete]
end
resources :comments, :only => [:delete]
NOTE: I am assuming that you don't want comment.post parameter for :delete action
Comment is a nested resource here which means comments belongs to a post.
Because rails routes are defined in a RESTFUL Way.
If you see in the RESTful way, all the CRUD operations in comment resource require post resource id, since comment is associated with post.
Not only the 'Edit' and 'Delete' operation requires parent resource id, All the CRUD operation requires it.
Have a look here at Nested resource section.
I'm trying shallow nested resources for the first time and having a little trouble with one my index routes.
routes.rb
resources :sites, shallow: true do
resources :visits
end
The error I get is in my visits#show page's back button:
<%= link_to 'Back', site_visits_path(#site) %>
No route matches {:action=>"index", :controller=>"visits", :site_id=>nil} missing required keys: [:site_id]
In the index action of my VisitsController I set#site as follows:
#site = Site.find(params[:site_id])
However it's saying my :site_id is nil and I'm not sure how to set this correctly.
You can set that like:
<%= link_to 'Back', site_visits_path(:site_id => #site.id) %>
The following code isn't working
<p>Tags: <%= #video.tags.map { |t| link_to t.name, tag_path(t)}.join(', ') %></p>
Rails complains about undefined method 'tag_path' for #<#<Class:0x007fd0f0260890>:0x007fd0ebce5f68>
I think tag_path is just not the right url_helper, can anybody explain which one to use here?
My rake routes
video_tags GET /videos/:video_id/tags(.:format) tags#index
POST /videos/:video_id/tags(.:format) tags#create
new_video_tag GET /videos/:video_id/tags/new(.:format) tags#new
edit_video_tag GET /videos/:video_id/tags/:id/edit(.:format) tags#edit
video_tag GET /videos/:video_id/tags/:id(.:format) tags#show
PATCH /videos/:video_id/tags/:id(.:format) tags#update
PUT /videos/:video_id/tags/:id(.:format) tags#update
DELETE /videos/:video_id/tags/:id(.:format) tags#destroy
videos GET /videos(.:format) videos#index
POST /videos(.:format) videos#create
new_video GET /videos/new(.:format) videos#new
edit_video GET /videos/:id/edit(.:format) videos#edit
video GET /videos/:id(.:format) videos#show
PATCH /videos/:id(.:format) videos#update
PUT /videos/:id(.:format) videos#update
DELETE /videos/:id(.:format) videos#destroy
Apart from that, I did not change my routes.rb, which looks like this:
Rails.application.routes.draw do
devise_for :users
get 'welcome/index'
root 'welcome#index'
resources :articles do
resources :comments
end
resources :videos do
resources :tags
end
end
Alright, I got it working this way:
Added resource to routes.rb:
resources :videos do
resources :tags
end
With the routes set up, I changed my RHTML to look like this:
<p>
Tags:
<%= raw #video.tags.map {
|t| link_to t.name, video_tag_path(:video_id => #video.id, :id => t.id)
}.join(', ') %>
</p>
Had to specify the video_id and tag id parameter explicitly.
For tags, you have to generate a controller afterwards.
I get the error
undefined method `favorite_relationships_path'
when I display this form:
<%= form_for(current_user.favorite_relationships.build(lesson_id: #lesson.id),
remote: true) do |f| %>
<div><%= f.hidden_field :lesson_id %></div>
<%= f.submit "Favorite", class: "btn btn-large btn-primary" %>
<% end %>
I'm not sure why. I have a controller called favorite_relationships_controller.rb and a model file, favorite_relationship.rb, with the code
class FavoriteRelationship < ActiveRecord::Base
attr_accessible :lesson_id
belongs_to :user
belongs_to :lesson
end
My user model also has:
has_many :favorite_relationships
has_many :lessons, :through => :favorite_relationships
I'm really not sure why im getting that error. Help would be appreciated.
Rails has _path and _url helpers for routes, which are set up in config/routes.rb. You'll need to ensure that you've defined the routes for FavouriteRelationshipController; something like:
resources :favourite_relationships
You can check the routes defined for your application using the rake routes command.
You can find more information about routing at the Rails Routing from the Outside In guide.
Defining controllers, actions and views is not enough. You need to define routes in config/routes.rb to connect URLs to your controllers/actions. Defining RESTful resources with resources :favourite_relationships in your routing file is what causes Rails to generate the *_path and *_url helpers; until you do this there is no way for requests to reach your app, and no way for your app to generate routes based on your models.
Your routes file should look something like this:
MyApp::Application.routes.draw do
resources :favourite_relationships
end
This generates the typical "CRUD" routes required for a RESTful resource:
favourite_relationships GET /favourite_relationships(.:format) {:action=>"index", :controller=>"favourite_relationships"}
POST /favourite_relationships(.:format) {:action=>"create", :controller=>"favourite_relationships"}
new_favourite_relationship GET /favourite_relationships/new(.:format) {:action=>"new", :controller=>"favourite_relationships"}
edit_favourite_relationship GET /favourite_relationships/:id/edit(.:format) {:action=>"edit", :controller=>"favourite_relationships"}
favourite_relationship GET /favourite_relationships/:id(.:format) {:action=>"show", :controller=>"favourite_relationships"}
PUT /favourite_relationships/:id(.:format) {:action=>"update", :controller=>"favourite_relationships"}
DELETE /favourite_relationships/:id(.:format) {:action=>"destroy", :controller=>"favourite_relationships"}