n.milsht n.milsht - 1 year ago 68
Ruby Question

Rails, link_to method: :delete breaks after child element (comment) instantiated

I'm on a video show page (which belongs to a post). The link_to delete works just fine until I create a comment on that video show page. I have a series of capybara tests that validate that the link_to delete video is working until I create a comment on that video at which point rails returns...

Failure/Error: <%= link_to "Delete Video", post_video_path(@video), method: :delete %>

No route matches

Not sure what's going on here or how to fix it. I stuck a pry in and the first two tests that hit it I checked the path...


which returned a valid path, e.g.

[1] pry(#<#<Class:0x007f891941dee0>>)> post_video_path(@video)
=> "/posts/1/videos/1"

When the spec instantiates a comment, the path reads as follows...

[1] pry(#<#<Class:0x007f891c2fd0a8>>)> post_video_path(@video)
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"videos", :post_id=>#<Video id: 1, user_id: 1, post_id: 1, title: "18title", url: "https://www.youtube.com/watch?v=tYm_182oCVdSM", embed_id: "https://www.youtube.com/watch?v=tYm_182oCVdSM.spli...", tags: nil, created_at: "2016-10-16 22:12:30", updated_at: "2016-10-16 22:12:30">, :video_id=>"1"} missing required keys: [:id]


def show
@video = Video.find(params[:id])
@user = @video.user
@post = @video.post
@comment = Comment.new
@comments = @video.comments


<%= @video.title %>
<%= content_tag(:iframe, nil, src: "//www.youtube.com/embed/#{@video.embed_id}") %>
<% binding.pry %>
<%= link_to "Delete Video", post_video_path(@video), method: :delete %>
<%= link_to('Back', user_post_path(@user, @post)) %>


<%= form_for [@video, @comment] do |f| %>
<%= f.label(:body, "Comment") %>
<%= f.text_area(:body) %>
<%= f.submit("Submit Comment") %>
<% end %>

<% @comments.each do |comment| %>
<%= comment.body %>
<%= comment.user %>
<% end %>


Rails.application.routes.draw do
devise_for :users

resources :users, only: [] do
collection do
get '/show_profile', to: 'users#show_profile', as: 'my_profile'
get '/show_log', to: 'users#show_log', as: 'my_log'
resources :posts, only: [:new, :create, :show]

resources :posts do
resources :videos

resources :videos do
resources :comments

root 'home#index'


class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :video

validates :body, presence: true

Please let me know if you would like to see any particular file or code.


Answer Source

Generally speaking - when you use a path name that has the names of two models, you need to pass it two models.

eg in your case, your path is post_video_path(@video) - what this expects is for you to pass it a post and a video eg post_video_path(@post, @video)

if you don't... then it will get confused, possibly in a way you didn't expect. In this case, I'm guessing that it's taking the id of the video, and assuming it's the post_id.

You can tell it's confused by look at this error message:

ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"videos", :post_id=>#<Video id: 1, user_id: 1, post_id: 1, title: "18title",

Specifically the part that has: :post_id=>#<Video id: 1, ... -> it's putting the video in the post_id. Quite possibly it only "worked" before because you had a single post, and a single video... and thus when it used the id of 1 from the video as the post-id... the video was already assigned to the post (that also had an id of 1)... but once you delete that one, it no longer exists. This is a total guess - it doesn't matter if this is how Rails got confused, as long as you recognise where the error is coming in.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download