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.



45
46
47
48
49
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 45

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)


9
10
11
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 9

def for_class?(model_class)
  model_class <= Mongoid::Document
end

.matches_condition?(subject, name, value) ⇒ Boolean

Override if override_condition_matching? returns true

Returns:

  • (Boolean)


31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 31

def 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)


20
21
22
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 20

def 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)


26
27
28
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 26

def 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)


15
16
17
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 15

def override_conditions_hash_matching?(_subject, _conditions)
  false
end

Instance Method Details

#closed_conditionsObject



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 90

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



70
71
72
73
74
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 70

def closed_subject_types
  @closed_subject_types ||= begin
    subject_types - open_subject_types
  end
end

#database_recordsObject



121
122
123
124
125
126
127
128
129
130
131
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 121

def database_records
  return @model_class.none unless has_any_conditions?

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

  and_conditions = { "$and" => [*closed_conditions].compact }
  and_conditions = {} if and_conditions["$and"].empty?

  @model_class.where(or_conditions.merge(and_conditions))
end

#has_any_conditions?Boolean

Returns:

  • (Boolean)


115
116
117
118
119
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 115

def has_any_conditions?
  subject_type_conditions.present? ||
    open_conditions.present? ||
    closed_conditions.present?
end

#open_conditionsObject



76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 76

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



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 58

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



109
110
111
112
113
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 109

def subject_type_conditions
  return unless open_subject_types.present?

  { :"#{type_key}".nin => closed_subject_types.map(&:to_s) }
end

#subject_typesObject



51
52
53
54
55
56
# File 'lib/cancancan/model_adapters/mongoid_adapter.rb', line 51

def subject_types
  @subject_types ||= begin
    root_cls = @model_class.root_class
    [root_cls, *root_cls.descendants].compact
  end
end