Class: MongoidAbility::Ability

Inherits:
Object
  • Object
show all
Includes:
CanCan::Ability
Defined in:
lib/mongoid_ability/ability.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(owner) ⇒ Ability

Returns a new instance of Ability.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/mongoid_ability/ability.rb', line 31

def initialize(owner)
  @owner = owner

  inherited_locks = owner.respond_to?(owner.class.inherit_from_relation_name) ? owner.inherit_from_relation.flat_map(&:locks_relation) : []
  inherited_locks = LocksDecorator.new(inherited_locks)

  owner_locks = owner.respond_to?(owner.class.locks_relation_name) ? owner.locks_relation : []

  self.class.subject_root_classes.each do |cls|
    cls_list = [cls] + cls.descendants
    cls_list.each do |subcls|
      # if 2 of the same, prefer open
      locks = subcls.default_locks.for_subject_type(subcls).group_by(&:group_key_for_calc).flat_map do |_, locks|
        locks.detect(&:open?) || locks.first
      end

      # if 2 of the same, prefer open
      locks += inherited_locks.for_subject_type(subcls).group_by(&:group_key_for_calc).flat_map do |_, locks|
        locks.detect(&:open?) || locks.first
      end

      # if 2 of the same, prefer open
      locks += owner_locks.for_subject_type(subcls).group_by(&:group_key_for_calc).flat_map do |_, locks|
        locks.detect(&:open?) || locks.first
      end

      selected_locks = locks.group_by(&:group_key_for_calc).flat_map do |_, locks|
        # prefer last one, i.e. the one closest to owner
        locks.last
      end

      selected_locks.sort(&Lock.sort).each do |lock|
        apply_lock_rule(lock)
      end
    end
  end
end

Instance Attribute Details

#ownerObject

Returns the value of attribute owner.



7
8
9
# File 'lib/mongoid_ability/ability.rb', line 7

def owner
  @owner
end

Class Method Details

.subject_classesObject



19
20
21
22
23
# File 'lib/mongoid_ability/ability.rb', line 19

def self.subject_classes
  Object.descendants.select do |cls|
    cls.included_modules.include?(MongoidAbility::Subject)
  end
end

.subject_root_classesObject



25
26
27
28
29
# File 'lib/mongoid_ability/ability.rb', line 25

def self.subject_root_classes
  subject_classes.reject do |cls|
    cls.superclass.included_modules.include?(MongoidAbility::Subject)
  end
end

Instance Method Details

#marshal_dumpObject



9
10
11
# File 'lib/mongoid_ability/ability.rb', line 9

def marshal_dump
  @rules
end

#marshal_load(array) ⇒ Object



13
14
15
16
17
# File 'lib/mongoid_ability/ability.rb', line 13

def marshal_load(array)
  Array(array).each do |rule|
    add_rule(rule)
  end
end

#model_adapter(model_class, action, options = {}) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/mongoid_ability/ability.rb', line 69

def model_adapter(model_class, action, options = {})
  @model_adapter ||= {}
  @model_adapter[model_class] ||= {}
  @model_adapter[model_class][action] ||= {}
  @model_adapter[model_class][action][options] ||= begin
    adapter_class = CanCan::ModelAdapters::AbstractAdapter.adapter_class(model_class)
    # include all rules that apply for descendants as well
    # so the adapter can exclude include subclasses from critieria
    rules = ([model_class] + model_class.descendants).inject([]) do |res, cls|
      res += relevant_rules_for_query(action, cls)
      res.uniq
    end
    adapter_class.new(model_class, rules, options)
  end
end