|
|
@@ -1,4 +1,48 @@
|
|
|
1
|
+# An Activity represents a single continuous event that the members of a group may attend.
|
|
|
2
|
+# An Activity belongs to a group, and has many participants.
|
|
1
|
3
|
class Activity < ApplicationRecord
|
|
|
4
|
+ # @!attribute public_name
|
|
|
5
|
+ # @return [String]
|
|
|
6
|
+ # the name that users will see if there is no {#secret_name}, or if
|
|
|
7
|
+ # {#show_hidden} is `false`.
|
|
|
8
|
+ #
|
|
|
9
|
+ # @!attribute secret_name
|
|
|
10
|
+ # @return [String]
|
|
|
11
|
+ # a name that is (be default) only visible to organizers and group
|
|
|
12
|
+ # leaders. Can be shown or hidden to normal participants using
|
|
|
13
|
+ # {#show_hidden}.
|
|
|
14
|
+ #
|
|
|
15
|
+ # @!attribute description
|
|
|
16
|
+ # @return [String]
|
|
|
17
|
+ # a short text describing the activity. This text is always visible to
|
|
|
18
|
+ # all users.
|
|
|
19
|
+ #
|
|
|
20
|
+ # @!attribute location
|
|
|
21
|
+ # @return [String]
|
|
|
22
|
+ # a short text describing where the activity will take place. Always
|
|
|
23
|
+ # visible to all participants.
|
|
|
24
|
+ #
|
|
|
25
|
+ # @!attribute show_hidden
|
|
|
26
|
+ # @return [Boolean]
|
|
|
27
|
+ # Whether or not the 'secret' attributes can be viewed by the people who
|
|
|
28
|
+ # aren't organizers or group leaders. Currently, only {#secret_name} is
|
|
|
29
|
+ # influenced by this. More attributes may be added in the future, and
|
|
|
30
|
+ # will be controlled by this toggle as well.
|
|
|
31
|
+ #
|
|
|
32
|
+ # @!attribute start
|
|
|
33
|
+ # @return [TimeWithZone]
|
|
|
34
|
+ # when the activity starts.
|
|
|
35
|
+ #
|
|
|
36
|
+ # @!attribute end
|
|
|
37
|
+ # @return [TimeWithZone]
|
|
|
38
|
+ # when the activity ends.
|
|
|
39
|
+ #
|
|
|
40
|
+ # @!attribute deadline
|
|
|
41
|
+ # @return [TimeWithZone]
|
|
|
42
|
+ # when the normal participants (everyone who isn't an organizer or group
|
|
|
43
|
+ # leader) may not change their own attendance anymore. Disabled if set to
|
|
|
44
|
+ # nil.
|
|
|
45
|
+
|
|
2
|
46
|
belongs_to :group
|
|
3
|
47
|
|
|
4
|
48
|
has_many :participants
|
|
|
@@ -6,20 +50,45 @@ class Activity < ApplicationRecord
|
|
6
|
50
|
|
|
7
|
51
|
validates :public_name, presence: true
|
|
8
|
52
|
validates :start, presence: true
|
|
9
|
|
- validate :deadline_before_start
|
|
|
53
|
+ validate :deadline_before_start, unless: "self.deadline.blank?"
|
|
|
54
|
+ validate :end_after_start, unless: "self.end.blank?"
|
|
10
|
55
|
|
|
|
56
|
+ # Get all people (not participants) that are organizers. Does not include
|
|
|
57
|
+ # group leaders, although they may modify the activity as well.
|
|
11
|
58
|
def organizers
|
|
12
|
|
- self.organizers.includes(:person).where(is_organizer: true)
|
|
|
59
|
+ self.participants.includes(:person).where(is_organizer: true)
|
|
|
60
|
+ end
|
|
|
61
|
+
|
|
|
62
|
+ # Determine whether the passed Person participates in the activity.
|
|
|
63
|
+ def is_participant?(person)
|
|
|
64
|
+ Participant.exists?(
|
|
|
65
|
+ activity_id: self.id,
|
|
|
66
|
+ person_id: person.id
|
|
|
67
|
+ )
|
|
13
|
68
|
end
|
|
14
|
69
|
|
|
15
|
|
- def is_organizer(person)
|
|
16
|
|
- Participant.exists?(person_id: person.id, activity_id: self.id, is_organizer: true)
|
|
|
70
|
+ # Determine whether the passed Person is an organizer for the activity.
|
|
|
71
|
+ def is_organizer?(person)
|
|
|
72
|
+ Participant.exists?(
|
|
|
73
|
+ person_id: person.id,
|
|
|
74
|
+ activity_id: self.id,
|
|
|
75
|
+ is_organizer: true
|
|
|
76
|
+ )
|
|
17
|
77
|
end
|
|
18
|
78
|
|
|
19
|
79
|
private
|
|
|
80
|
+ # Assert that the deadline for participants to change the deadline, if any,
|
|
|
81
|
+ # is set before the event starts.
|
|
20
|
82
|
def deadline_before_start
|
|
21
|
|
- if self.deadline && self.deadline > self.start
|
|
|
83
|
+ if self.deadline > self.start
|
|
22
|
84
|
errors.add(:deadline, 'must be before start')
|
|
23
|
85
|
end
|
|
24
|
86
|
end
|
|
|
87
|
+
|
|
|
88
|
+ # Assert that the activity's end, if any, occurs after the event's start.
|
|
|
89
|
+ def end_after_start
|
|
|
90
|
+ if self.end < self.start
|
|
|
91
|
+ errors.add(:end, 'must be after start')
|
|
|
92
|
+ end
|
|
|
93
|
+ end
|
|
25
|
94
|
end
|