CanCanCommunity/cancancan · warning

RSpec < 3 will not be supported in the CanCanCan >= 2.0.0

Error message

RSpec < 3 will not be supported in the CanCanCan >= 2.0.0

What it means

lib/cancan/matchers.rb detects whether RSpec::Core (RSpec 2/3+) or the legacy Spec constant (RSpec 1) is defined. On the legacy path it emits ActiveSupport::Deprecation.warn('RSpec < 3 will not be supported in the CanCanCan >= 2.0.0') (lib/cancan/matchers.rb:9) and then defines be_able_to against the old Spec::Matchers API. It is a deprecation warning, not a raised exception — specs still run.

Source

Thrown at lib/cancan/matchers.rb:9

# frozen_string_literal: true

rspec_module = defined?(RSpec::Core) ? 'RSpec' : 'Spec' # RSpec 1 compatability

if rspec_module == 'RSpec'
  require 'rspec/core'
  require 'rspec/expectations'
else
  ActiveSupport::Deprecation.warn('RSpec < 3 will not be supported in the CanCanCan >= 2.0.0')
end

Kernel.const_get(rspec_module)::Matchers.define :be_able_to do |*args|
  match do |ability|
    actions = args.first
    if actions.is_a? Array
      if actions.empty?
        false
      else
        actions.all? { |action| ability.can?(action, *args[1..-1]) }
      end
    else
      ability.can?(*args)
    end
  end

  # Check that RSpec is < 2.99
  if !respond_to?(:failure_message) && respond_to?(:failure_message_for_should)

View on GitHub (pinned to 8c1bf153a3)

Solutions

  1. Upgrade to RSpec >= 3 (rspec-rails '~> 3.0' or newer) and re-run bundle install.
  2. If the old RSpec must stay, pin cancancan to a version below 2.0 that still supports it.
  3. Stop requiring cancan/matchers in the legacy setup and test abilities with plain assertions (ability.can?(:read, article).should be_true style) until the upgrade.

Example fix

# before (Gemfile)
gem 'cancancan'
gem 'rspec-rails', '~> 2.14'  # Spec constant -> deprecation warning on require 'cancan/matchers'

# after (Gemfile)
gem 'cancancan'
gem 'rspec-rails', '~> 6.0'
Defensive patterns

Strategy: validation

Validate before calling

# spec_helper.rb — fail fast on unsupported RSpec instead of warning
raise 'CanCanCan matchers need RSpec >= 3' if defined?(Spec) && !defined?(RSpec::Core)
require 'cancan/matchers'

Type guard

def modern_rspec?
  defined?(RSpec::Core) && Gem::Version.new(RSpec::Version::STRING) >= Gem::Version.new('3.0')
end

Prevention

When it happens

Trigger: Gemfile pins rspec or rspec-rails to a 1.x/2.x release (exposing the Spec constant without RSpec::Core), and spec_helper requires 'cancan/matchers' to get be_able_to; Bundler resolves an ancient rspec transitive dependency in a legacy app.

Common situations: Long-lived Rails 3/4 apps upgrading cancancan but not the test stack; gems tested across many appraisals where one appraisal still uses RSpec 2.

Related errors


AI-assisted analysis of CanCanCommunity/cancancan@8c1bf153a3 (2026-08-21). Data as JSON: /api/errors/6bd859c81c6decbb. Report an issue: GitHub.