ruby-on-railsrubyfactory-botcancanrolify

FactoryGirl How to add several objects with different roles


class Ability

include CanCan::Ability

def initialize(user)

user ||= User.new # guest user

if user.has_role?  :student
  can :create, Atendimento
end

if user.has_role?  :professor
  can :create, Atendimento
end
if user.has_role? :administrative
  can [:read, :create], [Atendimento]
  can [:edit, :update], Atendimento
  can :manage, [Type, Place]
 end
if user.has_role? :admin
  can :manage, :all
end
end
end

and my factory

FactoryGirl.define do
factory :user do |f|
f.name "Alessandro"
f.username "alessandrocb"
f.matricula "123456789"
f.password "123456789"
f.password_confirmation "123456789"
f.after(:create) {|user| user.add_role(:student)}
end

I need those mocks receive all roles , but now I can only student role

my test with rspec

subject(:ability){ Ability.new(user) }
let(:user){ nil }

 context "when is an User" do
 let(:user) { FactoryGirl.create(:user) } 

what is happening is this: I can only test with rspec with only 1 paper, but would like to test with all the cancan, I need to create the factory with all these possibilities for different roles


Solution

  • First solution

    FactoryGirl.define do
      factory :user do
        name "Alessandro"
        username "alessandrocb"
        (...)
        trait :student do
          after(:create) {|user| user.add_role(:student)}
        end
        trait :professor do
          after(:create) {|user| user.add_role(:professor)}
        end
        trait :administrative do
          after(:create) {|user| user.add_role(:administrative)}
        end
        trait :admin do
          after(:create) {|user| user.add_role(:admin)}
        end
      end
    end
    

    You can then use and combine these traits like this:

    # Create a student
    create :user, :student
    
    # Create a user who is both professor and admin
    create :user, :professor, :admin
    

    Second solution

    FactoryGirl.define do
      factory :user do
        name "Alessandro"
        username "alessandrocb"
        (...)
        ignore do
          role
        end
        after(:create) do |user, params|      
          user.add_role(params.role)  if params.role
        end
      end
    end
    

    And then:

    # Create a student
    create :user, role: :student
    

    Note that the second solution does not allow you to combine roles as it is. But you could use an array to achieve this.