schild.rb 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. require 'schild/version'
  2. require 'sequel'
  3. if Module.private_method_defined? :include
  4. class Module
  5. public :include
  6. end
  7. end
  8. # String und Symbol werden um snake_case ergänzt, das die Schild-Tabellen umbenennt
  9. module CoreExtensions
  10. module String
  11. def snake_case
  12. return downcase if match(/\A[A-Z]+\z/)
  13. gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
  14. gsub(/([a-z])([A-Z])/, '\1_\2').
  15. downcase
  16. end
  17. end
  18. module Symbol
  19. def snake_case
  20. to_s.snake_case
  21. end
  22. end
  23. end
  24. # Schild hat teilweise nil in DB-Feldern. SchildTypeSaver gibt entweder einen
  25. # "Fehlt"-String zurück oder bei strftime das 1899 Datum zurück.
  26. module SchildTypeSaver
  27. Symbol.include CoreExtensions::Symbol
  28. String.include CoreExtensions::String
  29. # bei include wird für jede Spalte in der Schild-Tabelle eine Ersatzmethode
  30. # erstellt, die bei nil ein Null-Objekt erstellt.
  31. def self.included(klass)
  32. klass.columns.each do |column|
  33. name = column.snake_case
  34. define_method(name) { public_send(column) || Null.new("")}
  35. end
  36. end
  37. class Null < String
  38. def strftime(args)
  39. Time.new("1899").strftime(args)
  40. end
  41. end
  42. end
  43. # Das Schild Modul, das alle Klassen für die Datenbankanbindung bereitstellt
  44. module Schild
  45. # ist die Datenbank-Verbindung. Alle Daten können über diese Konstante abgerufen werden
  46. DB = Sequel.connect(:adapter=>ENV['S_ADAPTER'], :host=>ENV['S_HOST'], :user=>ENV['S_USER'], :password=>ENV['S_PASSWORD'], :database=>ENV['S_DB'])
  47. # Stellt eine Verbindung zu einem Schild-Server her. Sollte nur aufgerufen werden, wenn wechselnde Verbindungen nötig sind.
  48. def self.connect
  49. Sequel.connect(:adapter=>ENV['S_ADAPTER'], :host=>ENV['S_HOST'], :user=>ENV['S_USER'], :password=>ENV['S_PASSWORD'], :database=>ENV['S_DB'])
  50. end
  51. # Stellt die Schüler-Tabelle samt Assoziationen bereit.
  52. class Schueler < Sequel::Model(:schueler)
  53. include SchildTypeSaver
  54. many_to_one :fachklasse, :class => :Fachklasse, :key => :Fachklasse_ID
  55. one_to_many :abschnitte, :class => :Abschnitt
  56. # gibt das z.Zt. aktuelle Halbjahr zurück.
  57. def akt_halbjahr
  58. abschnitte.last
  59. end
  60. # gibt das erste Halbjahr von +jahr+ zurück.
  61. def erstes_halbjahr(jahr)
  62. halbjahr(jahr, 1)
  63. end
  64. # gibt das zweite Halbjahr von +jahr+ zurück.
  65. def zweites_halbjahr(jahr)
  66. halbjahr(jahr, 2)
  67. end
  68. # gibt aus +jahr+ das Halbjahr +1+ oder +2+ zurück.
  69. def halbjahr(jahr, abschnitt)
  70. abschnitte_dataset.where(:jahr => jahr, :abschnitt => abschnitt).first
  71. end
  72. # gibt +Herr+ oder +Frau+ als Anrede für Schüler zurück.
  73. def anrede
  74. if self.Geschlecht == 3
  75. return "Herr"
  76. elsif self.Geschlecht == 4
  77. return "Frau"
  78. end
  79. end
  80. # gibt +true+ zurück, wenn Schüler volljährig.
  81. def volljaehrig?
  82. self.Volljaehrig == "+"
  83. end
  84. # gibt das aktuelle Schuljahr als String im Format "2014/15" zurück.
  85. def schuljahr
  86. jahr = self.AktSchuljahr
  87. "#{jahr}/#{jahr-1999}"
  88. end
  89. end
  90. # Dient als Assoziation für Schüler und deren Klassenbezeichnung etc.
  91. class Fachklasse < Sequel::Model(:eigeneschule_fachklassen)
  92. include SchildTypeSaver
  93. one_to_one :schueler
  94. end
  95. # Assoziation für Lehrer, hauptsächlich für Klassenlehrer
  96. class Klassenlehrer < Sequel::Model(:k_lehrer)
  97. include SchildTypeSaver
  98. one_to_one :abschnitt, :primary_key=>:Kuerzel, :key=>:KlassenLehrer
  99. end
  100. # Ist die Assoziation, die Halbjahre, sog. Abschnitte zurückgibt.
  101. class Abschnitt < Sequel::Model(:schuelerlernabschnittsdaten)
  102. include SchildTypeSaver
  103. many_to_one :schueler, :class => :Schueler, :key => :Schueler_ID
  104. one_to_many :noten, :class => :Noten
  105. many_to_one :klassenlehrer, :class => :Klassenlehrer, :primary_key=>:Kuerzel, :key=>:KlassenLehrer
  106. dataset_module do
  107. # filtert den Datensatz nach Jahr
  108. def jahr(i)
  109. where(:Jahr => i)
  110. end
  111. # filtert den Datensatz nach Halbjahr
  112. def halbjahr(i,j)
  113. jahr(i).where(:Abschnitt => j)
  114. end
  115. # filtert und gibt den Datensatz als Abschnitt des aktuellen Halbjahrs zurück
  116. def akt_halbjahr
  117. halbjahr(Time.new.year-1, 1).first
  118. end
  119. end
  120. # Hilfsmethode für die folgenden Methoden
  121. def faecher_nach_id(id)
  122. noten.sort_by{ |n| n.fach.SortierungS2 }.select{ |n| n.fach.Fachgruppe_ID == id && n.AufZeugnis == '+' }
  123. end
  124. # wählt alle berufsübergreifenden Fächer des gewählten Schülers in angegeben Halbjahr.
  125. def berufsuebergreifend
  126. faecher_nach_id 10
  127. end
  128. # wählt alle berufsbezogenen Fächer des gewählten Schülers in angegeben Halbjahr.
  129. def berufsbezogen
  130. faecher_nach_id 20
  131. end
  132. # wählt alle Fächer des Differenzierungsbreichs des gewählten Schülers in angegeben Halbjahr.
  133. def differenzierungsbereich
  134. faecher_nach_id 30
  135. end
  136. # wählt alle Fächergruppen aus.
  137. def faechergruppen
  138. [berufsuebergreifend, berufsbezogen, differenzierungsbereich]
  139. end
  140. # gibt den Namen des Klassenlehrers mit gekürztem Vornamen.
  141. def v_name_klassenlehrer
  142. v = klassenlehrer.Vorname
  143. n = klassenlehrer.Nachname
  144. "#{v[0]}. #{n}"
  145. end
  146. # gibt "Klassenlehrer" entsprechend Geschlecht zurück
  147. def klassenlehrer_in
  148. klassenlehrer.Geschlecht == "3" ? "Klassenlehrer" : "Klassenlehrerin"
  149. end
  150. # gibt das aktuelle Schuljahr als String im Format "2014/15" zurück.
  151. def schuljahr
  152. jahr = self.Jahr
  153. "#{jahr}/#{jahr-1999}"
  154. end
  155. end
  156. # Assoziation für Noten
  157. class Noten < Sequel::Model(:schuelerleistungsdaten)
  158. include SchildTypeSaver
  159. many_to_one :abschnitt, :class => :Abschnitt, :key => :Abschnitt_ID
  160. many_to_one :fach, :class => :Faecher, :key => :Fach_ID
  161. # Notenbezeichnung als String
  162. def note
  163. case self.NotenKrz
  164. when "1"
  165. "sehr gut"
  166. when "2"
  167. "gut"
  168. when "3"
  169. "befriedigend"
  170. when "4"
  171. "ausreichend"
  172. when "5"
  173. "mangelhaft"
  174. when "6"
  175. "ungenügend"
  176. when 'NB'
  177. "----------"
  178. when 'E3'
  179. "teilgenommen"
  180. end
  181. end
  182. # Bezeichnung des Fachs
  183. def bezeichnung
  184. fach.Bezeichnung
  185. end
  186. # Die Fachgruppen ID des Fachs
  187. def fachgruppe_ID
  188. fach.Fachgruppe_ID
  189. end
  190. end
  191. # Assoziation für Fächer
  192. class Faecher < Sequel::Model(:eigeneschule_faecher)
  193. include SchildTypeSaver
  194. one_to_one :noten
  195. end
  196. # Schul-Tabelle mit vereinfachtem Zugriff auf Datenfelder.
  197. class Schule < Sequel::Model(:eigeneschule)
  198. include SchildTypeSaver
  199. # gibt die Schulnummer zurück
  200. def self.schulnummer
  201. self.first.SchulNr
  202. end
  203. def self.v_name_schulleiter
  204. "#{self.first.SchulleiterVorname[0]}. #{self.first.SchulleiterName}"
  205. end
  206. def self.schulleiter_in
  207. self.first.SchulleiterGeschlecht == 3 ? "Schulleiter" : "Schulleiterin"
  208. end
  209. def self.ort
  210. self.first.Ort
  211. end
  212. end
  213. end