-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdraw_student_assignment_form.rb
133 lines (113 loc) · 3.31 KB
/
draw_student_assignment_form.rb
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# frozen_string_literal: true
#
# Form / service object for adding or removing a single user to/from a draw by
# username. Removes them from their current draw (if they belong to one) and
# saves their previeous draw ID so they can be restored.
class DrawStudentAssignmentForm
include ActiveModel::Model
include Callable
attr_accessor :login, :login_attr, :adding
validates :login, presence: true
validates :adding, inclusion: { in: [true, false] }
validate :student_found
validate :student_valid
# Initializes a DrawStudentAssignmentForm
#
# @param params [#to_h] parameters from controller
def initialize(draw:, params: nil)
@draw = draw
@adding = true
@login_attr = User.login_attr
process_params(params) if params
end
# Execute the student update, either adding or removing the student in
# question. If the username is invalid or belongs to a user in a group,
# returns an error.
#
# @return Hash{Symbol=>Nil,DrawStudentAssignmentForm,Hash} a result hash
# containing nil for the :redirect_object, the DrawStudentAssignmentForm
# set to :update_object if there were any failures, and a flash message
def submit
return error(self) unless valid?
update_students
success
rescue ActiveRecord::RecordInvalid => e
error(e)
end
make_callable :submit
private
attr_reader :draw, :student
def update_students
if adding?
add_student(student)
else
student.draw_membership&.restore_draw(save_current: true)&.save!
end
end
def process_params(params)
@params = params.to_h.symbolize_keys
@login = @params[:login]&.downcase
@adding = @params[:adding] == 'true'
@student = find_student
end
def find_student
return nil unless login
UngroupedStudentsQuery.call.find_by(login_attr => login)
end
def student_found
return if student
# This query is needed to find out if a student record exists in our db
# but has a group already assigned to it.
if User.find_by(login_attr => login).present?
errors.add(
:username,
'cannot be added to this draw because they are already in a group.'
)
else
errors.add(:username,
"cannot be found. Maybe you haven't imported them yet?")
end
end
def student_valid
return unless student
validate_addition if adding?
validate_removal if removing?
end
def validate_addition
return unless student.draw == draw
errors.add(:username,
'must belong to a student outside the draw when adding')
end
def validate_removal
return unless student.draw != draw
errors.add(:username,
'must belong to a student in the draw when removing')
end
def add_student(student)
if student.draw_membership.present?
student.draw_membership&.remove_draw&.update!(draw: draw)
else
student.update!(draw: draw)
end
end
def success
verb = adding? ? 'added' : 'removed'
{
redirect_object: nil, update_object: nil,
msg: { success: "#{student.full_name} successfully #{verb}" }
}
end
def error(e)
msgs = ErrorHandler.format(error_object: e)
{
redirect_object: nil, update_object: self,
msg: { error: "Student update failed: #{msgs}" }
}
end
def adding?
adding
end
def removing?
!adding?
end
end