CanCanCommunity/cancancan · error · CanCan::NotImplemented

This model adapter does not support fetching records from th

Error message

This model adapter does not support fetching records from the database.

What it means

AbstractAdapter#database_records (lib/cancan/model_adapters/abstract_adapter.rb:73) raises CanCan::NotImplemented. AbstractAdapter.adapter_class falls back to the abstract class when no ORM-specific adapter is registered (the gem ships only ActiveRecord 4/5 adapters plus a default), so calling accessible_by on a model whose ORM has no adapter — Sequel, DataMapper, ROM, plain Ruby objects — fails here.

Source

Thrown at lib/cancan/model_adapters/abstract_adapter.rb:73

      # Used to determine if this model adapter will override the matching behavior for a specific condition.
      # If this returns true then matches_condition? will be called. See Rule#matches_conditions_hash
      def self.override_condition_matching?(_subject, _name, _value)
        false
      end

      # Override if override_condition_matching? returns true
      def self.matches_condition?(_subject, _name, _value)
        raise NotImplemented, 'This model adapter does not support matching on a specific condition.'
      end

      def initialize(model_class, rules)
        @model_class = model_class
        @rules = rules
      end

      def database_records
        # This should be overridden in a subclass to return records which match @rules
        raise NotImplemented, 'This model adapter does not support fetching records from the database.'
      end
    end
  end
end

View on GitHub (pinned to 8c1bf153a3)

Solutions

  1. Use ActiveRecord (or a model backed by a supported adapter) for resources you load with accessible_by.
  2. Write a custom adapter: subclass CanCan::ModelAdapters::AbstractAdapter, implement self.for? and database_records, and register it.
  3. Load records manually in the controller and authorize each in Ruby: @records = Invoice.all.select { |i| can?(:read, i) }.
  4. Check require order so the ActiveRecord adapter is loaded before any accessible_by call in initializers.

Example fix

# before
class InvoicesController < ApplicationController
  load_and_authorize_resource  # Invoice is a Sequel::Model -> index raises NotImplemented
end

# after
class InvoicesController < ApplicationController
  def index
    @invoices = Invoice.all.select { |i| can?(:read, i) }
  end
end
Defensive patterns

Strategy: validation

Validate before calling

# confirm a real ORM adapter is registered before querying
adapter = CanCan::ModelAdapters::AbstractAdapter.adapter_class(Invoice)
raise CanCan::NotImplemented, 'no adapter for this ORM' if adapter == CanCan::ModelAdapters::AbstractAdapter

Type guard

def query_supported?(model_class)
  CanCan::ModelAdapters::AbstractAdapter.adapter_class(model_class) != CanCan::ModelAdapters::AbstractAdapter
end

Try / catch

begin
  @invoices = Invoice.accessible_by(current_ability)
rescue CanCan::NotImplemented
  @invoices = Invoice.all.select { |i| can?(:read, i) } # Ruby-side fallback
end

Prevention

When it happens

Trigger: Invoice.accessible_by(current_ability) where Invoice is a Sequel::Model; an index action of load_and_authorize_resource on a non-ActiveRecord model; ActiveRecord not yet loaded/required when accessible_by runs (adapter never registers).

Common situations: Introducing CanCanCan into a service object / non-Rails context; a legacy app transitioning between ORMs; gems loading cancancan before the ORM adapter gets required in the boot order.

Related errors


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