Welcome to mirror list, hosted at ThFree Co, Russian Federation.

participable.rb « concerns « models « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9f667f47e0da8f6ee549e2bcbc92d3144b8c4b34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
68
69
70
71
72
73
# == Participable concern
#
# Contains functionality related to objects that can have participants, such as
# an author, an assignee and people mentioned in its description or comments.
#
# Used by Issue, Note, MergeRequest, Snippet and Commit.
#
# Usage:
#
#     class Issue < ActiveRecord::Base
#       include Participable
#
#       # ...
#
#       participant :author, :assignee, :mentioned_users, :notes
#     end
#     
#     issue = Issue.last
#     users = issue.participants
#     # `users` will contain the issue's author, its assignee,
#     # all users returned by its #mentioned_users method,
#     # as well as all participants to all of the issue's notes,
#     # since Note implements Participable as well.
#
module Participable
  extend ActiveSupport::Concern

  module ClassMethods
    def participant(*attrs)
      participant_attrs.concat(attrs.map(&:to_s))
    end

    def participant_attrs
      @participant_attrs ||= []
    end
  end

  def participants(current_user = self.author, project = self.project)
    participants = self.class.participant_attrs.flat_map do |attr|
      meth = method(attr)

      value = 
        if meth.arity == 1 || meth.arity == -1
          meth.call(current_user)
        else
          meth.call
        end

      participants_for(value, current_user, project)
    end.compact.uniq

    if project
      participants.select! do |user|
        user.can?(:read_project, project)
      end
    end

    participants
  end

  private
  
  def participants_for(value, current_user = nil, project = nil)
    case value
    when User
      [value]
    when Enumerable, ActiveRecord::Relation
      value.flat_map { |v| participants_for(v, current_user, project) }
    when Participable
      value.participants(current_user, project)
    end
  end
end