class CanCan::ModelAdapters::MongoidAdapter

Public Class Methods

for_class?(model_class) click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 6
def self.for_class?(model_class)
  model_class <= Mongoid::Document
end
matches_condition?(subject, name, value) click to toggle source

Override if override_condition_matching? returns true

# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 28
def self.matches_condition?(subject, name, value)
  attribute = subject.send(name)

  case value
  when Hash then hash_condition_match?(attribute, value)
  when Range then value.cover?(attribute)
  when Regexp then value.match(attribute)
  when Array then value.include?(attribute)
  when Enumerable then value.include?(attribute)
  else attribute == value
  end
end
matches_conditions_hash?(_subject, _conditions) click to toggle source

Override if override_conditions_hash_matching? returns true

# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 17
def self.matches_conditions_hash?(_subject, _conditions)
  raise NotImplemented, 'This model adapter does not support matching on a conditions hash.'
end
new(model_class, rules, options = {}) click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 41
def initialize(model_class, rules, options = {})
  @model_class = model_class
  @rules = rules
  @options = options
end
override_condition_matching?(_subject, _name, _value) click to toggle source

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

# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 23
def self.override_condition_matching?(_subject, _name, _value)
  true
end
override_conditions_hash_matching?(_subject, _conditions) click to toggle source

Used to determine if this model adapter will override the matching behavior for a hash of conditions. If this returns true then matches_conditions_hash? will be called. See Rule#matches_conditions_hash

# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 12
def self.override_conditions_hash_matching?(_subject, _conditions)
  false
end

Public Instance Methods

closed_conditions() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 86
def closed_conditions
  @closed_conditions ||= begin
    condition_rules.reject(&:base_behavior).each_with_object([]) do |rule, res|
      rule.conditions.each do |key, value|
        key = id_key if %i[id _id].include?(key.to_sym)
        case value
        when Regexp then res << { key => { '$not' => value } }
        else
          if prev_value = res.detect { |item| item.dig(key, '$nin') }
            prev_value[key]['$nin'] += Array(value)
          else
            res << { key => { '$nin' => Array(value) } }
          end
        end
      end
    end
  end
end
closed_subject_types() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 66
def closed_subject_types
  @closed_subject_types ||= begin
    subject_types - open_subject_types
  end
end
database_records() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 117
def database_records
  return @model_class.none unless has_any_conditions?

  or_conditions = { '$or' => [subject_type_conditions, *open_conditions].compact }
  or_conditions = nil if or_conditions['$or'].empty?

  and_conditions = { '$and' => [or_conditions, *closed_conditions].compact }
  and_conditions = nil if and_conditions['$and'].empty?

  @model_class.where(and_conditions)
end
has_any_conditions?() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 111
def has_any_conditions?
  subject_type_conditions.present? ||
    open_conditions.present? ||
    closed_conditions.present?
end
open_conditions() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 72
def open_conditions
  @open_conditions ||= begin
    condition_rules.select(&:base_behavior).each_with_object([]) do |rule, res|
      rule.conditions.each do |key, value|
        key = id_key if %i[id _id].include?(key.to_sym)
        res <<  case value
                when Array then { key => { '$in' => value } }
                else { key => value }
                end
      end
    end
  end
end
open_subject_types() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 54
def open_subject_types
  @open_subject_types ||= begin
    subject_types.inject(Set[]) do |res, cls|
      subject_type_rules_for(cls).each do |rule|
        cls_list = [cls, *cls.descendants].compact
        rule.base_behavior ? res += cls_list : res -= cls_list
      end
      res.to_a
    end
  end
end
subject_type_conditions() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 105
def subject_type_conditions
  return unless open_subject_types.present?

  { :"#{type_key}".nin => closed_subject_types.map(&:to_s) }
end
subject_types() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 47
def subject_types
  @subject_types ||= begin
    root_cls = @model_class.root_class
    [root_cls, *root_cls.descendants].compact
  end
end

Private Instance Methods

condition_rules() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 141
def condition_rules
  @rules.select { |rule| rule.conditions.present? }
end
id_key() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 149
def id_key
  @id_key ||= [prefix, '_id'].reject(&:blank?).join.to_sym
end
prefix() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 145
def prefix
  @options.fetch(:prefix, nil)
end
subject_type_rules() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 137
def subject_type_rules
  @rules.reject { |rule| rule.conditions.present? }
end
subject_type_rules_for(subject_type) click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 131
def subject_type_rules_for(subject_type)
  subject_type_rules.select do |rule|
    rule.subjects.include?(subject_type)
  end
end
type_key() click to toggle source
# File lib/cancancan/model_adapters/mongoid_adapter.rb, line 153
def type_key
  @type_key ||= [prefix, '_type'].reject(&:blank?).join.to_sym
end