Class: CanCan::ModelAdapters::MongoidAdapter

Inherits:
AbstractAdapter
  • Object
show all
Defined in:
lib/cancancan/model_adapters/mongoid_adapter.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_class, rules, options = {}) ⇒ MongoidAdapter

Returns a new instance of MongoidAdapter.



41
42
43
44
45
# 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

Class Method Details

.for_class?(model_class) ⇒ Boolean

Returns:

  • (Boolean)


6
7
8
# 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) ⇒ Boolean

Override if override_condition_matching? returns true

Returns:

  • (Boolean)


28
29
30
31
32
33
34
35
36
37
38
39
# 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) ⇒ Boolean

Override if override_conditions_hash_matching? returns true

Returns:

  • (Boolean)

Raises:

  • (NotImplemented)


17
18
19
# 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

.override_condition_matching?(_subject, _name, _value) ⇒ Boolean

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

Returns:

  • (Boolean)


23
24
25
# 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) ⇒ Boolean

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

Returns:

  • (Boolean)


12
13
14
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 12

def self.override_conditions_hash_matching?(_subject, _conditions)
  false
end

Instance Method Details

#closed_conditionsObject



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# 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_typesObject



66
67
68
69
70
# 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_recordsObject



117
118
119
120
121
122
123
124
125
126
127
# 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?Boolean

Returns:

  • (Boolean)


111
112
113
114
115
# 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_conditionsObject



72
73
74
75
76
77
78
79
80
81
82
83
84
# 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_typesObject



54
55
56
57
58
59
60
61
62
63
64
# 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_conditionsObject



105
106
107
108
109
# 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_typesObject



47
48
49
50
51
52
# 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