I am trying to build a blog where there will be 2 users admin and normal user.Admin can view every post and comment .Whereas normal user can view his only post and comment .I have applied my logic but it is not working .In my code every user can view each other post and comment which I don't want .I have uploaded my code at github
link
[ability.rb]
class Ability
include CanCan::Ability
def initialize(user)
unless user
else
case user.roles
when 'admin'
can :manage, Post
can :manage, Comment
when 'user'
can :manage, Post, user_id: user.id
can :manage, Comment, user_id: user.id
end
end
class PostsController < ApplicationController
before_action :authenticate_user!
authorize_resource
def index
@posts = Post.all.order('created_at DESC')
end
def new
@post = Post.new
end
def show
@post = Post.find(params[:id])
end
def create
@post = Post.new(post_params)
@post.user = current_user
if @post.save
redirect_to @post
else
render 'new'
end
end
def edit
@post = Post.find(params[:id])
end
def update
@post = Post.find(params[:id])
if @post.update(params[:post].permit(:title, :body))
redirect_to @post
else
render 'edit'
end
end
def destroy
@post = Post.find(params[:id])
@post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
[comment_controller]
class CommentsController < ApplicationController
authorize_resource
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.build(params[:comment].permit(:name, :body))
@comment.user = current_user
@comment.save
redirect_to post_path(@post)
end
def destroy
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
@comment.destroy
redirect_to post_path(@post)
end
end
[user.rb]
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :posts
has_many :comments
end
[post.rb]
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :body, presence: true
belongs_to :user
end
[comment.rb]
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
end
Firstly...
CanCan
is no longer maintained; CanCanCan
should be added to your Gemfile
:
#Gemfile
gem "cancancan"
--
You'll be able to use the following:
#app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
case user.roles
when "admin" #-> use double quotes for evaluating strings
can :manage, [Post, Comment]
when "user"
can :manage, [Post, Comment], user_id: user.id
end
end
end
--
You also need to make sure you're calling authorize!
.
Although authorize_resource
is good, in your case, you need to make sure you're sticking to convention...
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
authorize_resource :post
authorize_resource :comment
def create
@post = Post.find params[:post_id]
@comment = @post.comments.new comment_params
@comment.user = current_user
@comment.save
redirect_to @post
end
def destroy
@post = Post.find(params[:post_id])
@comment = @post.comments.find params[:id]
@comment.destroy
redirect_to @post
end
private
def comment_params
params.require(:comment).permit(:name, :body)
end
end