Timmy Von Heiss Timmy Von Heiss - 4 months ago 21
Ruby Question

Edited... ActionView::Template::Error (No route matches... missing required keys: [:comment_id])

I am getting the following error from Heroku log when I visit the

photos/show.html.erb
view:


ActionView::Template::Error (No route matches {:action=>"index", :comment_id=>nil, :controller=>"cflags", :photo_id=>"100"} missing required keys: [:comment_id])


I have very basic
Photo
and
Comment
models that work correctly and then I have built a
Cflag
model that is used to flag comments. I use
@photo.comments
to list the comments in the
photos/show.html.erb
view.

Show:

# photos/show.html.erb

<% @photo.comments.each do |comment| %>
<%= form_for(comment, url: photo_comment_cflags_path(@photo, comment)) do |f| %>
<%= f.hidden_field :user_id, value: current_user.id %>
<%= f.submit "Report Inappropiate" %>
<% end %>
<% end %>


Cflags Controller:

class CflagsController < ApplicationController
before_action :logged_in_user

def new
end

def create
@comment = Comment.find(params[:comment_id])
@cflag = @comment.cflags.build(cflag_params)
if @cflag.save
if @comment.cflags_count > 1
@comment.update_attribute(:approved, false)
flash[:success] = "Flag created! Comment ##{@comment.id} has been removed for review. Thank you for your feedback"
redirect_to :back
else
flash[:success] = "Flag created! Thank you for your feedback"
redirect_to :back
end
else
redirect_to :back, notice: @cflag.errors.full_messages
end
end

private
def cflag_params
params.require(:cflag).permit(:user_id, :comment_id).merge(user_id: current_user.id)
end
end


Routes:

resources :photos do
resources :comments, only: [:create, :edit, :destroy] do
resources :cflags, only: :create
end
end


Rails routes:

photo_comment_cflags GET /photos/:photo_id/comments/:comment_id/cflags(.:format) cflags#index
POST /photos/:photo_id/comments/:comment_id/cflags(.:format) cflags#create
new_photo_comment_cflag GET /photos/:photo_id/comments/:comment_id/cflags/new(.:format) cflags#new
edit_photo_comment_cflag GET /photos/:photo_id/comments/:comment_id/cflags/:id/edit(.:format) cflags#edit
photo_comment_cflag GET /photos/:photo_id/comments/:comment_id/cflags/:id(.:format) cflags#show
PATCH /photos/:photo_id/comments/:comment_id/cflags/:id(.:format) cflags#update
PUT /photos/:photo_id/comments/:comment_id/cflags/:id(.:format) cflags#update
DELETE /photos/:photo_id/comments/:comment_id/cflags/:id(.:format) cflags#destroy


Photos Controller:

def show
@photo = Photo.approved.find(params[:id])
end


Comments Controller:

def create
@photo = Photo.find(params[:photo_id])
@comment = @photo.comments.build(comment_params)
@comment.save
respond_to do |format|
format.html { redirect_to :back }
format.js
end
end


Cflag Model:

class Cflag < ActiveRecord::Base
belongs_to :comment, counter_cache: true
belongs_to :user, counter_cache: true
validates :user_id, presence: true
validates :comment_id, presence: true
validates :user_id, uniqueness: {
scope: [:comment_id],
message: 'You can only flag a comment once. Thank you for your feedback.'
}
default_scope -> { order(created_at: :desc) }
end


Schema:

create_table "cflags", force: :cascade do |t|
t.integer "comment_id"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

add_index "cflags", ["comment_id"], name: "index_cflags_on_comment_id"
add_index "cflags", ["user_id"], name: "index_cflags_on_user_id"


In Heroku Console

p = Photo.find(100)
p.comments = => #<ActiveRecord::Associations::CollectionProxy [#<Comment id: 309, content: "hi", photo_id: 100, user_id: 1, created_at: "2016-07-24 04:43:17", updated_at: "2016-07-24 04:43:17", approved: true, cflags_count: nil>

Answer

Change the form action to this, Updated:

<% if @photo.comments.any? %>
   <% @photo.comments.each do |comment| %>     
     # you do not have to use comment in form_for, because this form is for creating cflag
     <%= form_for(:cflag, url: photo_comment_cflags_path(@photo, comment), method: "post") do |f| %> 
          <%= f.hidden_field :user_id, value: current_user.id %> 
          <%= f.submit "Report Inappropiate" %> 
     <% end %> 
   <% end %> 
<% end %>