This plugin allows any mongoid class to become commentable object that can be commented upon.
You need to include the commentable module to the class you want to comment on (e.g. Book) and setup it as commentable using the "acts_as_commentable" method:
class Book
include Mongoid::Document
include Suj::Commentable
acts_as_commentable :order => :desc, :max_depth => 10, :paginates_per => 10, :dependent => :destroy
end
After this your Book class will be ready to accept comments.
- order: The order parameter can be to show the comments ordered in ascending or descending order.
- max_depth: Limit the number of replies to each comment. If max_depth is set to -1 then is unlimited.
- paginates_per: Each request for comments will return at least :paginates_per items.
- dependent: Can be any of:
- :delete -> Delete the associated comments. Does not invoke callbacks on comments.
- :destroy -> Destroy the associated comments. Invokes callbacks on comments.
- :nullify -> Leave the comments but with null commentable.
- :restrict -> Raise an error is it has comments.
The following methods are generated by the acts_as_commentable:
-
comments: Returns the list of comments. This is an association object and can be used to add, delete and edit comments.
book.comments.create(:text => "aaa", :author => author)
In the Suj::Commentable model (e.g. Book) you can define some callbacks that will be triggered on certain comment events:
- before_create_comment: Called before a comment is created. This can be used to inspect the comment contents and cancel the creation if it is not appropiate for your site. To cancel the creation simply return false on this callback.
- after_create_comment: This is called after a comment is created with the comment as argument. You can use this callback to send notifications via email or SMS to authors when a comment is created.
- before_destroy_comment: This is called before a comment is destroyed. You can use this callback to abort the deletion of the comment if you like. To do this return false from this callback.
- after_like_comment: This callback is triggered when a user likes a comment (rates positive). The callback receives the rated comment and the user objects as parameters.
- after_unlike_comment: Same as above but triggered when a user rates negatively a comment.
class Book
include Mongoid::Document
include Suj::Commentable
acts_as_commentable :order => :desc, :max_depth => 10, :paginates_per => 10, :dependent => :destroy
private
def before_create_comment(comment)
return false if has_bad_language(comment.text)
end
def after_create_comment(comment)
send_notify_email(address, comment.text)
end
def after_like_comment(comment, user)
logger.info("User #{user.name} liked comment #{comment.text}")
end
def after_unlike_comment(comment, user)
logger.info("User #{user.name} did not like comment #{comment.text}")
end
end
If you want your comments to have authors and to enable the like/unlike, hid/unhid functions you must enable one of your models to act as authors.
For this include the Suj::Commentable module and use the acts_as_commentable_author to configure the model:
class User
include Mongoid::Document
include Suj::Commentable
acts_as_commentable_author :name_field => "name", :avatar_field => "avatar"
end
- name_field: If set the name_field will be invoked on the model to get the authors name. By default it calls the "name" method.
- avatar_field: Should return an URL pointing to an image used to display as avatar in each comment. If not set it tries to obtain the avatar from Gravatar using the authors email address.
The author model does not acquire any methods to manipulate comments.
After configuring the models you should be able to add comments to the Book class via the comments association:
@book = Book.first
@book.comments
@book.comments.create(:text => "New Comment", :author => User.first)
Comments are threaded so they can have parents and childrens:
@book.comments.create(:text => "Threaded Comment", :author => User.first, :parent => Comment.first)
@comment.children
In your ApplicationController create a "commentable_user" that returns an author instance of the currently logged in user. This method will be used to restrict permissions on actions performed on comments. For example only the author of a comment will be able to delete or hide it.
If you use devise for authentication then you can simply return the current_user:
class ApplicationController < ActionController::Base
def commentable_user
current_user
end
end
In your routes.rb config file add this command:
commentable_for :books
This will create routes needed to create/destroy/like/dislike comments. Use rake routes to check the generated routes.
This plugin includes some partials and a helper used to render the comments. Also a default stylesheet is provided. To display the comments in you own views simply use the comments_for helper method:
<%= comments_for(@book) %>
This will render a list with the current comments and a form to add new comments.
If you have different User types with different privileges, like Admin, Moderator etc. you may want to give different comment privileges to each one.
To do this in our gem you can simply overrid the can_hid_comment? and can_delete_comment? in your User model.
class User
include Mongoid::Document
include Suj::Commentable
acts_as_commentable_author :name_field => "name", :avatar_field => "avatar"
def can_hid_comment?(comment)
return true if self.is_moderator?
super
end
def can_delete_comment?(comment)
return true if self.is_admin?
#super
end
end
The example above would allow a user to hid/unhide comments if he/she is a moderator or if he/she is the author of the comment (by calling super) and only allow delete if the user is admin. If you want to allow users to delete their own comments then uncomment the super call.
You can run the install generator to copy all the views, javascript, stylesheets and even the controller to your code tree. From there you can modify all the files to your liking.
rails generate suj:commentable:install