Search code examples
ruby-on-railsrspecauthlogicshoulda

Ruby on Rails with RSpec and shoulda-matcher validate_inclusion_of giving NoMethodError


I'm having problems with the validate_inclusion_of matcher when writing a spec.

My current specs are to do with users and user groups. A user has a user group id.

I want to check that the user group id of a user is actually in the list of current user group ids.

At the moment my spec is basically:



describe 'company_user_group list of valid IDs' do
  let!(:company_user_group_everything) { FactoryGirl.create(:company_user_group_everything) }
  let!(:company_user_group_nothing) { FactoryGirl.create(:company_user_group_nothing) }
  it '' do
    @company_user = FactoryGirl.create(:company_user, id: 1)
    CompanyUser.current_id = @company_user.id

    is_expected.to validate_inclusion_of(:company_user_group_id).in_array(CompanyUserGroup.full_list_of_ids)
  end
end

but the error I get is:



    1) CompanyUser validations company_user_group list of valid IDs should validate that :company_user_group_id is either ‹2› or ‹3›
         Failure/Error: is_expected.to validate_inclusion_of(:company_user_group_id).in_array(CompanyUserGroup.full_list_of_ids)

         NoMethodError:
           undefined method `attribute_setter' for nil:NilClass

I have tried various different things and debugged using byebug etc. but nothing is working for me.

e.g.

Adding in



    @company_user_group_id = @company_user.company_user_group_id

and changing the is_expected.to line to


    is_expected.to validate_inclusion_of(@company_user_group_id).in_array(CompanyUserGroup.full_list_of_ids)

I get the following error


  1) CompanyUser validations company_user_group list of valid IDs should validate that :8 is either ‹8› or ‹9›
     Failure/Error: is_expected.to validate_inclusion_of(@company_user_group_id).in_array(CompanyUserGroup.full_list_of_ids)

     Shoulda::Matchers::ActiveModel::AllowValueMatcher::AttributeDoesNotExistError:
       The matcher attempted to set :8 on the CompanyUser to 8, but that
       attribute does not exist

So it seems that the group id to check is valid (e.g. 8) and the array is valid (e.g. 8 and 9) but the matching isn't working.

Any help much appreciated!

Some of the company user model



    # This model holds User identities for internal staff.  This model is
    # primarily intended for use in the xxxx application.
    class CompanyUser LT ActiveRecord::Base
      acts_as_authentic do |c|

        c.merge_validates_uniqueness_of_email_field_options case_sensitive: false
        c.merge_validates_length_of_password_field_options minimum: 8

        if Rails.env.production?
          c.logged_in_timeout = 30.minutes
        else
          c.logged_in_timeout = 90.minutes
        end
      end

      # Constants

      # relationships
      belongs_to :company_user_group

      # validations
      validates :first_name, presence: true, length: { maximum: 20 }
      validates :last_name, presence: true, length: { maximum: 20 }
      validates :company_user_group_id, presence: true, numericality: { only_integer: true, greater_than: 0 }
      validates :company_user_group_id, inclusion: { in: CompanyUserGroup.full_list_of_ids }, unless: 'Rails.env.test?'
      validate :check_sys_admin_permission

If the "unless: 'Rails.env.test?'" bit is removed, most of the specs fail for some unknown reason. Just mentioned in case it is relevant.

and the following method from the Company Group model



      # class methods
      def self.full_list_of_ids
        CompanyUserGroup.all.pluck(:id)
      end


Solution

  • I have figured it out. For some reason the validate_inclusion_of works when it is within a let! block.

    It doesn't matter what argument is sent to the let helper method, just that one is.

    Still don't know WHY this fixes it though, if anybody can enlighten me!?

    So, the following spec now passes

    
        describe 'company_user_group list of valid IDs' do
          let!(:company_user_group_everything) { FactoryGirl.create(:company_user_group_everything) }
          let!(:company_user_group_nothing) { FactoryGirl.create(:company_user_group_nothing) }
    
          let!(:temp) do
            it {is_expected.to validate_inclusion_of(:company_user_group_id).in_array(CompanyUserGroup.full_list_of_ids)}
          end
    
        end