How to Submit Polymorphic Comments on Feed? [Error]
The problem is, for this to work, it looks like it is setup for comments to be a nested resource of whatever you're commenting on in your routes file.
So, if you want comments on activities, you'd have:
resources :activites do
resources :comments
end
This way, when the #load_commentable method picks apart the request path, it'll get the commentable and id from the first two segments.
It looks, instead, like you're trying to use comments as a top level resource.
UPDATE:
When you call your partial, simply pass along the url helper that the form should use. Like this:
<%= render "comments/form", new_comment: Comment.new(commentable_id: activity.id, commentable_type: activity.class.model_name), create_url: :activity_comments_path %>
Then, over in the partial, simply invoke that helper and pass the result as the url option - like this:
<%= form_for new_comment, url: send(create_url, new_comment.commentable)
Polymorphic comments route error
@Katie, @commentable
should be loaded for every action on which you are rendering the comment form. I think you are forgoing comments#new
in favor of using books#show
or posts#show
to render the form (which is fine), but that variable needs to be loaded every time you want to render the form.
However, since defining a @commentable
variable in books#show
isn't very expressive (you probably already have a @book
defined), here's what I would suggest:
Create a new partial (if you don't have one already) for the comment form:
<% form_for [commentable, Comment.new] do |f| %>
<p>
<%= f.text_area :body %>
</p>
<p><%= f.submit "Submit" %></p>
<% end %>
Notice commentable
is not an instance variable here. When you render the partial, you will define it as a local variable. Somewhere in books/show.html.erb
:
<%= render partial: "comments/form", locals: { commentable: @book } %>
Obviously, in other views, replace @book
with whatever variable should be commentable
.
Now you'll have another issue, which is that the form data won't carry the commentable_type
and commentable_id
attributes. There are a number of ways you can get them into your CommentsController
; here's a simple one using hidden fields:
<% form_for [commentable, Comment.new] do |f| %>
<%= hidden_field_tag :commentable_type, commentable.class.to_s %>
<%= hidden_field_tag :commentable_id, commentable.id %>
<p>
<%= f.text_area :body %>
</p>
<p><%= f.submit "Submit" %></p>
<% end %>
You'll need to change the find_commentable
action to something a bit more simple:
def find_commentable
params[:commentable_type].constantize.find(params[:commentable_id])
end
Polymorphic Association with Comments - Ruby on Rails
Your issue is that find_commentable is returning the params hash itself because the return statement never fired.
I deduced this by the error message because params.class == ActiveSupport::HashWithIndiffrentAccess
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
end
I would add something like
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
raise ActiveRecord:NoRecord.new("Couldn\'t find it captain!")
end
The above exception type I think is correct, if not see what Comment.find_by_id(-1) or something like that raises. Should be something along those lines.
Edit
The reason I suggest raising the exception is because ApplicationController should be catching those and handling them gracefully when people start poling around and go to example.com/posts/9001
Rails polymorphic comments ajax - 500 (Internal Server Error)
updated create.js with instance variable for comment and it works now.
<% unless @comment.errors.any? %>
$("ul.comments").append('<%= j render partial: "comments/comment", locals:{comment: @comment} %>')
$("#new_comment")[0].reset();
<% end %>
rails-3, new comment form from a polymorphic association, accepts form submission but doesn't display submited data
If you look at app/views/comments/_form.html.erb you'll notice that it
builds a form using
[@post, Comment.new]
This means that it works correctly when you create a comment directly from a PostsController
view as @post is set correctly. This means that the form
builder sets the form's action to /posts/5/comments (where the 5 is
taken from @post.id), thus setting the post_id param which the CommentsController
looks for in CommentsController#get_parent.
However, when you click on 'Add a comment' or 'Add a reply' you are in
the CommentsController, which sets a variable called @parent. That
means that the form builder sets the form's action to /comments
(since @post is nil), which means when you submit the form both the post_id and
comment_id params are nil.
What this means that it reaches this line in CommentsController#get_parent:
redirect_to root_path unless defined?(@parent)
which means that your form contents are silently discarded.
The easiest way to get the forms to work correctly is to make the
following changes:
#app/controllers/posts_controller.rb:
def show
- @post = Post.find(params[:id])
+ @parent = @post = Post.find(params[:id])
end
#app/views/comments/_form.html.erb b/app/views/comments/_form.html.erb
-
+
As you'll see, it means that the form looks for the @parent object
(instead of @post), which then gets set by PostsController & CommentsController.
As an aside, you could consider making the following changes to tighten up your code:
- redirect_to root_path unless defined?(@parent)
+ redirect_to root_path unless @parent
If @parent is not defined it will return nil, which is considered false.
- return @post if defined?(@post)
- @post = commentable.is_a?(Post) ? commentable : commentable.post
+ @post ||= commentable.is_a?(Post) ? commentable : commentable.post
Also, you call Comment.new in your views. Generally, initializing object should be done in a controller, and views should be limited to presentation logic.
Rails polymorphic comments associate
Relationships:
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
belongs_to :user
end
class Photo < ActiveRecord::Base
has_many :comments, as: :commentable, dependent: :destroy
end
class User < ActiveRecord::Base
has_many :comments, dependent: :destroy
has_many :messages, as: :commentable, class_name: 'Comment'
end
Schema:
# Comments
...
t.integer :user_id
t.integer :commentable_id
t.string :commentable_type
...
Then you can invoke:
@user.comments # Get all comments created by particular user
@user.messages # Get all comments where particular user is a subject
Rails - embedded polymorphic comment list + add comment form - example?
I figured it out, implemented it, tested it, then finally wrote a tutorial explaining how to do it for others:
https://github.com/hcatlin/make_resourceful/wiki/embedded-nested-polymorphic-comments
Related Topics
Export Content of a SQLite3 Table in CSV
Checking If a Variable Is Not Nil and Not Zero in Ruby
Rails 4: How to Reset Test Database
Finding What Is Common to Two Arrays
"Uninitialized Constant" Error When Including a Module
How to Find the Source File for a Rake Task
Seeding File Uploads with Carrierwave, Rails 3
Mountain Lion - Libxml & Nokogiri
Passing Error Messages Through Flash
How to Fetch Linkedin User Data
Rails: Convert Utc Datetime to Another Time Zone
How to Create a Copy of Some Columns of a CSV File in Ruby with Different Data in One Column
Find or Create Record Through Factory_Girl Association
How to Drop to the Irb Prompt from a Running Script
Is Rails.Cache Purged Between Tests