-
Notifications
You must be signed in to change notification settings - Fork 0
/
database.rb
120 lines (110 loc) · 3.38 KB
/
database.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
require 'pathname'
require 'yaml'
require 'pp'
module SchoolRecord
# A Database stores Note and Lesson objects in an organised way and persists
# them to disk. It needs to know the base directory where it can read and
# write its data. The recommended way to create or access a Database object is
# to use one of the factory methods:
# db = Database.test
# db = Database.production
# More of these could be defined, for instance if there were test scenarios
# requiring different databases.
#
class Database
def Database.dev
@testdb ||= Database.new( Dirs.dev_database_directory )
end
def Database.test
@testdb ||= Database.new( Dirs.test_database_directory )
end
def initialize(directory)
@files = Files.new(directory)
@classes = load_class_lists
# { '7' -> (SchoolClass), '10' -> (SchoolClass), ... }
@notes = load_notes
# { '7' -> [Note, Note, ...], ... }
end
# Notes.
def load_notes
notes = Hash.new { |hash, key| hash[key] = [] }
contents = @files.notes_file.read
if contents.strip.empty?
return notes
else
data = YAML.load(contents)
if data.is_a? Hash
return notes.merge(data)
else
msg = "#{@files.notes_file.to_s} contains invalid data.\n"
msg << contents
sr_int msg
end
end
end
def save_note(note)
@notes[note.student.class_label] << note
@files.notes_file.open('w') do |out|
out.puts YAML.dump(@notes)
end
end
def notes(class_label, name_fragment=nil)
notes = @notes[class_label]
if name_fragment
students = resolve_student(class_label, name_fragment)
names = students.map { |s| s.fullname }
notes = notes.select { |note|
note.student.fullname.in? names
}
end
notes
end
def contents_of_notes_file
@files.notes_file.read
end
# Class lists.
def load_class_lists
data = YAML.load(@files.class_lists_file.read)
# See file class-lists.yaml for the format of the data.
result = {}
data.each do |key, hash|
label, full_label, full_name, students =
hash.values_at('label', 'full_label', 'full_name', 'students')
students = students.map { |str|
last, first = str.split(', ')
SR::DO::Name.new(first.strip, last.strip)
}
result[label] = SR::DO::SchoolClass.new(label, full_label, full_name, students)
end
result
end
def valid_class_label?(label)
@classes.key? label
end
def resolve_student(class_label, name_fragment)
@classes[class_label].resolve(name_fragment)
end
def resolve_student!(class_label, name_fragment)
@classes[class_label].resolve!(name_fragment)
end
end # class Database
class Database::Dirs
def self.dev_database_directory
@dir ||= Pathname.new("etc/dev-db").tap { |p| p.mkpath }
end
def self.test_database_directory
@dir ||= Pathname.new("test/db").tap { |p| p.mkpath }
end
end # class Database::Dirs
class Database::Files
def initialize(directory)
@directory = Pathname.new(directory)
end
def notes_file
@nf ||= @directory + "notes.yaml"
end
def class_lists_file
@clf ||= @directory + "class-lists.yaml"
end
end # class Database::Files
end # module SchoolRecord