I would like to see if users have authorization to certain pages in my application. For this I am using rSpec
and FactoryBot
as my fixtures replacement.
I have two factories, one for the role
which has_many
users and a user
that belongs_to
a role
.
Role factory
FactoryBot.define do
factory :role do
trait :admin do
role_name 'admin'
end
end
factory :admin, traits: [:admin]
end
User factory
FactoryBot.define do
factory :user do
association :role, factory: :admin
end
end
I am using Pundit for authorizatin and the pundit matchers gem for the testing of pundit policies.
require 'rails_helper'
describe AccountPolicy do
subject { described_class.new(user, account) }
let (:account) { Account.create }
context 'being an admin' do
let(:user) { User.create(role: :admin) }
it { is_expected.to permit_action([:index]) }
end
end
Above is the policy written to see if the user, being an admin, can access the Accounts index. When running rake
I get the following error.
ActiveRecord::AssociationTypeMismatch:
Role(#70284397401400) expected, got :admin which is an instance of Symbol(#70284363589400)
I see that I am getting a type mismatch. However, I am not sure how to return the role as an active record object, which I think is what it is expecting from the looks of it, instead of a symbol. How can I achieve this?
I think part of your issue is in your architecture, but I'll address that at the bottom.
let(:user) { User.create(role: :admin) }
This is trying to set a role attribute to the symbol :admin. Whereas you want to pass in an actual admin role object/record.
let(:admin_role) { Role.create(:admin) }
let(:user) { User.create(role: admin_role) }
However, your current user factory is setting the role factory to be the admin factory. So all users created will be admins by default. You'll want to do more reading on FactoryBot to structure your factories for easier creation of certain types of users. Adding traits to the user model to create the correct role would help with your current architecture.
Out of curiosity, why use a separate table for role if a User can only have one? Why not use an enum column on User?