Reputation: 200
I have a implemented the post and user model where post model belongs to user model. I defined the ability model for authorisation so that only user who created the post can able to delete or update the post. i have the post controller like this:
def edit
@post = @topic.posts.find(params[:id])
authorize! :update, @post
end
Ability model:
class Ability
include CanCan::Ability
def initialize(user)
can :update, Post do |p|
p.user == user
end
can :destroy, Post do |p|
p.user == user
end
can :destroy, Comment do |c|
c.user == user
end
can :create, Post
can :create, Comment
end
end
What will be the rspec for the above model? Error:
expected #<User id: nil, email: "", created_at: nil, updated_at: nil> to respond to `able_to?`
0) User Check for Abilities What User can do should be able to :create and #<Post id: nil, title: nil, body: nil, created_at: nil, updated_at: nil, topic_id: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, user_id: nil>
Failure/Error: it { should be_able_to(:create, Post.new) }
expected #<User id: nil, email: "", created_at: nil, updated_at: nil> to respond to `able_to?`
# ./spec/models/ability_spec.rb:8:in `block (4 levels) in <top (required)>'
expected #<User id: nil, email: "", created_at: nil, updated_at: nil> to respond to `able_to?`
0) User Check for Abilities What User can do should be able to :update and #<Post id: nil, title: nil, body: nil, created_at: nil, updated_at: nil, topic_id: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, user_id: nil>
Failure/Error: it { should be_able_to(:update, Post.new) }
expected #<User id: nil, email: "", created_at: nil, updated_at: nil> to respond to `able_to?`
# ./spec/models/ability_spec.rb:9:in `block (4 levels) in <top (required)>'
Upvotes: 2
Views: 2695
Reputation: 2357
Based on the limited information you have provided, I'm going to share a sample spec
which tests abilities.
describe "User" do
describe "Check for Abilities" do
let(:user) { FactoryGirl.create(:user) }
describe "What User can do" do
it { should be_able_to(:create, Post.new) }
it { should be_able_to(:update, Post.new) }
end
end
end
What I have provided at the top was a Sample, using which you have to build upon it. My updated answer
require "cancan/matchers"
describe "User" do
describe "abilities" do
user = User.create!
ability = Ability.new(user)
expect(ability).to be_able_to(:create, Post.new)
expect(ability).to_not be_able_to(:destroy, Post.new)
end
end
Upvotes: 1
Reputation: 5528
Let's start by refactoring your ability file a little bit. Is always a good idea to use a hash of conditions, rather than blocks. Therefore your ability file should look like:
class Ability
include CanCan::Ability
def initialize(user)
can [:update, :destroy], Post, user_id: user.id
can :destroy, Comment, user_id: user.id
can :create, Post
can :create, Comment
end
end
this is a shorter version of the one you have, and it does more.
Here is an example on how I would write the test, based on the cancancan documentation:
require 'cancan/matchers'
RSpec.describe Ability do
subject(:ability) { described_class.new(user) }
context 'when there is no user' do
let(:user){ nil }
it { is_expected.to_not be_able_to(:create, Post)
....
end
context 'when the user is present' do
let(:user){ User.new }
it { is_expected.to be_able_to(:create, Post) }
...
end
end end
I let the rest of the tests to you.
Upvotes: 1