Ask A Question

Notifications

You’re not receiving notifications from this thread.

Comments With Polymorphic Associations Discussion

Awesome Video. I really liked and refreshed my concepts about Polymorphic Associations. Thanks :)

Reply

Here is a Pro episode suggestion - take this and add nested comments and some AJAX to it :)

Reply

Id be sure to subscribe for that. Not found a decent example of nested before.

Reply
+1 on the suggestion. Daniel's link is helpful, but I'm getting caught up on the polymorphic_url generation to use the _comment partial as a shared file between mutliple models. 
Reply
Nick Chernyshev Nick Chernyshev

Polymorphism is the main anti-pattern in rails(

Reply
Jonathan Denney Jonathan Denney

How would you suggest getting all the comments a user's posts collectively have? For example @user.comments.all throws the error
ActiveRecord::HasManyThroughAssociationNotFoundError at / Could not find the association :commentable in model User

Reply

Is this something to consider in a social networking site? If I would have say comments polymorphically associated with various models, wouldn't it be a major hit on one table all the time?

Reply

Since they are reads, I think that so long as your database server can handle it, it doesn't matter how many connections read from the same table. Reads don't lock the table/row like writes do since a read cannot cause data loss. You shouldn't experience any loss of speed if many things are reading the same table.

Reply

The problem with polymorphic models and tables is there is no way to keep the database from becoming corrupt due to no FK constraints.

Reply

I would suggest that you please either put in minimal security on these screen casts or at least mention that the implementation is very insecure and to check out the rails security guidelines. I know the case can be made where security is out of scope for this discussion but a, at one point you reference how this method is "more secure" when talking about the hidden form field and b, you leave xss/injection etc all wide open so that body may be used to by malicious users to extend reach.

Reply

Can you please elaborate on this part `you leave xss/injection etc all wide open so that body may be used to by malicious users to extend reach`? I'd like to understand the security risk a little more.

Reply

How would this be handled if we only want the user to see their own comments, but not anyone else's?

Reply

You could do that by scoping the comments further by adding ".where(user: current_user)" to the query in the controller.

Reply

you can scope it like this (if comment.user_id == current_user.id) {...}

Reply

I found some of this information useful on how to test these polymorphic comment features at https://github.com/thoughtb...

Reply

Interesting way to do this. I created an app that does comments, but I did it by the whole post has_many :comments, comments belongs_to post, and resource nesting. Took me hours to figure out how to do display comments. What's the pros and cons of the that way versus this way?

One great thing about this episode is that the whole polymorphic thing finally clicks for me, because for the longest time I still didn't really understand it despite reading on it repeatedly. In all of my albiet smallish projects I never used it, now that I understand it finally, I have some idea when to use polymorphic association.

Thanks so much! I signed up for GoRails based on this episode and the omniauth twitter episode!

Reply

The main difference is that you probably have tied your comments to the Post model. With polymorphism, you could have comments on the Post model, the User model, or any other model you've got.

And thank you a bunch for subscribing!!

Reply
Michael Langat Michael Langat

How do you add a destroy method to this

Reply

I am trying to add a delete comment button to this. But it is sending me to the articles controller destroy action. Please can you add how to add a delete button to the comment? I'm stuck. Thanks very much!

Reply

Hey Melanie!

For deleting comments, it might be useful to add a "resources :comments" to your routes that isn't inside another resources block. Then you can create a regular CommentsController with a destroy action like normal. That way you can delete any comment as long as you know the ID of it and not worry about whether it's a film or actor comment because that doesn't really matter when you're deleting a comment.

To add the delete link to each comment in the view, you can say: <%= link_to "Delete", comment, method: :delete %> and that will make a DELETE request to the /comments/1 url, which will trigger the destroy action.

That should do it! If you want to go over and above, you can also make it as a "remote: true" link so that you can return some JS to remove the item from the page to make it AJAXy and nicer to use.

Reply

Hi Chris, I'm still struggling along in trying to get this set up. My current issue is with my comments policy update function. Your tutorial shows how to define update as set out below (which I have tried in both my article policy and my comment policy:

Article Policy:

def update?

#user && user.article.exists?(article.id) -- I have also tried this on this suggestion of someone on stack overflow).

user.present? && user == article.user

end

Comment Policy:

def update?

user.present? && user == comment.user

end

I keep getting a controller action error which says: undefined method `user' for #<class:0x007f9e24fa7cf0>

It highlights the update definition. Has something changed in pundit that requires a different form of expression for this update function? Can you see what might have gone wrong? Thanks very much

Reply

That looks correct. It sounds like the comment object is potentially the class and not the instance of the comment.

Does your controller have " authorize @comment" in it? And is your @comment variable set to an individual record?

Reply

Chris, Fantastic episode here. Thank you very much.

I got it to work - mostly - in my set-up but I encounter a little redirect problem.

In my case my association is a "noteable" - referring to Notes.

My resources and namespace profile is:

namespace :navigate do
--resources :boks, :only => [:show] do
----resources :tools, :only => [:show, :index]
------resources :notes, module: :processus
----resources :processus do
------resources :notes, module: :processus

The problem I have is with the NotesController for the create/update of the notes. When I try to do a redirect I am finding that I am missing the information about the "bok" entity.

In my controller I have this:

def create
@note = @noteable.notes.new note_params
@note.user = current_user
@note.save
redirect_to [:navigate, @bok, @noteable], notice: "Your note was succesfully created."
end

Really the redirect_to should send me back to the right place, however the @bok entity is not present at all...mostly because at this stage I don't actually need it.

What would be the recommended approach to dealing with this nested situation?

Thanks!

Reply

Chris, awesome episode! I'm trying to implement something similar, but before I dive deep into it I'd like to make sure I go down the right path. So I will do the exactly same, except comments are gonna have replies. My guess is if I have the right polymorphic setup for the comments, then I can just setup a simple `has_many + belongs_to` relationship between the comment model and the reply model, so from the reply's perspective it doesn't matter if the comment is polymorphic or not since every comment will have its unique id. Is this right?

Reply

Yeah, you can have a comment as a commentable, allowing you to have Comments with comments if you like. That's how you would normally setup threaded comments. You might want to put some limits on the nesting so you don't get threads that are too far nested in. Facebook limits it to one layer for example.

Reply

In the comments controller when I try to do

@comment.user = current_user

Throws an error (no user method for user class) unless I do

@comment.user_id = current_user.id

Problem is, when I try to show the username associated to a comment (I need to do queries instead of accessing the object). Any idea on how to fix this?

Reply

Oops, I never did the belongs_to :user association :$

Reply

Question Chris - I'm trying to show the last 5 comments in the show view. I can't get the query string right. Thanks for your help!

Reply

You could change it to the following:

<% commentable.comments.order(created_at: :desc).limit(5).each do |comment| %>

Reply
Daniela Correa Orozco Daniela Correa Orozco

Hi Chris!
Awesome video!
I'm having problems with current_user being nil in the base CommentsController where we set
@comment.user_id = current_user

current_user seems to return the right user_id in my other controllers. I have looked around but I haven't been able to pin point the problem (cookie problems maybe?)
Thank you in advance and for the really helpful videos!

Reply

Is the user not currently signed in by chance when you submit a comment?

Reply

I love this nifty bit of code. I'm wondering how would you go about using will_paginate to paginate the comments?

Reply

I forgot about this. I watched it a year ago and used in in my last attempt at implementing these associations. And then I forgot about it. Im back on track again - thanks for this (again). I'm struggling to figure out how to filter the index of the comments resource by an attribute (say :status == 'published'). I can't do that in the regular way because the route is looking for a prefix (of film/actor)

Reply

Hey Melanie! :)

If you wanted a route to get all published comments (not ones scoped to a commentable type) you could add a resources :comments that was not nested in your routes and use that.

  resources :comments

resources :actors do
resources :comments, module: :actors
end
resources :films do
resource :comments, module: :films
end

And then you could make a comments_controller.rb that worked for all comments for any object. Is that what you're looking for?

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 83,168+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.