{"record":{"id":"aaa5cf70c7e18736","repo":"CanCanCommunity/cancancan","slug":"this-model-adapter-does-not-support-matching-on-a","errorCode":null,"errorMessage":"This model adapter does not support matching on a conditions hash.","messagePattern":"This model adapter does not support matching on a conditions hash\\.","errorType":"exception","errorClass":"CanCan::NotImplemented","httpStatus":null,"severity":"error","filePath":"lib/cancan/model_adapters/abstract_adapter.rb","lineNumber":35,"sourceCode":"      # Used to determine if the given adapter should be used for the passed in class.\n      def self.for_class?(_member_class)\n        false # override in subclass\n      end\n\n      # Override if you need custom find behavior\n      def self.find(model_class, id)\n        model_class.find(id)\n      end\n\n      # Used to determine if this model adapter will override the matching behavior for a hash of conditions.\n      # If this returns true then matches_conditions_hash? will be called. See Rule#matches_conditions_hash\n      def self.override_conditions_hash_matching?(_subject, _conditions)\n        false\n      end\n\n      # Override if override_conditions_hash_matching? returns true\n      def self.matches_conditions_hash?(_subject, _conditions)\n        raise NotImplemented, 'This model adapter does not support matching on a conditions hash.'\n      end\n\n      # Override if parent condition could be under a different key in conditions\n      def self.parent_condition_name(parent, _child)\n        parent.class.name.downcase.to_sym\n      end\n\n      # Used above override_conditions_hash_matching to determine if this model adapter will override the\n      # matching behavior for nested subject.\n      # If this returns true then nested_subject_matches_conditions? will be called.\n      def self.override_nested_subject_conditions_matching?(_parent, _child, _all_conditions)\n        false\n      end\n\n      # Override if override_nested_subject_conditions_matching? returns true\n      def self.nested_subject_matches_conditions?(_parent, _child, _all_conditions)\n        raise NotImplemented, 'This model adapter does not support matching on a nested subject.'\n      end","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/CanCanCommunity/cancancan/blob/8c1bf153a3da7b2261d6fa4a5f84eb28e2feb828/lib/cancan/model_adapters/abstract_adapter.rb#L17-L53","documentation":"AbstractAdapter#matches_conditions_hash? (lib/cancan/model_adapters/abstract_adapter.rb:35) is a template method that raises CanCan::NotImplemented. It is only reachable on a model adapter whose override_conditions_hash_matching? returns true but which never implemented matches_conditions_hash? — i.e., an incomplete custom adapter. It fires when a rule with a conditions hash is checked against an in-memory record (can?/authorize!).","triggerScenarios":"Writing a custom adapter for Sequel/DataMapper/etc. that declares def self.override_conditions_hash_matching?(_, _); true; end without implementing matches_conditions_hash?, then calling can?(:read, record) with hash conditions for that model; a third-party adapter gem whose version lags the CanCanCan API.","commonSituations":"Bringing CanCanCan to a non-ActiveRecord ORM by copying the ActiveRecord adapter skeleton; upgrading cancancan so the adapter contract gained new methods your fork predates.","solutions":["If you maintain the adapter: implement self.matches_conditions_hash?(subject, conditions) to evaluate the hash against the subject.","Or return false from override_conditions_hash_matching? so CanCanCan falls back to its built-in hash matching.","If you just use the gem: switch the model to a supported ORM (ActiveRecord) or update/patch the third-party adapter.","Avoid hash conditions for that model until the adapter supports them (use blocks)."],"exampleFix":"# before (custom adapter)\nclass MyAdapter < CanCan::ModelAdapters::AbstractAdapter\n  def self.override_conditions_hash_matching?(_subject, _conditions)\n    true # promises hash matching...\n  end\n  # ...but matches_conditions_hash? is never implemented -> NotImplemented\nend\n\n# after\nclass MyAdapter < CanCan::ModelAdapters::AbstractAdapter\n  def self.override_conditions_hash_matching?(_subject, _conditions)\n    false # let CanCanCan's default hash matching handle it\n  end\n  # or implement it:\n  # def self.matches_conditions_hash?(subject, conditions)\n  #   conditions.all? { |k, v| subject.public_send(k) == v }\n  # end\nend","handlingStrategy":"validation","validationCode":"# adapter authors: only claim the override you implement\nclass MyAdapter < CanCan::ModelAdapters::AbstractAdapter\n  def self.override_conditions_hash_matching?(_subject, _conditions)\n    respond_to?(:matches_conditions_hash?) && !method(:matches_conditions_hash?).owner == MyAdapter rescue false\n  end\nend\n# users of a broken adapter: avoid hash conditions for that model\ncan :read, Widget { |w| w.visible? } # block conditions skip the hash-matching path","typeGuard":"def adapter_supports_hash_matching?(adapter)\n  !adapter.override_conditions_hash_matching?(nil, {}) || adapter.method(:matches_conditions_hash?).owner != CanCan::ModelAdapters::AbstractAdapter\nend","tryCatchPattern":"begin\n  can?(:read, widget)\nrescue CanCan::NotImplemented => e\n  Rails.logger.error(\"adapter incomplete: #{e.message}\")\n  false\nend","preventionTips":["When writing a custom adapter, flip each override_* flag to true only after the matching method is implemented.","Copy the full ActiveRecord adapter as the skeleton rather than the abstract one, so no method is missing.","Smoke-test the adapter with can?, authorize!, and accessible_by in its own spec suite before shipping."],"tags":["model-adapter","custom-orm","not-implemented","cancancan","ruby"],"backgroundTag":"unimplemented-adapter-method","analyzedSha":"8c1bf153a3da7b2261d6fa4a5f84eb28e2feb828","analyzedAt":"2026-08-21T20:05:55.000Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}