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
- Upgrade to RSpec >= 3 (rspec-rails '~> 3.0' or newer) and re-run bundle install.
- If the old RSpec must stay, pin cancancan to a version below 2.0 that still supports it.
- 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
- Pin rspec-rails '>= 3' in the Gemfile so Bundler cannot resolve legacy RSpec.
- Treat deprecation warnings as CI failures (config.raise_errors_for_deprecations! in rspec 2 or a warning-as-error flag).
- Require 'cancan/matchers' only from spec files, never from app initializers.
- Run bundle update rspec after upgrading cancancan major versions.
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
- accessible_by_strategy = :subquery requires ActiveRecord 5 o
- You are not authorized to access this page.
- You can't specify target (#{target}) as alias because it is
- The can? and cannot? call cannot be used with a raw sql 'can
- accessible_by_strategy must be one of #{valid_accessible_by_
AI-assisted analysis of CanCanCommunity/cancancan@8c1bf153a3 (2026-08-21).
Data as JSON: /api/errors/6bd859c81c6decbb.
Report an issue: GitHub.