I'm getting an error raised of "undefined method 'comments_path' for..." At this code in app/views/comments/_form.html.erb (line 1).
I recently tried to implement nestable comments via polymorphic associations on a website I'm building; however, I'm running into a problem that's not allowing me to move forward.
I'm trying to implement nested comments on a 'commentable' model (ie the blog in this case) and then when show is clicked, all the nested comments are shown and the individual can comment on the blog or reply to a comment (and hence result in nested comments) without leaving the page.
I've included a few other files to show the setup, but if I've missed one that's necessary, please let me know and I'll promptly add it. Any help is much appreciated. I've been stumped for several hours and I'm sure its something simple.
<%= form_for [@commentable, @comment] do |f| %>
<%= f.hidden_field :parent_id %></br>
<%= f.label :content, "New Comment" %></br>
<%= f.text_area :body, :rows => 4 %></br>
<%= f.submit "Submit Comment" %>
<% end %>
app/views/blogs/show.html.erb
<div class="content">
<div class="large-9 columns" role="content">
<h2>Comments</h2>
<div id="comments">
<%= nested_comments @comments %>
<%= render "comments/form" %>
</div>
</div>
</div>
app/controllers/comments_controller
class CommentsController < ApplicationController
def new
@parent_id = params.delete(:parent_id)
@commentable = find_commentable
@comment = Comment.new( :parent_id => @parent_id,
:commentable_id => @commentable.id,
:commentable_type => @commentable.class.to_s)
end
def create
@commentable = find_commentable
@comment = @commentable.comments.build(params[:comment])
if @comment.save
flash[:notice] = "Successfully created comment."
redirect_to @commentable
else
flash[:error] = "Error adding comment."
end
end
private
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
def comment_params
params.require(:comment).permit(:parent_id, :body, :commentable_type, :commentable_id)
end
end
app/controller/blogs_controller.rb
class BlogsController < ApplicationController
before_filter :authenticate, :except => [ :index, :show ]
before_action :set_blog, only: [:show, :edit, :update, :destroy]
include MyModules::Commentable
# GET /blogs
# GET /blogs.json
def index
@blogs = Blog.all.order('created_at DESC')
respond_to do |format|
format.html
format.json
format.atom
end
end
# GET /blogs/1
# GET /blogs/1.json
def show
@blog = Blog.find(params[:id])
end
# GET /blogs/new
def new
@blog = Blog.new
end
# GET /blogs/1/edit
def edit
@blog = Blog.find(params[:id])
end
# POST /blogs
# POST /blogs.json
def create
@blog = Blog.new(blog_params)
respond_to do |format|
if @blog.save
flash[:success] = "Blog was sucessfuly created"
format.html { redirect_to @blog }
format.json { render :show, status: :created, location: @blog }
else
format.html { render :new }
format.json { render json: @blog.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /blogs/1
# PATCH/PUT /blogs/1.json
def update
respond_to do |format|
if @blog.update(blog_params)
flash[:success] = "Blog was successfully updated."
format.html { redirect_to @blog }
format.json { render :show, status: :ok, location: @blog }
else
format.html { render :edit }
format.json { render json: @blog.errors, status: :unprocessable_entity }
end
end
end
# DELETE /blogs/1
# DELETE /blogs/1.json
def destroy
@blog.destroy
respond_to do |format|
flash[:success] = "Blog was successfully deleted."
format.html { redirect_to blogs_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_blog
@blog = Blog.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def blog_params
params.require(:blog).permit(:title, :body, :image, :image_cache, :remote_image_url)
end
private
def authenticate
authenticate_or_request_with_http_basic do |name, password|
name == "admin" && password == "runfast"
end
end
end
my routes file looks like this...
Rails.application.routes.draw do
resources :blogs do
resources :comments
end
resources :applications
resources :reviews
resources :properties
root to: 'blogs#index'
end
the blog and comment models...
class Blog < ActiveRecord::Base
validates_presence_of :body, :title
has_many :comments, :as => :commentable, :dependent => :destroy
mount_uploader :image, ImageUploader
end
class Comment < ActiveRecord::Base
has_ancestry
belongs_to :commentable, :polymorphic => true
validates_presence_of :body
end
and finally the commentable module in lib/my_modules/commentable.rb
require 'active_support/concern'
module MyModules::Commentable
extend ActiveSupport::Concern
included do
before_filter :comments, :only => [:show]
end
def comments
@Commentable = find_commentable
@comments = @Commentable.comments.arrange(:order => :created_at)
@comment = Comment.new
end
private
def find_commentable
return params[:controller].singularize.classify.constantize.find(params[:id])
end
end
@blog
#<Blog id: 8, title: "New Blog Post about Databases.... Again", body: "RDM, the database management system, was designed ...", created_at: "2015-03-01 22:28:07", updated_at: "2015-03-03 00:11:07", image: "IMG_2210.JPG">
@commentable
#<Blog id: 8, title: "New Blog Post about Databases.... Again", body: "RDM, the database management system, was designed ...", created_at: "2015-03-01 22:28:07", updated_at: "2015-03-03 00:11:07", image: "IMG_2210.JPG">
app/helpers/comments_helper.rb
module CommentsHelper
def nested_comments(comments)
comments.map do |comment, sub_comments|
content_tag(:div, render(comment), :class => "media")
end.join.html_safe
end
end
@_params instance variable in better errors
{"utf8"=>"✓", "authenticity_token"=>"OH2tDdI5Kp54hf5J78wXHe//Zsu+0jyeXuG27v1REqjdAec7yBdlrVPLTZKEbLZxgR2L7rGwUwz5BlGTnPcLWg==", "comment"=>{"parent_id"=>"", "body"=>"Hello!\r\n"}, "commit"=>"Submit Comment", "controller"=>"comments", "action"=>"create", "blog_id"=>"8"}
You're getting the error in this view: app/views/blogs/show.html.erb
.
The data for this view has been prepared in blogs#show
. So in your view, you should have <%= form_for [@blog, @comment] do |f| %>
, since you set @blog
, not @commentable
.
You should also do @comment = Comment.new
. Not sure where you set this one...
Do <% raise @commentable.inspect %>
in your view (app/views/blogs/show.html.erb). If it's nil, then that's why you're getting the error.