Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
Bachelor Thesis
Hochschule HeilbronnStudiengang Software Engineering
ThemaAutomatisierte Erfassung statistischer Nutzungsdaten vonFacebook-Anwendungen mittels eines Gems fur Ruby on Rails
Klaus BreyerMatrikel-Nr.: 167 407
1. Prufer:2. Prufer:Betreuer:Firma:
Prof. Dr. Jorg WincklerProf. Dr. Alois HeinzOle Riesenbergbuddybrand GbRKopenicker Str. 15410997 Berlin
Vorgelegt am: 30.07.2010
Kurzfassung
Diese Arbeit handelt uber die Erstellung eines Gems fur Ruby on Rails zur auto-
matisierten Erfassung statistischer Nutzungsdaten von Facebook-Anwendungen. Ein-
leitend wird ein grober Uberblick uber Facebook als soziale Plattform und als Pro-
grammierschnittstelle gegeben. Zur besseren Orientierung wird eine Beispielanwen-
dung eingefuhrt, die den Leser durch die Thesis fuhrt.
Vorbereitend, zur Beschreibung der Implementierung und der Architektur, werden
die Anforderungen, die von der Firma buddybrand an den Gem gestellt werden,
erortert. Zum Abschluss der Arbeit, vor einer Zusammenfassung und einem Aus-
blick, wird erklart, wie der Gem sich in eine bestehende Anwendung integrieren und
erweitern lasst.
Aspekte der Metaprogrammierung von Ruby werden im Anhang ebenso beschrie-
ben, wie die Erweiterbarkeit von Ruby on Rails.
Schlagworter: Ruby, Ruby on Rails, Facebook, Gem, Metaprogrammierung, Sta-
tistik
Abstract
This work is about creating a Gem for Ruby on Rails for the automated collection
of statistical data from Facebook applications. First, a broad overview of Facebook
as a social platform and a programming interface is given.
In preparation, the requirements will be discussed regarding the needs of the com-
pany. Moreover, the main part of the work is about the Gem. The design and func-
tionality are described in the chapters about the architecture and implementation in
detail. To close the work, there is a chapter about the integration and enhancement
of the Gem in an application.
Aspects of Ruby metaprogramming are described during the appendix as well as
the extensibility of Ruby on Rails.
Keywords: Ruby, Ruby on Rails, Facebook, Gem, metaprogramming, statistical
data
Inhaltsverzeichnis Seite I
Inhaltsverzeichnis
Inhaltsverzeichnis I
Abbildungsverzeichnis VI
Tabellenverzeichnis VII
Listingverzeichnis VIII
Abkurzungsverzeichnis X
Vorwort XI
1. Uberblick 1
2. Ziele 3
3. Facebook als Plattform 4
3.1. Community-Features . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3.2. Anwendungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.3. Entwicklung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.3.1. Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3.2. FBML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.3.3. FBJS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3.4. REST-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.3.5. FQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3.6. Graph-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4. Beispielanwendung: Tetris-Gifts 13
4.1. Spielmechanik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.1.1. Startseite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.1.2. Absenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.1.3. Einladung annehmen . . . . . . . . . . . . . . . . . . . . . . . 15
4.1.4. Geschenk-Seite . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.1.5. Absenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.2. Serverseitige Realisierung . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.2.1. Datenbankmodell . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.2.2. Formulareingaben verarbeiten . . . . . . . . . . . . . . . . . . 21
4.3. Zu erfassende Daten . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Inhaltsverzeichnis Seite II
5. Anforderungen 23
5.1. Datenerfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.1.1. Seitenaufruf . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.1.2. Pinnwand-Veroffentlichungen . . . . . . . . . . . . . . . . . . 24
5.1.3. Gesendete Einladungen . . . . . . . . . . . . . . . . . . . . . . 25
5.1.4. Gesendete E-Mails . . . . . . . . . . . . . . . . . . . . . . . . 25
5.1.5. Gesendete Dashboard-Benachrichtigungen . . . . . . . . . . . 26
5.1.6. Gesetzte Dashboard-Counter . . . . . . . . . . . . . . . . . . . 26
5.1.7. Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.1.8. Deinstallation . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.1.9. Anwendungsspezifische Datenerfassung . . . . . . . . . . . . . 28
5.2. View-Helper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.3. Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.4. Kompatibilitat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.5. Lokaler Puffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.6. Ubertragung der Daten . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.6.1. Exaktheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.6.2. Eskalation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.6.3. Austauschbarkeit des Backends . . . . . . . . . . . . . . . . . 30
5.6.4. Redis-Backend . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.6.5. Alternative Backends . . . . . . . . . . . . . . . . . . . . . . . 31
5.7. Anonymisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.8. Fehlerbehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.8.1. Ausfall des Tracking-Servers . . . . . . . . . . . . . . . . . . . 32
5.8.2. Benachrichtigung per Hoptoad . . . . . . . . . . . . . . . . . . 33
5.8.3. Alternative Benachrichtigungen . . . . . . . . . . . . . . . . . 33
5.9. Konfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
6. Architektur 35
6.1. Implementierungsalternativen . . . . . . . . . . . . . . . . . . . . . . 35
6.1.1. RubyGem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6.1.2. Plugin fur Ruby on Rails . . . . . . . . . . . . . . . . . . . . . 36
6.1.3. REST-API oder Webservice . . . . . . . . . . . . . . . . . . . 36
6.1.4. Logdatei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
6.2. Wissensgewinnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.2.1. Zusatzliche Parameter . . . . . . . . . . . . . . . . . . . . . . 37
6.2.2. Parsen des Inhalts . . . . . . . . . . . . . . . . . . . . . . . . 38
6.2.3. Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Inhaltsverzeichnis Seite III
6.2.4. Wissensbibliothek . . . . . . . . . . . . . . . . . . . . . . . . . 38
7. Implementierung 39
7.1. Ordnerstruktur eines RubyGems . . . . . . . . . . . . . . . . . . . . . 39
7.2. Konfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.2.1. YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.2.2. Alternative Konfigurationsmoglichkeiten . . . . . . . . . . . . 40
7.3. Modularchitektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
7.3.1. Hit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.3.2. Custom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.3.3. Email-Extension . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.3.4. Restapi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.3.5. Buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
7.3.6. Backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
7.3.7. Helper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
7.3.8. Railtie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7.3.9. Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7.4. Fehlerbenachrichtigung . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.5. trackbuddy-redis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.5.1. Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.5.2. Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.5.3. Datenformat . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.6. Initialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.6.1. Railties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.6.2. Backend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.7. Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
8. Integration 60
8.1. Installation des Gems . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
8.2. Facebook-Einstellungen . . . . . . . . . . . . . . . . . . . . . . . . . . 61
8.3. Anpassung der Views . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
8.3.1. Setzen von Referrer-Parametern in Links . . . . . . . . . . . . 62
8.3.2. Callback-Aufruf bei manueller Pinnwand-Veroffentlichung . . . 62
9. Erweiterung 64
9.1. Erweiterung des Gems . . . . . . . . . . . . . . . . . . . . . . . . . . 64
9.1.1. Weiterer Gem mit Abhangigkeit . . . . . . . . . . . . . . . . . 64
9.1.2. Hooks und Handler . . . . . . . . . . . . . . . . . . . . . . . . 64
Inhaltsverzeichnis Seite IV
9.1.3. Fork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
9.2. Implementierung eines eigenen Backend-Moduls . . . . . . . . . . . . 65
10.Zusammenfassung und Ausblick 67
Lessons learned 68
Quellenverzeichnis 70
A. Protokolle 71
A.1. Meeting wegen Tracking-Anforderungen . . . . . . . . . . . . . . . . . 71
A.2. Review-Meeting Bachelor-Thesis . . . . . . . . . . . . . . . . . . . . . 72
B. trackbuddy 75
B.1. Erfasste Rohdaten innerhalb von Redis . . . . . . . . . . . . . . . . . 75
B.2. Beispiel-Auswertung der erfassten Daten . . . . . . . . . . . . . . . . 77
B.3. Gem-Spezifikation trackbuddy.gemspec . . . . . . . . . . . . . . . . . 82
B.4. Konfigurationsdatei trackbuddy.yml . . . . . . . . . . . . . . . . . . . 84
B.5. Anpassung einer Einladung . . . . . . . . . . . . . . . . . . . . . . . 84
B.6. Integration eines Callbacks bei manueller Pinnwand-Veroffentlichung . 85
C. Ruby 88
C.1. Metaprogrammierung in Ruby . . . . . . . . . . . . . . . . . . . . . . 88
C.1.1. Module einbeziehen . . . . . . . . . . . . . . . . . . . . . . . . 88
C.1.2. Methodenaufrufe als Parameter . . . . . . . . . . . . . . . . . 89
C.1.3. Behandlung fehlender Methoden . . . . . . . . . . . . . . . . . 90
C.1.4. Method-Chaining . . . . . . . . . . . . . . . . . . . . . . . . . 91
C.1.5. methods.include? . . . . . . . . . . . . . . . . . . . . . . . . . 92
C.1.6. Oberserver-Pattern . . . . . . . . . . . . . . . . . . . . . . . . 92
C.2. Schnittstellen von Rails . . . . . . . . . . . . . . . . . . . . . . . . . . 93
C.2.1. Rack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
C.2.2. Railties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
D. Redis-Benchmark 97
D.1. Programmcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
D.2. Ergebnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
E. Hoptoad 99
E.1. Oberflache mit aggregierten Fehlermeldungen . . . . . . . . . . . . . 99
E.2. Hoptoad-E-Mail mit Fehlermeldung . . . . . . . . . . . . . . . . . . . 99
Inhaltsverzeichnis Seite V
F. Internetmaterial 103
F.1. Facebook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
F.1.1. Graph-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
F.1.2. 500 Million Stories . . . . . . . . . . . . . . . . . . . . . . . . 103
F.1.3. Developer Principles & Policies . . . . . . . . . . . . . . . . . 103
F.1.4. Pages Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . 104
F.2. Ruby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
F.2.1. Jeweler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
F.2.2. Create Your Own Gem . . . . . . . . . . . . . . . . . . . . . . 104
F.2.3. DataMapper . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
F.2.4. Toadhopper . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
F.2.5. Redis-Gem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
F.3. Redis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
F.3.1. Befehlsreferenz . . . . . . . . . . . . . . . . . . . . . . . . . . 105
F.3.2. Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Eidesstattliche Erklarung 107
Abbildungsverzeichnis Seite VI
Abbildungsverzeichnis
1. Kommunikation von einem Benutzer mit einer Facebook-Anwendung 10
2. FBML-Element fb:multi-friend-selector (Anonymisiert) . . . . . . . . 11
3. Tetris-Gifts Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4. Abschicken einer Einladung von Tetris-Gifts . . . . . . . . . . . . . . 16
5. Darstellung einer Tetris-Gifts-Einladung . . . . . . . . . . . . . . . . 16
6. Geschenk-Seite von Tetris-Gifts . . . . . . . . . . . . . . . . . . . . . 17
7. E-Mail Benachrichtigung von Tetris-Gifts . . . . . . . . . . . . . . . . 18
8. FBJS-Popup mit Pinnwandveroffentlichung zu Tetris-Gifts . . . . . . 19
9. Dashboard-Counter zu Tetris-Gifts . . . . . . . . . . . . . . . . . . . 19
10. Dashboard-News zu Tetris-Gifts . . . . . . . . . . . . . . . . . . . . . 20
11. Datenbankmodell zu Tetris-Gifts . . . . . . . . . . . . . . . . . . . . 20
12. Zusammenspiel der aktiven Tracking-Komponenten . . . . . . . . . . 42
13. Erfassung von Requests mittels Middleware . . . . . . . . . . . . . . 44
14. Erfassung von Aufrufen der REST-API . . . . . . . . . . . . . . . . . 47
15. Eintrag fur Schlussel :request in Puffer . . . . . . . . . . . . . . . . . 48
16. Erfassung eines Seitenaufrufes mit Ubertragung auf Tracking-Server . 55
17. Initialisierung von trackbuddy . . . . . . . . . . . . . . . . . . . . . . 58
18. Post-Remove-Callback URL . . . . . . . . . . . . . . . . . . . . . . . 62
19. Statistik uber Seitenaufrufe . . . . . . . . . . . . . . . . . . . . . . . 78
20. Statistik uber Installationen, Deinstallationen, Veroffentlichungen, E-
Mails und Einladungen . . . . . . . . . . . . . . . . . . . . . . . . . 78
21. Anwendungsspezifische Datenerfassung von versendeten Nachrichten . 79
22. Statistik, welche E-Mails wie oft versendet wurden . . . . . . . . . . . 79
23. Statistik, uber welche viralen Kanale Benutzer wieder in die Anwen-
dung kommen (srcref-Parameter) . . . . . . . . . . . . . . . . . . . . 80
24. Statistik, welche Veroffentlichungen wie oft getatigt wurden . . . . . . 80
25. Statistik, uber welche Veroffentlichungen Benutzer wieder in die An-
wendung kommen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
26. Statistik, wie viele automatisierte und manuelle Veroffentlichungen
getatigt wurden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
27. Hoptoad-Oberflache (Fehlermeldungen wurden unkenntlich gemacht) 99
Tabellenverzeichnis Seite VII
Tabellenverzeichnis
1. Zu erfassende Daten der Beispielanwendung Tetris-Gifts . . . . . . . 22
2. Datenerhebung der verschiedenen Module . . . . . . . . . . . . . . . 43
3. Ergebnis vom Redis-Benchmark (Zeit in Sekunden) . . . . . . . . . . 57
Listingverzeichnis Seite VIII
Listingverzeichnis
1. POST-Parameter in Facebook-Request . . . . . . . . . . . . . . . . . 9
2. Ubersetzter FBML-Code mit HTML-Attribut “id” . . . . . . . . . . 10
3. FBML-Tag “fb:profile-pic” zur Anzeige eines Benutzerbildes . . . . . 10
4. Ergebnis der Graph-API fur “klausbreyer” ohne Access-Token . . . . 12
5. Anwendungsspezifische Datenerfassung fur Beispiel “sentgift” . . . . . 28
6. Einladungslink mit Referrer-Argument . . . . . . . . . . . . . . . . . 28
7. Minimalbeispiel fur trackbuddy-Gem-Ordnerstruktur . . . . . . . . . 39
8. Aufruf des Puffers fur das Zahlen einer Installation . . . . . . . . . . 48
9. Moglichkeit fur alternative Syntax zum Eintrag in Puffer . . . . . . . 49
10. Helper-Methode mit Template “trackingcallback” . . . . . . . . . . . 50
11. Anwendung der View-Helper zur URL-Generierung . . . . . . . . . . 50
12. Mogliche Alternative zur URL-Generierung . . . . . . . . . . . . . . . 51
13. Verworfene Alternative zur URL-Generierung . . . . . . . . . . . . . 51
14. Einbindung der Helper . . . . . . . . . . . . . . . . . . . . . . . . . . 51
15. Alternative Syntax fur Einbindung der Helper . . . . . . . . . . . . . 52
16. Toadhopper-Schnittstelle (Quelle: Anhang F.2.4) . . . . . . . . . . . . 54
17. Generierung des Tracking-Namespaces . . . . . . . . . . . . . . . . . 54
18. Redis-Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
19. Ordnerstruktur fur Rails Generator . . . . . . . . . . . . . . . . . . . 59
20. Zusatzliche Eintrage in Gemfile mit Eintrag fur trackbuddy . . . . . . 60
21. Generierung der Konfiguration . . . . . . . . . . . . . . . . . . . . . . 61
22. Gerust fur weiteres Backend-Modul . . . . . . . . . . . . . . . . . . . 66
23. Redis-Rohdaten fur Schlussel “impression” . . . . . . . . . . . . . . . 75
24. Redis-Rohdaten fur Schlussel “install” . . . . . . . . . . . . . . . . . 76
25. Redis-Rohdaten fur Schlussel “uninstall” . . . . . . . . . . . . . . . . 76
26. Redis-Rohdaten fur Schlussel “custom” . . . . . . . . . . . . . . . . . 76
27. Redis-Rohdaten fur Schlussel “email” . . . . . . . . . . . . . . . . . . 76
28. Redis-Rohdaten fur Schlussel “publish” . . . . . . . . . . . . . . . . . 76
29. Redis-Rohdaten fur Schlussel “invite” . . . . . . . . . . . . . . . . . . 76
30. Redis-Rohdaten fur Schlussel “dashboardnews” . . . . . . . . . . . . 76
31. Redis-Rohdaten fur Schlussel “dashboardcounter” . . . . . . . . . . . 76
32. trackbuddy.gemspec . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
33. Konfigurationsdatei fur trackbuddy in YAML-Notation . . . . . . . . 84
34. FBML-Code einer Einladung vor Anpassung . . . . . . . . . . . . . . 84
35. FBML-Code einer Einladung nach der Anpassung . . . . . . . . . . . 85
36. Geparster FBML-Code einer Einladung . . . . . . . . . . . . . . . . . 85
Listingverzeichnis Seite IX
37. FBJS-Code einer Veroffentlichung vor der Anpassung . . . . . . . . . 85
38. FBJS-Code einer Pinnwand-Veroffentlichung nach der Anpassung . . 86
39. Geparster FBJS-Code einer Pinnwand-Veroffentlichung . . . . . . . . 87
40. Einbeziehen eines Moduls mit include . . . . . . . . . . . . . . . . . . 88
41. Einbeziehen eines Moduls mit extend . . . . . . . . . . . . . . . . . . 89
42. Send-Methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
43. Einbindung mittels send-Methode . . . . . . . . . . . . . . . . . . . . 90
44. Definiertes Verhalten bei nicht vorhandener Methode . . . . . . . . . 90
45. Method Chaining in Ruby . . . . . . . . . . . . . . . . . . . . . . . . 91
46. Uberprufung auf vorhandene Methode . . . . . . . . . . . . . . . . . 92
47. Observer Pattern in Ruby . . . . . . . . . . . . . . . . . . . . . . . . 93
48. Middleware-Komponenten mittels “rake middleware” . . . . . . . . . 94
49. Implementierung einer Middleware-Klasse . . . . . . . . . . . . . . . 95
50. Verfugbarmachen einer Middleware-Komponente mittels Railtie . . . 96
51. Programmcode des Redis-Benchmarks . . . . . . . . . . . . . . . . . 97
52. Ergebnis des Redis-Benchmarks . . . . . . . . . . . . . . . . . . . . . 98
Abkurzungsverzeichnis Seite X
Abkurzungsverzeichnis
API Application Programming Interface
DHCP Dynamic Host Configuration Protocol
DOM Document Object Model
DRY don’t repeat yourself
DSL Domain Specific Language
FBJS Facebook Javascript
FBML Facebook Markup Language
FQL Facebook Query Language
JSON Javascript Object Notation
MD5 Message-Digest Algorithm 5
MTA Mail Transfer Agent
Rails Ruby on Rails
RAKE Ruby Make
RDBMS Relational Database Management System
REST Representational State Transfer
SDK Software Development Kit
SNMP Simple Network Management Protocol
SSH Secure Shell
URI Uniform Resource Identifier
URL Uniform Resource Locator
VPN Virtual Private Network
XMPP Extensible Messaging and Presence Protocol
YAML YAML Ain’t Markup Language
Vorwort Seite XI
Vorwort
Diese Bachelor-Thesis handelt von einem Gem fur Facebook-Anwendungen auf Ba-
sis von Ruby on Rails. Jede Anwendung, die durch diesen Gem erweitert wird, soll
automatisch statistische Nutzungsdaten erfassen. Der Prozess der Entwicklung be-
ginnt mit der Erfassung der Anforderungen und endet nach der Programmierung
mit der Beschreibung des Ergebnisses.
Benotigt und angetrieben wird die Entwicklung von der buddybrand GbR in Berlin.
Tagesgeschaft bei buddybrand ist das Konzipieren, Entwickeln und Vermarkten vi-
raler Facebook-Anwendungen fur große Markenunternehmen.
Dieses Dokument ist zwischen Marz 2010 und Juli 2010 entstanden.
1 Uberblick Seite 1
1. Uberblick
Fur Anwendungen, die bei buddybrand erstellt werden, wird eine eigenstandige sta-
tistische Erfassung von Nutzerdaten benotigt. Bis jetzt wurde auf externe Tools, wie
sie von Facebook bereit gestellt werden, oder auf Google Analytics
(http://www.google.com/intl/de/analytics/) gesetzt. Google Analytics ist nicht
auf die speziellen Anforderungen von Anwendungen innerhalb Facebooks optimiert.
Die viralen Aspekte, wie sie bei Facebook-Anwendungen zu Tage treten, werden
nicht berucksichtigt. Die Effektivitat von Marketingkanalen, wie Einladungen oder
Pinnwand-Veroffentlichungen, kann uber Google Analytics nicht nachverfolgt wer-
den. Facebook selbst liefert auch Statistiken von Anwendungen aus, dabei kann
jedoch die Richtigkeit und Genauigkeit der Angaben nicht uberpruft werden. Hier-
bei wird auch keine Transparenz geboten, was die Haufigkeit der Aktualisierung oder
das Alter der erfassten Daten anbelangt. Statistiken von Facebook konnen uber ei-
ne Weboberflache aus der Anwendungskonfiguration heraus eingesehen werden. Des
Weiteren bietet Facebook auch die Moglichkeit, Statistiken mittels der Graph-API
zu beziehen (Anhang F.1.1).
Diese beiden externen Losungen erfordern ein manuelles Erfassen und Verarbei-
ten der Daten, ebenso mussen die fur den Kunden bestimmten Berichte von Hand
angefertigt werden. Sowohl die Facebook als auch Google Analytics bieten keine
Schnittstelle fur automatisierten Zugriff von außen auf die statistischen Daten. So
konnen diese nicht fur Reporting-Zwecke verwendet werden. Aus diesem Grund wird
mit dem zu entwickelnden Gem der Ansatz verfolgt, moglichst authentische Daten
direkt aus den Anwendungen zu generieren und lokal in der Firma auf Abruf zu
halten.
Ein auf Facebook optimiertes Tracking bietet der kommerzielle Anbieter Kontagent
(http://www.kontagent.com/). Kontagent bietet Programmbibliotheken fur Ruby,
PHP und .NET. Die Anbindung der fur Ruby bereitgestellten Bibliothek, in Form
eines RubyGems, hat sich in der Praxis als sehr umstandlich erwiesen. Auch hier
konnen die erfassten Daten lediglich in Graphen angezeigt, aber nicht weiterverar-
beitet werden.
Als Thema fur die Bachelor-Thesis wurde ein Gem fur Anwendungen in Ruby on
Rails (im Folgenden lediglich “Rails” genannt) gewahlt, welches eben eine solche
statistische Erfassung durchfuhrt und die erfassten Daten an einen Tracking-Server
ubertragt. Der Entwicklungsname fur den Gem lautet trackbuddy.
Nach der Zielsetzung dieser Bachelor-Thesis im folgenden Kapitel 2 zu Beginn des
Dokuments wird in Kapitel 3 eine Einfuhrung zu der Facebook-Plattform gegeben.
1 Uberblick Seite 2
Dabei werden die nativen Features, die sich dem Endbenutzer prasentieren, ebenso
erwahnt, wie die Eignung und besonderen Merkmale von Facebook als Programmier-
plattform. Eine Beispielanwendung, die den Benutzer durch die Thesis fuhrt, wird
in Kapitel 4 eingefuhrt. Kapitel 5 nimmt Bezug auf die Anforderungen, die von
der Firma an den Gem gestellt werden, aber auch darauf, welche Aspekte aus wel-
chem Grund bewusst nicht realisiert werden. Vorbereitend auf den Kernteil der
Arbeit wird in Kapitel 6 ein Uberblick uber die Architektur gegeben. Dabei wer-
den Alternativen diskutiert und Entscheidungen begrundet. Anschließend behandelt
Kapitel 7 als Kernteil die Implementierung des Gems in Ruby. In Kapitel 8 wird die
Integration des Gems in eine bestehende Anwendung, begonnen von der Installa-
tion bis hin zur Programmierung eines alternativen Backends beschrieben. Vor der
abschließenden Zusammenfassung in Kapitel 10 bietet Kapitel 9 eine Ubersicht, wie
der Gem erweitert werden kann.
Wird im Text der Arbeit Bezug auf eine Internetquelle mit weiteren Informationen
genommen, so ist ein Verweis auf den entsprechenden Eintrag im Anhang zu finden.
Ausfuhrungen zu Metaprogrammierung in Ruby und der Erweiterung von Rails sind
ebenso im Anhang wie Gesprachsprotokolle und Internetquellen.
2 Ziele Seite 3
2. Ziele
Ziel dieser Bachelor-Thesis ist es, einen Gem fur Ruby on Rails zu entwickeln, welcher
in folgende Teilaspekte unterteilt werden kann:
• Grundgerust und Konfigurationsmodul
• Modul fur das Erfassen von Aktionen der Anwendung
• Rack-Middleware fur das Erfassen der Zugriffsquellen
• Lokaler Puffer
• Kommunikation mit Backend zur Datenubermittlung
• Rails-Helper
Der Gem soll kompatibel zu Rails 3 sowie den Ruby Versionen 1.8 und 1.9 sein.
Ruby on Rails wurde unter den Pramissen Convention over configuration und don’t
repeat yourself (DRY) entwickelt. Dies bedeutet, dass moglichst viele Informatio-
nen aus dem Kontext bezogen werden sollen (Ruby u. a., 2009, S. 2). Unter dieser
Zielsetzung wird auch dieser Gem entwickelt, welcher moglichst universell einsetz-
bar sein soll. Der Aufwand, eine Anwendung durch Konfiguration oder zusatzliche
Methodenaufrufen anzupassen, soll auf ein Minimum reduziert werden.
3 Facebook als Plattform Seite 4
3. Facebook als Plattform
Facebook ist zum Zeitpunkt, als diese Thesis geschrieben wird, das großte sozia-
le Netzwerk weltweit. Im Juli 2010 zahlt die Facebook-Community mehr als 500
Millionen aktive Nutzer (Anhang F.1.2). In diesem Kapitel werden die Features
von Facebook erlautert. Im Speziellen werden Anwendungen auf Facebook erklart,
denen, neben der Entwicklung fur Facebook, auch jeweils ein eigenes Unterkapitel
gewidmet ist.
3.1. Community-Features
Facebook ist eine soziale Plattform die es erlaubt, mit Freunden und Bekannten in
Kontakt zu bleiben und neue Menschen kennenzulernen. Im Folgenden werden die
Features, die Facebook bietet, naher vorgestellt.
Startseite Die Startseite von Facebook bietet aggregierte Informationen uber die
Aktivitaten befreundeter Benutzer in naher Vergangenheit. Dargestellt werden fol-
gende Tatigkeiten:
• Neu hochgeladene Fotos
• Neue Freundschaften von Freunden
• Pinnwand-Eintrage
• Beitritte zu Gruppen
• “Gefallt mir” - Markierung von Seiten
• Anwendungsmeldungen
Jede Aktivitat aus dem Freundeskreis kann mit einem Kommentar versehen wer-
den. Auch kann jede Aktivitat mit einem “Gefallt mir” versehen werden, womit ein
Nutzer Interesse kennzeichnen kann.
Profil Das Profil bietet eine Ubersicht uber die Aktionen eines Benutzers und des-
sen im Profil hinterlegte Daten. Hauptmerkmal eines Profils ist die eigene Pinnwand
des Benutzers. Dort konnen andere Benutzer Beitrage und kleine Nachrichten hin-
terlassen, die direkt an den Benutzer adressiert sind. Neben den Pinnwand-Beitragen
gibt es auch eine Ubersicht uber die letzten Aktivitaten des Benutzers.
Ein Reiter auf der Profilseite bietet personliche Informationen in Form von Kon-
taktdaten, Informationen zu Ausbildung und Beruf, Gruppenmitgliedschaften sowie
3 Facebook als Plattform Seite 5
Seiten, die dem Nutzer gefallen. Ein anderer Reiter fuhrt zu Fotoalben, welche der
Benutzer selbst erstellen kann. Weitere Reiter konnen durch Facebook-Anwendungen
von einem Benutzer zu seinem Profil hinzugefugt werden.
Unabhangig von der momentan aufgerufenen Profilfunktion bietet das Profil jeder-
zeit ein aktuelles Profilbild, sofern hochgeladen, sowie die Anzeige der Freunde des
Benutzers.
Privatsphare Samtliche im Profil angegebenen Informationen konnen in ihrer Sicht-
barkeit eingeschrankt werden. Dabei gibt es folgende Abstufungen der Sichtbarkeit:
• Alle
• Freunde und Netzwerke
• Freunde von Freunden
• Nur Freunde
• Benutzerdefiniert
Bei der benutzerdefinierten Angabe der Sichtbarkeit konnen einzelne Freunde ein-
bezogen oder ausgeschlossen werden.
Freundesliste Jeder Benutzer hat eine Freundesliste, welche auf seinem Profil ein-
gesehen werden kann. Bevor eine Freundschaft zwischen zwei Personen zustande
kommt, muss eine Freundschaftsanfrage gestellt werden. Diese muss, je nach Ein-
stellung des Angefragten, angenommen werden.
Netzwerke Netzwerke bilden die Zugehorigkeit zu einer Institution ab. Dies kann
eine Hochschule oder ein Arbeitsplatz sein. Ein Benutzer kann maximal 5 Netz-
werken beitreten. Wenn ein Netzwerk nicht vorhanden ist, kann ein Neues erstellt
werden.
Gruppen Gruppen dienen als Diskussionsforen. Sie bilden sich um eine bestimmte
Thematik, beispielsweise einer Programmiersprache. Ein Benutzer kann einer Grup-
pe beitreten, wenn er sich fur diese Thematik interessiert.
Seiten Seiten in Facebook handeln im Allgemeinen von Unternehmen, Kunstlern,
Produkten und Prominenten. Erstellt werden die Seiten von Fans, Agenturen, offi-
ziellen Vertreten oder den Beteiligten selbst. Seiten sind grundsatzlich nicht be-
schrankt, jeder Benutzer kann eine Seite zu einem Thema seiner Wahl erstellen. Ein-
geschrankt wird das lediglich durch Richtlinien von Facebook (Anhang F.1.4). Wenn
3 Facebook als Plattform Seite 6
Benutzern eine Seite gefallt, so kann die Sympathie mittels des Buttons “Gefallt mir”
ausgedruckt werden. Andere Benutzer sehen dies dann auf der eigenen Startseite.
Dabei wird ihnen auch die Moglichkeit angeboten, selbst durch ein “Gefallt mir” zu
einem Unterstutzer der Seite zu werden.
Chat Der Chat von Facebook ist standig in minimierter Form am unteren Rand des
Browsers dargestellt. Es kann ausschließlich mit anderen Benutzern gechattet wer-
den, die ebenfalls gerade in Facebook eingeloggt und befreundet sind. Die Moglich-
keit besteht, auch außerhalb von Facebook mittels XMPP (Extensible Messaging
and Presence Protocol) auf den Chat zuzugreifen.
Dashboard Fur Spiele und Anwendungen in Facebook gibt es das sogenannte
Dashboard, welches Informationen aus Spielen und Anwendungen aufbereitet. An-
wendungen konnen an das Dashboard eines Benutzers Neuigkeiten senden, wenn
z.B. im Spiel eine Aktion geschehen ist, welche das Reagieren von einem Benutzer
erwartet. Diese Art der Kommunikation wird Dashboard-Notifications genannt.
Als Erganzung gibt es sogenannte Dashboard-Counter. Diese Elemente zeigen,
ahnlich wie in einem E-Mail-Programm, die Anzahl neuer Aktionen als Zahl in ei-
ner Klammer hinter dem Lesezeichen fur die jeweilige Anwendung.
Beispiele fur diese beiden Elemente finden sich in der Beschreibung der Beispielan-
wendung, die fur diese Thesis erstellt wurde, in Kapitel 4.1.5.
3.2. Anwendungen
Facebook bietet eine Schnittstelle fur externe Programmierer. Diese erlaubt es, An-
wendungen innerhalb von Facebook zu programmieren. Die Großzahl der momen-
tan verfugbaren Anwendungen sind Spiele. Die Daten des Benutzers verbleiben bei
Facebook. Diese werden von Facebook erst bei der Auslieferung der Anwendung
eingesetzt. Bei der Installation kann eine Anwendung zusatzliche Genehmigungen
einholen, um beispielsweise auf Fotoalben zuzugreifen.
Die Anzahl der Variationen von Anwendungen ist groß. Von voll implementierten
Spielemechaniken bis hin zu einer simplen Veroffentlichung eines zufallig ausgewahl-
ten Spruches auf der Pinnwand von einem Benutzer bietet sich eine große Auswahl.
Richtlinien Bei der Entwicklung einer Anwendung verpflichtet sich der Entwickler
gewisse Richtlinien zu beachten (Anhang F.1.3). Unter anderem darf die Anwendung
keinen Spam verschicken und muss sich in einigen Punkten so verhalten, wie es ein
Benutzer von Facebook erwarten wurde.
3 Facebook als Plattform Seite 7
Verbreitung Die meisten Anwendungen sind darauf ausgelegt, dass sie sich uber
virale Aspekte von selbst verbreiten. Viral bedeutet, dass die Anwendung von den
Benutzern so verwendet werden soll, dass sie nach außen hin moglichst sichtbar
ist. Durch soziale Faktoren wie Gruppenzwang sollen moglichst viele Freunde von
Benutzern in die Anwendung gelangen. Auch kann dies dadurch geschehen, dass der
Benutzer einen Vorteil innerhalb eines Spieles erlangt, wenn er neue Benutzer in die
Anwendung einladt.
Eine solche Verbreitung wird deshalb viral genannt, da sie wie ein Virus viele weitere
Nutzer infizieren kann.
Monetarisierung Anwendungen konnen dem Entwickler auf mehrere Arten Geld
einbringen:
• Monetarisierung durch Werbung auf eine speziell zugeschnittene Zielgruppe
• Virtuelle Wahrungen
• Agenturgeschaft fur Markenunternehmen
Facebook-Anwendungen finden bei Markenunternehmen steigende Akzeptanz um
anstelle von klassischer Werbung ihre Kunden zu erreichen. Durch ein Spiel beschaf-
tigt sich ein einzelner Benutzer langer und intensiver mit einer Marke, als mit einem
kurzen Werbespot.
3.3. Entwicklung
Die fur Facebook entwickelten Anwendungen werden auf den Servern des jeweiligen
Anbieters betrieben. Diese Server liefern Code aus, welcher von Facebook angefor-
dert und anschließend an den Kunden ausgeliefert wird.
Dies bedeutet auch, dass zur Entwicklung von Facebook-Anwendungen der Entwick-
ler jederzeit online sein muss, damit Facebook auf seine Entwicklungsumgebung zu-
greifen kann. Um dies auch in Internet-Cafes oder in großen Firmen zu gewahrleisten
wird mit SSH-Tunneln gearbeitet. Beschrieben wird diese Methode im Kontext von
Facebook-Anwendungen durch Mangino (2008, S. 10). Eine Alternative fur Entwick-
ler zu SSH-Tunneln ist, mittels Router-Einstellungen Ports weiterzuleiten. Hierbei
muss auch die IP, die der Entwickler nach Außen hin bekommt, in den Einstellungen
von Facebook aktualisiert werden, wenn diese wechselt. Weitere Moglichkeiten sind,
sich in ein VPN einzuwahlen oder eine statische IP zu benutzen. Dies ist aber im
professionellen Umfeld wegen der großen Anzahl an Arbeitsplatzen nicht praktika-
bel. Ein zusatzliches Hindernis konnen auch die wechselnden lokalen IP-Adressen
3 Facebook als Plattform Seite 8
darstellen, wenn diese per Dynamic Host Configuration Protocol (DHCP) vergeben
werden. Bei SSH-Tunnelung indes beschrankt sich der Konfigurationsaufwand ledig-
lich auf die eigene Entwicklungsumgebung.
Es gibt zwei grundsatzliche Moglichkeiten wie Anwendungen mit Facebook kom-
munizieren konnen. Diese werden in den folgenden Absatzen verglichen.
FBML-Code auf Leinwand Von dem Anwendungsserver wird spezieller FBML-
Code ausgeliefert. FBML steht fur Facebook-Markup-Language und wird in Kapitel
3.3.2 naher erlautert. Dieser Code beinhaltet FBML-Tags, welche anschließend von
Facebook verarbeitet werden. Jede Anwendung hat eine sogenannte Leinwand, das
sogenannte Canvas, welche den ubersetzten FBML-Code darstellt. Diese Art von
Anwendungen integriert sich luckenlos in Facebook. Durch FBML werden die Ele-
mente benutzt, die der Benutzer bereits von Facebook kennt. Wenn eine Anwendung,
die neu erstellt wird, sich luckenlos in Facebook integrieren soll empfiehlt sich diese
Methode.
Anwendung in Iframe Die Anwendung kann auch mittels normalem HTML-Code
beschrieben werden. Das Ergebnis wird von Facebook auf der Anwendungsseite in-
nerhalb eines Iframes angezeigt. Die Verbindung zu Facebook findet statt, indem
auf Facebook-Connect zuruckgegriffen wird. Bei Facebook-Connect handelt es sich
um ein Javascript-SDK (Software Development Kit), welches die Verbindung zu
Facebook handhabt. Dieses Vorhaben empfiehlt sich, wenn eine Website, die bereits
vorher existierte, an Facebook angebunden und integriert werden soll. Die Mechanik
und der serverseitige Programmcode konnen beibehalten werden. Zur Authentifizie-
rung und Sichtbarkeit der Anwendung muss lediglich uber Facebook-Connect die
Anbindung zu Facebook realisiert werden. Eine Einfuhrung zu Facebook-Connect
bietet Mangino (2008, S. 150-154).
3.3.1. Request
Jeder Request der von Facebook an den Laufzeitserver gestellt wird ist ein HTTP-
POST-Request. Von welchem Typ der Request ursprunglich war, wird in dem Para-
meter method festgehalten. Als zusatzliche Argumente des Requests schickt Face-
book Sitzungsinformationen zu dem momentanen Benutzer und der Anwendung mit.
Parameter, neben denen der Anwendung, die von Facebook generiert werden haben
das Prafix fb . In erster Linie sind von den automatisch generierten Parametern vor
allem die Facebook-ID des Benutzers sowie die ID der Anwendung von Interesse.
3 Facebook als Plattform Seite 9
Parameters : {” method”=>”GET” ,
” f b s i g a p p i d ”=>” 352575023427 ” ,
” f b s i g r e que s t me tho d ”=>”GET” ,
” f b s i g l o c a l e ”=>”de DE” ,
” id ”=>”13955” ,
” f b s i g i n c a n v a s ”=>”1” ,
” f b s i g i n n e w f a c e b o o k ”=>”1” ,
” f b s i g ”=>” eba12445699007c9e906b4f694d8ae71 ” ,
” f b s i g f r i e n d s ”=>” [FILTERED] ” ,
” f b s i g a d d e d ”=>”1” ,
” f b s i g e x p i r e s ”=>” 1270026000 ” ,
” f b s i g s e s s i o n k e y ”=>” 2 .66hWJKxKrWLVNwhRXdWCx” ,
” f b s i g e x t p e r m s ”=>” status update , photo upload [ . . ] ”
,
” f b s i g a p i k e y ”=>”060 c9655436726c655c193f95c5512e9 ”
,
” f b s i g t i m e ”=>” 1270019752.0794 ” ,
” f b s i g p r o f i l e u p d a t e t i m e ”=>” 1268998234 ” ,
” f b s i g u s e r ”=>” 100000901054792 ”
” c o n t r o l l e r ”=>” takes ” ,
” ac t i on ”=>”show” ,
” q u i z i d ”=>”5” ,
}Listing 1: POST-Parameter in Facebook-Request
3.3.2. FBML
FBML, die Facebook Markup Language, ist ein von Facebook entwickelter Dialekt
von HTML. FBML bietet Tags um komplexe Facebook-Elemente wie z.B. Dialoge
zur Freundesauswahl anzuzeigen. Facebook ubersetzt das FBML einer Anwendung
unter Berucksichtigung einiger Sicherheitsaspekte in HTML, welches ausgeliefert
wird (Abbildung 1). FBML-Code einer Anwendung kann nur die Leinwand der An-
wendung manipulieren, da er in einem eigenen Namespace ausgefuhrt wird. Der Na-
mespace wird realisiert, indem Facebook samtlichen IDs und Klassen der CSS-Datei
und im ausgelieferten HTML-Code einen Bezeichner der Anwendung voranstellt.
3 Facebook als Plattform Seite 10
Abbildung 1: Kommunikation von einem Benutzer mit einer Facebook-Anwendung
<div id=” app192978304867 footer ”>
Listing 2: Ubersetzter FBML-Code mit HTML-Attribut “id”
Oft benutzte Elemente von FBML sind beispielsweise Tags, um den Benutzernamen
oder das Profilbild eines Benutzers zugehorig zu seiner Facebook-ID anzuzeigen,
aber auch Interface-Elemente wie eine Auswahlbox um Freunde in die Anwendung
einzuladen.
<fb : p r o f i l e p i c uid=”1” l i nked=” f a l s e ” s i z e=”normal” />
Listing 3: FBML-Tag “fb:profile-pic” zur Anzeige eines Benutzerbildes
3.3.3. FBJS
Als Erganzung zu FBML existiert FBJS, das so genannte Facebook Javascript, ein
Framework in Javascript, welches Zugriff auf interaktive Elemente von Facebook
erlaubt. Es gibt beispielsweise den Dialog zur Auswahl von Freunden, wie in Abbil-
dung 2 dargestellt.
3 Facebook als Plattform Seite 11
Abbildung 2: FBML-Element fb:multi-friend-selector (Anonymisiert)
Um normales Javascript in Facebook-Anwendungen zu verwenden, mussen eini-
ge Anpassungen vorgenommen werden. Um auf die Eigenschaften der Elemente
des Document-Object-Models (DOM) zuzugreifen sind spezielle Methoden, die das
FBJS-Framework von Facebook abkapselt, notwendig. Facebook verhindert auf diese
Weise, dass eine Anwendung mittels Javascript auf Elemente außerhalb der eigenen
Leinwand zugreifen kann.
3.3.4. REST-API
Uber einen Zugriff per REST (Representational State Transfer) kann auch auf die
Facebook-API (Application Programming Interface) zugegriffen werden. Die REST-
API bietet beispielsweise die Moglichkeit, auf Pinnwanden von Benutzern Beitrage
zu veroffentlichen.
3 Facebook als Plattform Seite 12
Die REST-API kann auch per FBJS abgefragt werden. Dies ist eine Moglichkeit,
um auch in Flash-Anwendungen vollen Zugriff auf Facebook zu bekommen.
3.3.5. FQL
Uber die REST-API konnen auch Anfragen in einer Sprache, die sehr ahnlich zu SQL
ist, gestellt werden. Der Dialekt, den Facebook fur diesen Anwendungszweck bereit-
stellt, wird FQL (Facebook Query Language) genannt. Dieser bietet ein Interface fur
virtuelle Tabellen, welche Informationen zu Benutzern (Vorname, Nachname, etc.)
aber auch fur Fanseiten enthalten. Auf diesem Wege konnen Daten im Klartext in
die Anwendung geladen werden.
3.3.6. Graph-API
Am 21. April 2010 wurde es die sogenannte Graph-API eingefuhrt. Hiermit ist es
einfacher moglich, auf Nutzerdaten zuzugreifen. Es reicht dabei aus die Adresse
https://graph.facebook.com/ mit darauf folgender eindeutiger ID aufzurufen.
Ergebnis der Anfrage ist ein JSON-String (Javascript Object Notation) mit Infor-
mationen zu dem angeforderten Element. Jede Seite, jedes Event und jeder Nut-
zer hat eine eigene eindeutige ID oder einen Bezeichner aus Buchstaben. Fur das
Profil mit dem Bezeichner “klausbreyer” kann ein JSON-String unter der Adresse
https://graph.facebook.com/klausbreyer abgerufen werden.
{” id ” : ” 707892557 ” ,
”name” : ”Klaus Breyer ” ,
” f i r s t n a m e ” : ”Klaus” ,
” last name ” : ” Breyer ” ,
” l i n k ” : ” http ://www. facebook . com/ k lausbr eye r ” ,
” gender ” : ”m\u00e4nnl i ch ” ,
” l o c a l e ” : ”de DE”
}
Listing 4: Ergebnis der Graph-API fur “klausbreyer” ohne Access-Token
Hat sich eine Anwendung mittels dem Protokoll O-Auth 2.0
http://oauth.net/ gegenuber Facebook authentifziert, kann als weiterer Parame-
ter ein Access-Token ubergeben werden. Facebook liefert dann alle weitere Daten zu
dem angeforderten Element, die die sich so authentifzierende Anwendung einsehen
kann. Weitere Informationen zu der Graph-API finden sich in Anhang F.1.1.
4 Beispielanwendung: Tetris-Gifts Seite 13
4. Beispielanwendung: Tetris-Gifts
Mit der Beispielanwendung Tetris-Gifts soll der Leser durch dieses Dokument gefuhrt
werden. Dieses Spiel bildet in Facebook eine einfache Mechanik ab, bei der alle
von trackbuddy zu erfassenden Aspekte berucksichtigt werden. In diesem Kapitel
wird erlautert, welche Aspekte bei welcher Mechanik ausgelost werden. In dem Spiel
Tetris-Gifts geht es um Geschenke in Form von Bausteinen des Spiels “Tetris”. Es
kann ein Baustein ausgewahlt, eine Nachricht hinterlassen sowie ein Freund aus-
gewahlt werden, der ein Geschenk erhalten soll. Dieser wird anschließend durch eine
Veroffentlichung auf seiner Pinnwand und einer Einladung in die Anwendung darauf
aufmerksam gemacht.
Die Anwendung ist unter der Adresse http://apps.facebook.com/tetrisgifts zu
erreichen. Fur diese Dokumentation der Anwendung wurde ein Test-Account, wel-
cher im Vorfeld angelegt wurde, namens Klaus Erde benutzt, um die verschiedenen
Rollen kenntlich zu machen.
4.1. Spielmechanik
Das Spiel hat zwei FBML-Views:
• Die Startseite mit Auswahl von Geschenk und Freund sowie den erhaltenen
Geschenken.
• Die Detailansicht des Geschenks, welche der Beschenkte aufruft.
4.1.1. Startseite
Die Startseite dient dem Versenden von Geschenken. Des Weiteren bietet sie eine
Ubersicht uber erhaltene Geschenke und lasst den Spielern der Anwendung erwei-
terte Berechtigungen geben.
Im Folgenden werden die nummerierten Punkte der Abbildung 3 erlautert.
1 Der Spieler wahlt einen Tetris-Stein aus, den er verschenken mochte.
2 Anschließend kann er dem Freund, den er beschenken mochte, eine Nachricht
hinterlassen.
4 Beispielanwendung: Tetris-Gifts Seite 14
Abbildung 3: Tetris-Gifts Index
4 Beispielanwendung: Tetris-Gifts Seite 15
3 Das FBML-Element fb:multi-friend-selector zeigt alle Freunde des Benut-
zers an. Hieraus kann er einen Freund wahlen. Generell lasst dieses Element eine
mehrfache Auswahl von Freunden zu. Um die Anwendung simpel zu halten, wurde
die Auswahl auf einen Freund begrenzt. Ein in einem Multi-Friend-Selector aus-
gewahlter Freund erhalt eine Einladung in die Anwendung hinein.
4 Wurde ein Freund ausgewahlt, kann das Formular abgeschickt werden.
5 Fur mehr Bequemlichkeit kann der Benutzer folgende Komfort-Features aktivie-
ren:
bookmark: Er kann die Anwendung als Bookmark hinzufugen, um sie bequem zu
erreichen. Des Weiteren befindet sich neben dem Bookmark der Dashboard-Counter
(Abbildung 9). Dieser zeigt in diesem Fall an, wie viele Geschenke der Benutzer
bisher bekommen hat.
publish stream: Mit der erweiterten Berechtigung publish stream kann die Anwen-
dung automatisiert Beitrage fur den Benutzer auf Pinnwanden veroffentlichen. Ist
diese Berechtigung nicht vergeben, kann der Benutzer Beitrage manuell durch ein
FBJS-Popup veroffentlichen.
6 In der Box, welche mit Your Gifts betitelt ist, sieht der Benutzer alle Geschenke
die er bereits erhalten hat. Jeder Eintrag verlinkt auf eine Seite, auf der er Details
zu dem Geschenk einsehen kann.
4.1.2. Absenden
Hat der Benutzer den Button Send Tetris-Gifts Invitation betatigt, bekommt er ein
Popup angezeigt, auf dem der Vorgang des Einladens bestatigt werden muss (Abbil-
dung 4). Hier konnen Text und Gestaltung der Einladung uberpruft werden. Diese
Einladung wird in dem Fall von dem Entwickler-Account Klaus Erde verschickt,
weshalb sein Avatar dargestellt wird.
4.1.3. Einladung annehmen
Wurde eine solche Einladung verschickt, so taucht sie bei dem anderen Spieler in-
nerhalb der Anfragen von Facebook auf. Auf Abbildung 5 ist eine Einladung zu
Tetris-Gifts zu sehen die der Test-Account Klaus Erde geschickt hat. Der Benutzer
4 Beispielanwendung: Tetris-Gifts Seite 16
Abbildung 4: Abschicken einer Einladung von Tetris-Gifts
Abbildung 5: Darstellung einer Tetris-Gifts-Einladung
4 Beispielanwendung: Tetris-Gifts Seite 17
Abbildung 6: Geschenk-Seite von Tetris-Gifts
kann diese Einladung annehmen oder ignorieren. Nimmt er die Einladung an, wird
er in die Anwendung geleitet.
4.1.4. Geschenk-Seite
Hat ein Benutzer eine Einladung angenommen, oder auf der Startseite eines der er-
haltenen Geschenke nochmals angeschaut, kann er die Details des Vorgangs einsehen.
Hier werden der Beschenkte sowie der Schenkende angezeigt. Zwischen den beiden
Akteuren ist das Geschenk in Form eines Tetris-Elements abgebildet. Wenn eine
Nachricht eingetragen wurde, so wird diese ebenfalls angezeigt. Die Darstellung der
Namen der Benutzer wird mittels des FBML-Tags fb:name, die angezeigten Profil-
bilder mittels fb:profile-pic realisiert. Beide Tags erwarten die Facebook-ID des
Nutzers.
4 Beispielanwendung: Tetris-Gifts Seite 18
Abbildung 7: E-Mail Benachrichtigung von Tetris-Gifts
4.1.5. Absenden
Hat der Schenkende das Formular ausgefullt, so schickt er es ab. Danach werden die
Formulareingaben verarbeitet. Dem Nutzer wird nach Absenden des Formulars die
Seite mit dem Schenkungsvorgang angezeigt, welche auch der Beschenkte sehen wird.
Hat der Schenkende keine erweiterte Berechtigung abgegeben, so wird ihm beim
Darstellen der Seite das FBJS-Popup zur Veroffentlichung angezeigt. Im Hintergrund
werden die im Folgenden beschriebenen Ablaufe angestoßen.
E-Mail Hat der Beschenkte bereits das Spiel benutzt, so hat er bei der Installa-
tion die Erlaubnis abgegeben, dass die Anwendung ihm E-Mails schreiben darf. Ist
dies der Fall, wird dem Beschenkten eine E-Mail, wie in Abbildung 7 dargestellt,
gesendet.
Pinnwand-Veroffentlichung Hat der Schenkende die erweiterte Berechtigung
publish stream abgegeben, so wird serverseitig direkt eine Veroffentlichung von
dem Schenkenden auf der Pinnwand des Beschenkten hinterlassen. Hat er diese Be-
rechtigung nicht abgegeben, so wird dem Schenkenden ein FBJS-Popup (Abbildung
8) angezeigt, um diesen Vorgang durchzufuhren.
Dashboard-Aktionen Bei jedem Schenkvorgang wird die Anzahl des Dashboard-
Counters auf die Anzahl erhaltener Geschenke gesetzt (Abbildung 9). Ebenfalls wird
eine News fur das Dashboard erstellt, damit der Nutzer informiert ist, welche Neu-
igkeiten es in der Anwendung gibt (Abbildung 10).
4 Beispielanwendung: Tetris-Gifts Seite 19
Abbildung 8: FBJS-Popup mit Pinnwandveroffentlichung zu Tetris-Gifts
Abbildung 9: Dashboard-Counter zu Tetris-Gifts
4 Beispielanwendung: Tetris-Gifts Seite 20
Abbildung 10: Dashboard-News zu Tetris-Gifts
4.2. Serverseitige Realisierung
Das Datenbankmodell beinhaltet 3 Tabellen (siehe Abbildung 11). Mit diesen und
der bereits erlauterten Mechanik konnen alle Aspekte der zu erfassenden Daten
erzeugt werden.
4.2.1. Datenbankmodell
Abbildung 11: Datenbankmodell zu Tetris-Gifts
Die users-Tabelle beinhaltet Informationen, die zur Verknupfung mit Facebook
benotigt werden. Die ID von users kann in dem Kontext eines Senders (sender id)
oder Empfangers (receiver id) mit der transfers-Tabelle verknupft werden. Die
Eigenschaften der verschiedenen Tetris-Steine sind in der Tabelle bricks abgelegt.
Die Steine werden mittels ihrer ID zu dem Fremdschlussel brick id der transfers-
Tabelle verknupft.
4 Beispielanwendung: Tetris-Gifts Seite 21
4.2.2. Formulareingaben verarbeiten
Wird das Formular abgeschickt, so sind folgende Daten per HTTP-POST ubertragen
worden:
• Facebook-ID des Empfangers
• Nachricht, die ubertragen werden soll
• Die ID des ausgewahlte Tetris-Steins
Zusatzlich zu den eigentlichen Formulardaten ist die Facebook-ID des Schenkenden
bekannt, da diese von Facebook mit ubertragen wird. Mit diesen Daten wird ein
neuer Transfer erstellt. Wenn erforderlich, wird an dieser Stelle auch die E-Mail
verschickt sowie die automatisierte Veroffentlichung des Beitrages fur die Pinnwand
abgesendet.
Bei jeder verarbeiteten Formulareingabe wird der Dashboard-Counter neu gesetzt
und eine Dashboard-News geschrieben. Des Weiteren soll in die Datenerfassung noch
mit einfließen, wie viele Geschenke verschenkt wurden. Diese manuelle Erfassung
von Werten geschieht in der Anwendung mittels eines Methodenaufrufes, den das
trackbuddy bereit stellt. Naheres hierzu wird in den Anforderungen, im speziellen in
Kapitel 5.1.9 zu der anwendungsspezifischen Datenerfassung, erlautert.
4.3. Zu erfassende Daten
In der folgenden Tabelle sind alle Daten, zusammen mit der Stelle an der sie auftre-
ten, notiert. Diese Beispielanwendung erzeugt alle Daten, die von trackbuddy erfasst
werden sollen.
Die Anforderungen im nachsten Kapitel werden Bezug auf die Beispielanwendung
nehmen.
4 Beispielanwendung: Tetris-Gifts Seite 22
Daten AuftrittInstallation Anwendung wird von einem Benutzer das erste Mal
aufgerufen und installiertDeinstallation Nutzer deinstalliert die Anwendung in den
Facebook-OptionenImpression Wenn eine Seite aufgerufen wirdEinladungen Nutzer werden uber den Multi-Friend-SelectorE-Mail Durch die Anwendung versendete E-MailsDashboard-News Benachrichtigung fur den Beschenkten bei einem
neuen GeschenkDashboard-Counter Wird nach jedem Schenkvorgang fur den Beschenk-
ten neu gesetztVeroffentlichung (System) Wenn der Nutzer eine erweiterte Berechtigung ab-
gegeben hat und ein Geschenk verschickt hatVeroffentlichung (Nutzer) Der Nutzer hat keine erweiterte Berechtigung ab-
gegeben und macht eine manuelle Veroffentlichunguber ein FBJS-Popup
Anwendungsspezifische Da-tenerfassung
Jeder Schenkvorgang soll intern gezahlt werden
Tabelle 1: Zu erfassende Daten der Beispielanwendung Tetris-Gifts
5 Anforderungen Seite 23
5. Anforderungen
Die Anforderungen an den Gem trackbuddy sind zusammen mit der Firma
buddybrand definiert worden. In diesem Kapitel werden die einzelnen Aspekte naher
aufgeschlusselt. Wie die einzelnen Teile implementiert wurden, wird spater in Ka-
pitel 7 aufgezeigt. Die verschiedenen Anforderungen an die Datenerfassung nehmen
Bezug auf die Beispielanwendung Tetris-Gifts aus Kapitel 4.
5.1. Datenerfassung
Der Gem erweitert nicht das Rails-Framework generell, sondern klinkt sich in die
Anwendung ein. So werden fur jede Anwendung unabhangig voneinander Daten ge-
sammelt.
Die Datenerfassung unterteilt sich in verschiedene zu erfassende Schlussel mit un-
terschiedlichen Eigenschaften. Im Folgenden werden die einzelnen Schlussel naher
erlautert. Wenn moglich, beziehen sich die Beispiele auf die Beispielanwendung aus
dem vorherigen Kapitel.
5.1.1. Seitenaufruf
Jede aufgerufene Seite muss erfasst werden. Dabei ist nicht ausschließlich die Uhrzeit
und der Nutzer von Interesse, sondern auch, welche Seite aufgerufen wird. Des Wei-
teren mussen Referrer erfasst werden, uber die der Nutzer in die Anwendung gelangt
ist. Referrer werden durch View-Helper gesetzt, wenn eine Veroffentlichung oder ein
anderer Kanal, der von der Anwendung nach außen fuhrt, HTTP-Links enthalt. So
soll festgestellt werden auf welchem Weg Nutzer in die Anwendung kommt.
Auf eine Erfassung der Metadaten des HTTP-Headers (Browser oder Betriebssys-
tem) wird verzichtet. Zudem ist dieses auch nicht moglich, da die Requests an den
Anwendungsserver von Facebook gestellt werden und somit der HTTP-Request nicht
vom Nutzer direkt kommt. Des Weiteren haben Informationen uber Browser oder
Betriebssystem im Reporting keinen Mehrwert fur buddybrand oder deren Kunden.
Schlussel: impression
Daten:
• Zeit
• Nutzer
• Query-String
5 Anforderungen Seite 24
• Referrer
– Einladung
– Pinnwand
– Dashboard-News
– Lesezeichen
– Benutzerdefiniert durch Konfiguration
– ohne Referrer (direkter Aufruf)
• Referrer-Typ
5.1.2. Pinnwand-Veroffentlichungen
Jede Veroffentlichung eines Benutzers auf der Pinnwand wird in die Statistik mit
aufgenommen.
Es muss herausgefunden werden, von welcher Art eine Veroffentlichung ist. Ist be-
kannt welche Veroffentlichungen am haufigsten gemacht werden, konnen diese op-
timiert werden. Um festzustellen welche Veroffentlichung getatigt worden ist, muss
die Anwendung per AJAX einen Callback an den Anwendungsserver senden, der
diesen erfasst.
In der Beispielanwendung findet eine Pinnwand-Veroffentlichung statt, wenn ein
Nutzer jemand anderem einen Tetris-Stein schenkt. Wenn die Seite danach geladen
wird offnet sich ein Popup, die den Nutzer die Veroffentlichung vornehmen lasst. Hat
der Nutzer die entsprechende erweiterte Berechtigung vergeben, so offnet sich nichts
und die Veroffentlichung wird mittels der REST-API serverseitig durchgefuhrt.
Schlussel: publish
Daten:
• Quelle
– Veroffentlichung durch Benutzer
– Automatisierte Veroffentlichung durch Anwendung
• Zeit
• Nutzer
• Art
5 Anforderungen Seite 25
5.1.3. Gesendete Einladungen
Benutzer konnen ihre Freunde in eine Anwendung einladen. In der Beispielanwen-
dung werden Beschenkte, die durch den Multi-Friend-Selector ausgewahlt wurden,
in die Anwendung eingeladen.
Bei einer solchen Einladung werden die Facebook-IDs der eingeladenen Benutzer
der Anwendung mitgeteilt. So konnen die Anzahl und Identitaten der Eingeladenen
erfasst werden.
Sofern es die Anwendung erlaubt, ist es fur einen Benutzer moglich auch Einla-
dungen in die Anwendung per E-Mail zu verschicken. Auf eine Erfassung solcher
Einladungen per E-Mail wird bewusst verzichtet. Diese Art von Einladungen besit-
zen ohnehin keine Relevanz, da dieses Feature von Benutzern nicht angenommen
wird. Deswegen verzichtet buddybrand ganzlich auf die Option Einladungen dieser
Art anzubieten. Auf der anderen Seite kann auch nicht luckenlos verfolgt werden, ob
sich ein Benutzer nach einer Einladung per E-Mail auch auf die Anwendung begibt.
Der Prozess reißt an der Stelle ab, an der sich ein potentieller Benutzer erst bei
Facebook registrieren muss.
Schlussel: invite
Daten:
• Einladender Nutzer
• Eingeladener Nutzer
• Zeit
5.1.4. Gesendete E-Mails
Gibt der Benutzer eine entsprechende erweiterte Berechtigung, kann eine Anwen-
dung aus Facebook heraus dem Benutzer E-Mails senden. Dies kann benutzt werden,
um den Benutzer auch außerhalb von Facebook uber Neuigkeiten zu informieren.
Solche E-Mails werden serverseitig von der Anwendung mit frei definierbarem Inhalt
verschickt. Hat ein Nutzer die Beispielanwendung Tetris-Gifts bereits installiert, so
hat er die Erlaubnis abgegeben, dass die Anwendung ihm E-Mails schicken darf. In
einem solchen Fall wird der Beschenkte per E-Mail daruber informiert, wenn ihm
ein neues Geschenk gesendet wurde.
Die Anzahl der E-Mails, die durch die Anwendung an Benutzer versendet werden,
wird gezahlt. Relevant ist diese Anzahl der E-Mails um sie in ein Verhaltnis dazu
5 Anforderungen Seite 26
zu stellen, wie viele Benutzer uber gesendete E-Mails wieder die Anwendung betre-
ten. Um dies festzustellen, werden modifizierte Links mit einem speziellen Referrer
benutzt.
Schlussel: E-Mail
Daten:
• Nutzer
• Zeit
• Art
5.1.5. Gesendete Dashboard-Benachrichtigungen
Jede Anwendung kann Benachrichtigungen in das “Dashboard fur Spiele oder An-
wendungen” von Benutzern platzieren. Beispielsweise erscheint im Dashboard unter
dem Eintrag der Beispielanwendung Tetris-Gifts eine Nachricht, wenn der Benutzer
ein neues Geschenk erhalten hat.
Diese Anzahl ist wie bei den gesendeten E-Mails relevant, um den Wirksamkeitsgrad
dieser Art der Kommunikation mit dem Benutzer zu ermitteln.
Schlussel: dashboardnews
Daten:
• Nutzer
• Zeit
• Art
5.1.6. Gesetzte Dashboard-Counter
Als Erganzung zu Dashboard-Benachrichtigungen kann auch fur jede Anwendung
eine Zahl neben dem Lesezeichen aktualisiert werden, die sogenannten Dashboard-
Counter (Siehe Kapitel 3.1). In der Beispielanwendung zeigt diese Zahl die Gesamt-
zahl der erhaltenen Geschenke an. Erhohungen des Dashboard-Counters, wie er von
jeder Anwendung spezifisch gesetzt wird, mussen gezahlt und ubertragen werden.
Der Nutzen des Zahlens von Dashboard-Countern liegt auch hier darin, den Wirk-
samkeitsgrad dieser Art der Kommunikation festzustellen.
5 Anforderungen Seite 27
Schlussel: dashboardcounter
Daten:
• Nutzer
• Zeit
5.1.7. Installation
Eine Anwendung muss installiert werden, bevor sie dem Nutzer zur Verfugung steht.
Installationen werden der Anwendung per Callback von Facebook mitgeteilt. Jedes
Mal, wenn ein Nutzer die Anwendung installiert, kann von Facebook eine in der
Anwendungskonfiguration hinterlegte Adresse angefordert werden. Die Einrichtung
eines solchen Callbacks wird in Kapitel 8.2 erklart.
Der Callback wird anschließend ausgewertet und dessen Aufruf dem Tracking-Server
mitgeteilt.
Schlussel: install
Daten:
• Nutzer
• Zeit
5.1.8. Deinstallation
In den Optionen zu seinem Benutzerkonto kann ein Nutzer Anwendungen deinstal-
lieren. Wurde eine Anwendung deinstalliert, so kann diese nicht weiter auf die Daten
eines Nutzers zugreifen.
Deinstallationen werden, wie Installationen auch, der Anwendung von Facebook mit-
tels eines Callbacks mitgeteilt.
Schlussel: uninstall
Daten:
• Nutzer
• Zeit
5 Anforderungen Seite 28
5.1.9. Anwendungsspezifische Datenerfassung
Je nach Anwendung sollen eigene anwendungsspezifische Datenerfassungen hinzu-
kommen. Die Erfassung der Daten beschrankt sich auf ganzzahlige Werte, die bei
einem Aufruf inkrementiert werden. Pro Anwendung sind beliebig viele anwendungs-
spezifische Daten moglich. Gespeichert werden diese mit dem Namen des Wertes,
der ubergeben wird.
In der Beispielanwendung wird so die absolute Anzahl an gesendeten Geschen-
ken gezahlt. Im Programmcode soll dies, durch einen Aufruf von der Methode
track action mit einem entsprechenden Argument, erfasst werden.
t r a c k a c t i o n ( ” s e n t g i f t ” )
Listing 5: Anwendungsspezifische Datenerfassung fur Beispiel “sentgift”
Die Argumente fur track action mussen nicht in der Konfigurationsdatei definiert
werden. Stattdessen ist der Parameter generisch, das heißt die Funktion darf an je-
der Stelle mit jedem beliebigen Argument aufgerufen werden.
Schlussel: custom
Daten:
• Art
• Zeit
5.2. View-Helper
Um den Referrer zu bestimmen, werden Links, die von Außen wieder in die An-
wendung fuhren, um die Parameter “srcref” und “srctype” erweitert. Ein Link zur
Bestimmung der Besucher, die durch eine Einladung auf die Anwendung kommen,
kann folgendes Format haben:
http :// apps . facebook . com/anwendungsname? s r c r e f=i n v i t e&
src type=publ i sh1
Listing 6: Einladungslink mit Referrer-Argument
5 Anforderungen Seite 29
So kann mit den in Kapitel 5.1.1 definierten Arten in jeder von außen kommen-
den Anfrage festgestellt werden, durch welchen Kommunikationskanal die Anfrage
angestoßen wurde.
5.3. Callbacks
Bei Installationen und Deinstallationen macht Facebook einen Callback auf eine
Seite, die bei Facebook hinterlegt werden kann (Kapitel 8.2). Eine solche Callback-
Seite kann jedes Mal, wenn sie aufgerufen wird, die Anzahl der Installationen bzw.
Deinstallationen erhohen.
Manuelle Veroffentlichungen auf der Pinnwand mussen ebenfalls per Callback erfasst
werden. Eine manuelle Veroffentlichung auf der Pinnwand geschieht durch ein FBJS-
Element. An dieser Stelle kann asynchron ein Callback ausgefuhrt werden, der auf
dem Server die Anzahl der manuellen Veroffentlichungen hochzahlt.
5.4. Kompatibilitat
Der Gem muss kompatibel zu Rails 3 sein. Zur Kommunikation mit Facebook wird
der von buddybrand entwickelte Gem buddy als Grundlage genommen. Zu diesem
muss trackbuddy ebenfalls kompatibel sein.
Eine Alternative ist, auf Rails 2.3 mit dem Gem Facebooker zu setzen. Die Ent-
scheidung von buddybrand fiel darauf, den Gem ausschließlich fur Rails 3 und fur
kommende Anwendungen zu entwickeln. Anwendungen, die fur Rails 2.3 program-
miert wurden, werden bei Erfolg ohnehin auf Rails 3 portiert.
Rails 3 lasst sich mit Ruby in Version ab 1.8.7 und 1.9.1 benutzen. Der Gem muss
in Folge dessen kompatibel zu beiden Ruby-Versionen sein.
5.5. Lokaler Puffer
Die durch den Gem gewonnenen Daten mussen lokal gepuffert werden. Ein lokaler
Puffer bietet eine erhohte Fehlertoleranz, wenn der Server nicht erreichbar ist.
Die Tatigkeit des Pufferns muss der Gem selbststandig und autark ausfuhren. Hierfur
wird ActiveSupport::Cache::MemoryStore von Rails verwendet. Der Cache halt
die Daten im RAM vor.
Da die Daten im Arbeitsspeicher gehalten werden, gehen diese auch bei einem erneu-
ten Deployment der Anwendung nicht verloren und sind auch uber mehrere Requests
hinweg verfugbar.
5 Anforderungen Seite 30
5.6. Ubertragung der Daten
Die Ubertragung der Daten lasst sich mittels der Konfigurationsdatei durch zwei
Werte parametrisieren:
• Limit von Datensatzen, nachdem die Ubertragung eingeleitet wird
• Schwelle, ab wie vielen fehlgeschlagenen Ubertragungen ein Fehler gemeldet
wird
5.6.1. Exaktheit
Ein Datensatz soll bei einer Ubertragung nur geloscht werden, wenn dieser auch
auf den Tracking-Server ubertragen werden konnte. Konnte ein Datensatz nicht
ubertragen werden, wird dieser nicht aus dem Puffer geloscht. Es findet keine weitere
Ubertragung von Datensatzen statt, wenn ein einziger Datensatz nicht ubertragen
wurde. Bei einem erneuten Erreichen des Puffer-Limits wird nochmals eine Uber-
tragung eingeleitet.
5.6.2. Eskalation
Jede fehlgeschlagene Ubertragung wird gezahlt. In der Konfigurationsdatei wird eine
Schwelle definiert, ab wie vielen fehlgeschlagenen Ubertragungen ein Fehler berichtet
wird. Wird diese Schwelle uberschritten, wird ein Fehler genau einmal gemeldet,
unabhangig davon wie oft die Ubertragung im weiteren Verlauf fehlschlagt.
Wenn ein Fehler gemeldet wurde, wird weiterhin bei jedem Erreichen des Puffer-
Limits eine erneute Ubertragung eingeleitet. War die Ubertragung erfolgreich, wird
die Anzahl fehlgeschlagener Versuche wieder zuruck auf Null gesetzt.
Alternativ konnte bei jedem Vielfachen des Schwellenwertes ein Fehler ausgelost
werden. Als Resultat entstehen so viele gleiche Fehlermeldungen.
5.6.3. Austauschbarkeit des Backends
Das Modul zur Kommunikation mit dem Tracking-Server soll austauschbar sein.
Aus diesem Grund soll der Transfermechanismus lediglich uber eine einzige Metho-
de ausgelost werden.
Um vollstandige Freiheit bei der Implementierung des Backends zu haben, wird
dieses als eigener Gem implementiert. Das Backend der Wahl wird in der Konfi-
gurationsdatei zu trackbuddy angegeben. Der Wert fur den Schlussel ist der Name
des Gems, welcher das Backend implementiert hat. Um bei vielen Backends einen
Uberblick zu behalten, sollte hierfur das Prafix “trackbuddy-” verwendet werden.
5 Anforderungen Seite 31
Fur jedes gewunschte weitere Backend kann ein eigener Gem erstellt werden. Da in
diesem Fall das Backend der Wahl Redis ist, wird der entsprechende Gem trackbuddy-
redis heißen.
Diesem Schema bedient sich auch DataMapper. DataMapper ist ein objektrelationa-
ler Mapper (ORM), welcher ebenfalls in Ruby programmiert wurde. DataMapper ist
eine Alternative zu ActiveRecord und kann die Datenhaltung einer Rails-Anwendung
ubernehmen. Hier werden auch die Implementierungen des Backends fur verschie-
dene Datenbanken in eigenen Gems realisiert, beispielsweise in dm-sqlite-adapter.
5.6.4. Redis-Backend
Der Tracking-Server ist eine Redis-Datenbank, in welche die Daten direkt geschrie-
ben werden. Redis (http://code.google.com/p/redis/) ist eine erweiterte Key-
Value-Datenbank. Sie kann sowohl im RAM gehalten, als auch auf der Festplatte
persistiert werden.
Mittels Namespacing werden auf der Redis-Datenbank die einzelnen Anwendungen
separiert. Der Namespace fur die Anwendung anwendungsname ergibt sich durch
das Schema trackbuddy:anwendungsname.
Innerhalb des Namespaces sind die erfassten Daten, getrennt nach den verschiedenen
Schlusseln und wie in Kapitel 5.1 definiert, gespeichert.
5.6.5. Alternative Backends
Eine Alternative zur Kommunikation mit einem Redis-Server kann auch die API zu
einem dedizierten Server eines Drittanbieters sein. Im Backend muss diese spezielle
API dann angesprochen werden.
Die erfassten Daten konnen auch serialisiert in einer Datei abgelegt werden, welche
anschließend ausgelesen und geleert wird. Problematisch hierbei ist der gleichzei-
tige Zugriff von mehreren Quellen auf die Datei, diese konnte dadurch beschadigt
werden. Der Durchsatz von Lese- und Schreiboperationen skaliert schlecht, wenn
lediglich aus einer Datei gelesen wird.
Die Daten, welche auf den Redis-Server geschrieben werden, konnten auch direkt in
eine relationale Datenbank geschrieben werden. Bei buddybrand ist es ublich, Da-
ten, welche weiterverarbeitet werden oder temporar sind, in Redis abzulegen. Redis
wird auf drei Servern parallel ausgefuhrt und bietet einen hoheren Durchsatz bei
dem Schreiben von Daten als PostgreSQL, welches fur die restlichen Datenbanken
verwendet wird. Zur abschließenden Verarbeitung kann ein Cronjob, Daemon oder
Ahlniches die Daten aus Redis auslesen und Statistiken generieren.
5 Anforderungen Seite 32
5.7. Anonymisierung
Durch eine Option in der Konfigurationsdatei konnen die gesammelten Daten, wel-
che eine Benutzer-ID enthalten, anonymisiert werden. Dies geschieht, indem eine
Hashfunktion auf die IDs angewendet wird. Die Hashfunktion ist vom Typ MD5
(Message-Digest Algorithm 5) und liefert einen 32 Zeichen langen alphanumerischen
String als Ergebnis.
5.8. Fehlerbehandlung
Der Gem muss den verantwortlichen Administratoren und Entwicklern selbststandig
mitteilen wenn ein Problem auftritt.
5.8.1. Ausfall des Tracking-Servers
Ein realistisches Problem im Betrieb ist die Nichtverfugbarkeit des Tracking-Servers.
Der lokale Puffer speichert die Daten, damit in diesem Fall die erfassten Daten
nicht verloren gehen. Ist der Tracking-Server aber fur einen langeren Zeitraum nicht
verfugbar, muss dies den Verantwortlichen mitgeteilt werden.
Bei der Benachrichtigung uber einen nicht erreichbaren Tracking-Server sind, je nach
Anwendungsfall, folgende Intervalle moglich:
• Benachrichtigung jedes Mal, wenn der Tracking-Server nicht verfugbar ist
• Benachrichtigung nach einer bestimmten Anzahl an missgluckten Versuchen
• Keine Benachrichtigung
Um sich hier nicht definitiv festlegen zu mussen und die Eskalation auch je nach
Anwendungsfall individuell bestimmen zu konnen, empfiehlt sich eine Option in
der Konfigurationsdatei mit einem ganzzahligen Wert. Dieser Wert kann 0 (fur kei-
ne Benachrichtigung) bis hin zu einer fest definierten Anzahl an fehlgeschlagenen
Ubertragungen betragen, bis der Gem das Problem meldet. Folgende Probleme sind
denkbar:
• Redis-Server hat keine Netzwerkverbindung
• Verbindung wird vom Server abgelehnt
• Interner Serverfehler
5 Anforderungen Seite 33
5.8.2. Benachrichtigung per Hoptoad
Die Anwendungen von buddybrand melden einen Fehler, indem auf den Dienst des
Drittanbieters Hoptoad (http://hoptoadapp.com/) zuruckgegriffen wird. Tritt in
einer Anwendung eine Exception auf, wird diese an Hoptoad ubermittelt. In einem
Webinterface werden alle aufgetretenen Fehler mit Datum und Haufigkeit aufgefuhrt.
Zusatzlich werden von Hoptoad, sofern aktiviert, E-Mails an die Entwickler gesendet,
um sie sofort uber den Fehler zu informieren. Als zusatzliche Informationsquelle wird
auch ein Eintrag in die Logdatei der Anwendung geschrieben.
5.8.3. Alternative Benachrichtigungen
Eine Alternative zur Benachrichtung via Hoptoad, ist die Anbindung an eine System-
management-Software. buddybrand setzt als Software fur das Systemmanagement
die Open-Source-Losung Zabbix ein. Uber SNMP, das Simple Network Management
Protocol, konnte der Gem seinen Status an ein solches System melden. Ruby kann
mittels eines Gems mit dem Namen snmp uber dieses Protokoll kommunizieren. Be-
nachrichtungen uber Hoptoad empfehlen sich gegenuber einer Anbindung an Zabbix,
denn Hoptoad ist in den Workflow der Entwickler eingebunden. Die E-Mail-Adressen
sind in Hoptoad ohnehin hinterlegt, um bei Fehlern in Anwendungen zu informieren.
Wiederum eine andere Moglichkeit ist, ausschließlich auf den internen Logger von
Rails zuruckzugreifen. Die Fehlermeldungen der Datenerfassung werden mit weite-
ren Informationen der Seitenaufrufe in der Logdatei abgelegt. Logdateien enthalten
viele weitere Informationen wie HTTP-Parameter und ausgelieferter View. Somit
werden diese in der Regel nur bei der Suche nach einem konkreten Fehler konsul-
tiert. Diese Moglichkeit eignet sich nicht, um aktiv die Entwickler von einem Fehler
in Kenntnis zu setzen. Diese mussten also von sich aus die Logdateien uberprufen,
was aufgrund der Datenmengen nicht praktikabel ist.
Im Gegenzug konnte die Anwendung selbst eine E-Mail versenden. Hierbei gibt es
folgende Nachteile:
• Nicht jede Anwendung ist fur den E-Mail-Versand konfiguriert
• Die E-Mail-Adressen der Entwickler mussten hinterlegt werden
• Fehler im Mail Transfer Agent (MTA), der fur den Versand der E-Mails zu-
standig ist
Auch hier ist es sinnvoller, auf Hoptoad zuruckzugreifen, da zusatzlich wie bei Zabbix
die E-Mail-Adressen ein zweites Mal hinterlegt und gepflegt werden mussten.
5 Anforderungen Seite 34
5.9. Konfiguration
Die Konfiguration findet mittels einer Konfigurationsdatei innerhalb der Rails- An-
wendung statt. Folgende Punkte sind uber die Konfigurationsdatei zu bestimmen.
• Anzahl Datensatze, die ubertragen werden sollen
• Schwellenwert, ab wie vielen fehlgeschlagenen Ubertragungen ein Fehler ge-
meldet wird
• Welche URIs (Uniform Resource Identifier) nicht erfasst werden sollen
• Ob Nutzerdaten anonymisiert werden sollen
• Welches Backend zur Datenubertragung geladen werden soll
• Anzahl fehlgeschlagener Ubertragungen bis zur Benachrichtigung
• Gultige Werte fur Referrer
Wird keine Konfigurationsdatei gefunden, so wird der Gem mit Standardwerten
initialisiert.
6 Architektur Seite 35
6. Architektur
Ziel des Gems ist eine minimale Beeinflussung der Anwendung. Moglichst viele
sich ergebende Konfigurationseinstellungen werden aus dem Kontext der Anwen-
dung bestimmt. Auch sollen Mechanismen und Entwicklungspraktiken der Entwick-
ler berucksichtigt werden, um auch in dieser Hinsicht eine nahtlose Integration zu
ermoglichen.
Alternativen werden, wenn vorhanden, diskutiert. Die Entscheidung fur einen Weg
ergibt sich aus minimaler Beeinflussung der Anwendung, was gangig bei buddybrand
sowie Praktik der Ruby-Community ist.
6.1. Implementierungsalternativen
Die Datenerfassung muss nicht zwingend als RubyGem umgesetzt werden. Es gibt
sowohl in der Welt von Rails eine Alternative, als auch andere, verteilte und lokale,
Ansatze. Im Folgenden wird erlautert, warum ein RubyGem verwendet wird und
welche Nachteile die anderen Losungen mit sich bringen.
6.1.1. RubyGem
Gems in Ruby sind systemweite Bibliotheken. Eine solche Bibliothek kann von meh-
reren Anwendungen gleichzeitig benutzt werden und muss auch lediglich einmal
aktualisiert werden, wenn ein neue Version verfugbar ist.
Alle aktuell verwendeten Gems konnen auch eingefroren und mit der Anwendung
ausgeliefert werden. In diesem Fall sind sie nicht systemweit verwendbar.
Jede Anwendung hat eine eigene Instanz der Gems, die in der Anwendung verwendet
werden.
Gems sind das universelle Mittel, Ruby um fremde Bibliotheken zu erweitern. Jeder
Entwickler weiß, wie Gems installiert werden und kann damit umgehen.
Seit Rails 3 ist es Standard, die Gems einer Anwendung mit dem Tool bundler zu
verwalten. Jede Anwendung hat zu diesem Zweck ihr eigenes Gemfile. In einem
Gemfile werden die Gems, die die Anwendung benutzt, definiert. Mittels bundler
werden die Gems mit den jeweiligen Abhangigkeiten installiert. Durch diesen Me-
chanismus werden Gems, wenn sie nicht bereits systemweit installiert sind, fur jede
Anwendung separiert installiert.
bundler initialisiert zum Start der Anwendung die Gems, anschließend sind die so-
genannten Railties verfugbar, die einen stabilen Hook wahrend dem Bootstrapping
einer Anwendung darstellen (Kapitel C.2.2).
Dadurch ist auch der Umgang mit verschiedenen Versionen von Gems, mit speziel-
6 Architektur Seite 36
len Branches und Repositories problemlos moglich, ohne andere Anwendungen zu
beeinflussen. Ein Set von Gems kann auch komplett unter Berucksichtigung aller
Aspekte eingefroren werden.
6.1.2. Plugin fur Ruby on Rails
Im Gegenteil zu Gems werden Plugins direkt in die Anwendung integriert und mit
der Anwendung ausgeliefert.
Fur ein Plugin kann die selbe Codebasis wie fur einen Gem benutzt werden. Ein
Plugin braucht lediglich eine init.rb-Datei im Hauptordner. Diese hat Zugriff auf
Variablen des Rails Initializer (Fowler, 2006, S. 239), um Rails einen Einstiegspunkt
zu liefern. Die Spezifikation eines Gems (.gemspec) wird dabei ignoriert.
Ein Nachteil von Plugins ist, dass diese keine Abhangigkeiten abbilden konnen.
Wenn ein weiterer Gem oder ein weiteres Plugin benotigt wird, muss dieses manuell
installiert werden. Abhangigkeiten mussen ebenfalls manuell aufgelost werden.
In Rails 3 werden dank bundler Gems generell vor Plugins bevorzugt. Die Vortei-
le einer anwendungsspezifischen Erweiterung sind durch bundler genauso gegeben,
wie sie Plugins bieten. Zusatzlich kann auf die starke Infrastruktur der RubyGems
zuruckgegriffen werden, die bereits etabliert ist.
6.1.3. REST-API oder Webservice
Die komplette Datenerfassung kann mittels eines REST-Services implementiert wer-
den. An jeder Stelle des Programmcodes, an der zu erfassende Daten auftreten,
mussen diese an eine REST-API ubermittelt werden.
Eine minimale Beeinflussung der Anwendung ist hiermit nicht gegeben. Die Punkte,
an denen die Daten auftreten, mussen in jeder Anwendung aufs Neue gefunden und
an die REST-API weitergeleitet werden.
Ein Teilaspekt, welcher ohne Komplikationen als verteilte Komponente implemen-
tiert werden kann, ist das Backend. Die Punkte, an denen die Daten erfasst wer-
den, konnen einmal durch einen RubyGem angesprochen werden. Anschließend wird
ein alternatives Backend implementiert, welches die Daten an eine REST-API oder
einen Webservice ubertragt. Ein solcher Webservice kann komplett als geschlossener
Dienst angeboten werden, welcher die Auswertung der Daten ubernehmen kann.
6.1.4. Logdatei
Alternativ konnen die von Rails erstellte Logdateien mittels regularen Ausdrucken
untersucht werden. Hier ist es aber nicht moglich alle Informationen zu gewinnen.
6 Architektur Seite 37
Keine Probleme ergeben sich zwar durch alle zu erfassenden Eigenschaften, die sich
aus den HTTP-Parametern bestimmen lassen, da diese immer in der Logdatei ab-
gelegt werden. Anfragen an die REST-API sind ebenfalls im Log zu finden.
Nicht erfasst werden konnen die anwendungsspezifische Tracking-Aufrufe
(Kapitel 5.1.9), welche mittels einer Helper-Methode direkt erfasst werden.
Diese Methode ist fehleranfallig, weil sichergestellt werden muss, dass die regularen
Ausdrucke keine falschen Informationen liefern. Erschwerend kommt hinzu, dass fur
jede Anwendung ein hoher Setup-Aufwand notig ist, da eine Logrotation ebenfalls
berucksichtigt werden muss.
6.2. Wissensgewinnung
Wie in den Anforderungen aus Kapitel 5.1 beschrieben, gibt es fur einige zu er-
fassende Eigenschaften mehrere Typen, die unterschieden werden mussen. Bei einer
Veroffentlichung muss beispielsweise erfasst werden, ob diese nun einen Sieg oder eine
Niederlage des Spielers veroffentlicht. Es wird die Unterscheidung benotigt, wie oft
eine Nachricht generiert wird und wie oft Nutzer uber diesen Weg in die Anwendung
kommen. Um an diese Informationen zu gelangen, gibt es mehrere Ansatzpunkte.
Die erzeugten Nachrichten folgender Kommunikationskanale mussen auf verschiede-
ne Typen (im Folgenden Nachrichtentypen genannt) unterschieden werden:
• E-Mails
• Dashboard-News
• Manuelle Veroffentlichungen
• Automatische Veroffentlichungen
• Einladungen
6.2.1. Zusatzliche Parameter
Der Ansatz hierbei ist, direkt an der Stelle, an der die Nachricht definiert wird, dem
erzeugenden Element einen speziellen weiteren Parameter zu ubergeben, welcher
diesen Nachrichtentyp identifiziert. Somit sind Inhalt der Nachricht und Metainfor-
mation an der gleichen Stelle.
Je nach Art des Kommunikationskanals und wie dieser erzeugt wird, kann ein zusatz-
licher Parameter unterschiedlich realisiert werden.
6 Architektur Seite 38
6.2.2. Parsen des Inhalts
In einer allgemeinen oder speziellen Konfigurationsdatei konnen Schlusselworte oder
regulare Ausdrucke definiert werden, welche eine Nachricht beschreiben. Die Da-
tenerfassung uberpruft wahrend dem Erkennen einer Nachricht, basierend auf den
Schlusselworten, welchem Nachrichtentyp sie zugeordnet werden kann.
Nachteilig an dieser Alternative ist, dass neben dem eigentlichen Inhalt der Nach-
richt diese ein weiteres Mal an einer anderen Stelle beschrieben werden muss. Des
Weiteren konnen gewisse Schlusselworter in mehreren zu identifizierenden Nachrich-
ten existieren.
6.2.3. Handler
Um die Datenerfassung nicht fur jede Anwendung modifizieren zu mussen, konnen
Handler fur jeden Nachrichtentyp innerhalb der Anwendung geschrieben werden.
Diese Handler mussen innerhalb der Datenerfassung abgefragt werden. Wurde ein
solcher Handler aktiviert, kann die Datenerfassung mittels diesem den Typ der Nach-
richt gewinnen.
Wie bei einem zusatzlichen Parameter auch, muss weiterer Code an genau der Stel-
le, an der die Nachricht definiert wird, angehangt werden. Da in diesem Fall aber
lediglich der Typ der Nachricht von Interesse ist (nicht aber die vielen weiteren
Moglichkeiten welche sich durch Handler bieten), kann ganz auf Handler verzichtet
werden. Aus diesem Grund stellt ein weiterer Parameter fur diesen Anwendungs-
zweck eine simplere Losung auf der Seite der Anwendung dar.
6.2.4. Wissensbibliothek
Durch Aggregation aller Nachrichten, die uber alle Kommunikationskanale gesendet
wurden, kann eine Wissensbibliothek generiert werden. Aus den Nachrichten konnen
sich relevante Informationen extrahieren lassen, welche das Wesen der Nachricht be-
schreiben. Ahnlich wie bei Google News (http://news.google.de) werden Nach-
richten verschiedener Nachrichtenportale aggregiert. Auf der anderen Seite mussen
die personalisierten Aspekte, wie direkte Ansprache des Nutzers, ignoriert werden.
Selbst wenn mit erheblichem Aufwand eine solche dynamisch wachsende Wissensbi-
bliothek aufgebaut wird, fehlt ein konkreter Nachrichtentyp, welcher als Eigenschaft
fur den erfassten Datensatz abgespeichert werden kann.
Alternativ konnte eine solche Wissensbibliothek bei der Auswertung der Daten auf
der Seite des Tracking-Servers eingesetzt werden. Fur diesen Zweck mussten samt-
liche gesendeten Nachrichten erfasst und komplett ubertragen werden.
7 Implementierung Seite 39
7. Implementierung
7.1. Ordnerstruktur eines RubyGems
Als Hilfsmittel, um den RubyGem zu erstellen, wird auf Jeweler (Anhang F.2.1)
zuruckgegriffen. Jeweler bietet Generatoren fur Dateigeruste und Instruktionen fur
das Laden von Gems. Hierfur ist nicht unbedingt ein Tool erforderlich, dennoch
nimmt Jeweler vor allem fur das Erstellen der .gemspec-Datei Arbeit ab, da er
diese aus der Konfiguration automatisch erstellen kann.
Eine Alternative ist, komplett auf Tools zu verzichten (Anhang F.2.2) oder die Tools
selbst zu erstellen. Ein RubyGem, welcher mittels Jeweler erstellt wurde, hat fol-
gende Ordnerstruktur.
.
|−− R a k e f i l e
|−− VERSION. yml
|−− l i b
| |−− trackbuddy
| | |−− r a i l t i e . rb
| ‘−− trackbuddy . rb
|−− pkg
| ‘−− trackbuddy −1 . 0 . 0 . gem
|−− t e s t
| ‘−− t e s t t rackbuddy . rb
‘−− trackbuddy . gemspec
Listing 7: Minimalbeispiel fur trackbuddy-Gem-Ordnerstruktur
Rakefile Das Rakefile enthalt die Instruktionen fur rake (ruby make), ein Build-
werkzeug unter Ruby.
VERSION.yml Enthalt die aktuelle Version des Gems in YAML-Notation. Die-
se Datei ist nicht unbedingt notwendig. Stattdessen kann die Version auch in der
Konstanten mit dem Namen “VERSION” notiert werden.
lib Der Ordner lib enthalt den erstellten Programmcode. Die Hauptdatei des Gems,
trackbuddy.rb, liegt in der Wurzel dieses Ordners. Diese Datei wird geladen, wenn
der Gem eingebunden wird. Hier findet die Initialisierung des Gems selbst statt.
Davon zu unterscheiden ist aber die Einbindung des Gems in den Dispatch-Prozess
des Rails-Frameworks (Kapitel 7.6).
7 Implementierung Seite 40
Jedes Modul innerhalb des Gems wird per Konvention in eine eigene Datei geschrie-
ben. Diese Dateien liegt innerhalb eines Ordners, der auch den Namen des Gems
selbst tragt, in diesem Fall innerhalb lib/trackbuddy.
pkg Hier liegt der gepackte Gem. Der Dateiname beinhaltet neben dem Gem-
Namen auch die Versionsnummer.
test In dem Ordner test werden die Unit-Tests fur den Gem abgelegt.
trackbuddy.gemspec Diese Datei wird automatisch von Jeweler wahrend des Uber-
setzungsvorgangs generiert. Hier sind die fur Ruby notwendigen Informationen hin-
terlegt, um den Gem zu laden, welche nicht uber die Ordnerstruktur abgebildet
werden konnen (Thomas, 2009, S. 246). Die Gem-Spezifikation zu trackbuddy findet
sich in Anhang B.3.
7.2. Konfiguration
In der Anwendung selbst kann eine Konfigurationsdatei hinterlegt sein, dies ist aber
nicht notwendig. Kann eine Konfigurationsdatei nicht gefunden werden, so wird der
Gem mit vordefinierten Werten geladen. Bei der Installation und ersten Initialisie-
rung des Gems kann diese Datei durch einen Generator (Kapitel 7.7) mit eben diesen
vordefinierten Werten angelegt werden.
7.2.1. YAML
Die Konfiguration des Gems wird mittels der Datei config/trackbuddy.yml in-
nerhalb der Anwendung vorgenommen. Die Notation der Konfiguration erfolgt in
YAML (YAML Ain’t Markup Language). In der Konfigurationsdatei sind die Punk-
te aus den Anforderungen (Kapitel 5.9) definiert. YAML hat den Vorteil wenige
Zeichen zur Abbildungen von Werten auf Schlussel zu benotigen. Ein Beispiel fur
die Konfigurationsdatei von trackbuddy in YAML-Notation ist in Anhang B.4 zu
finden.
7.2.2. Alternative Konfigurationsmoglichkeiten
In den folgenden Absatzen werden mogliche Alternativen zu YAML diskutiert. Es
wird erlautert wieso YAML die beste Wahl zur Konfiguration von trackbuddy ist.
7 Implementierung Seite 41
Textdatei mit eigener Struktur Die Konfiguration konnte in einer Textdatei mit
einem selbst definierten Schema abgelegt werden. Dieses muss dann allerdings erst
umstandlich geparst werden. Ein Parser fur YAML existiert bereits als RubyGem.
JSON Alternativ zu einem eigenen Schema konnte auch JSON verwendet werden.
Hierfur existiert ebenfalls ein Parser in Form eines RubyGems. JSON hat, wegen
der Fahigkeit komplette Objekte zu beschreiben, allerdings neben der eigentlichen
Konfiguration einen Uberschuss an Zeichen, welcher fur eine korrekte Notation not-
wendig ist und den es bei YAML nicht gibt. Selbiges gilt fur XML. Hierfur gibt es
auch einen Parser, dennoch ist XML fur das menschliche Auge schwerer lesbar und
enthalt mehr Overhead an Zeichen als YAML.
Initializer-Skript Eine Alternative zu einer Konfiguration mittels einer Konfigura-
tionsdatei ist ein Initializer-Skript. Skripte im Ordner config/initializers wer-
den ein einziges Mal beim Start der Anwendung geladen. So wird verfahren, wenn
eine Aktion ein einziges Mal ausgefuhrt werden muss. Auf diesem Weg wird die
Session-Verwaltung von Rails initialisiert. Diese Moglichkeit empfiehlt sich, wenn
Code zum Start ausgefuhrt werden muss. Mittels einem Initializer kann auch direkt
Code des Gems manipuliert werden, im einfachsten Fall das Setzen einer Variablen.
So findet eine Konfiguration auf diesem Weg in Ruby statt. Fur eine Konfigurati-
onsdatei, welche keinen Code ausfuhren muss, ist das YAML-Format verbreiteter
und akzeptierter, da dieses Format lesbarer ist.
Handler Musste ein Handler definiert werden, welcher fur jede Anwendung speziell
ist, so ist ein Initializer-Skript ebenfalls der optimale Platz. Der Handler konnte ein-
mal zum Start der Anwendung geladen und in den Gem integriert werden. In einem
Handler konnte, wenn der Gem darauf ausgelegt ist, das komplette Backend imple-
mentiert werden - oder auch jede andere Funktionalitat des Gems. Allerdings beruht
das Konzept des Gems auf einer minimalen Beeinflussung. Da auch alle Anwendun-
gen, fur die dieser verwendet werden soll, homogen sind, gibt es keine Sonderfalle,
die in jeder Anwendung auf einem anderen Wege implementiert werden mussten.
Fur die minimalen Abweichungen reicht deshalb eine reine Konfigurationsdatei aus.
Domainspezifische Sprache Eine DSL (Domain Specific Language) konnte eben-
falls in Ruby implementiert werden. Die Definition der DSL konnte, wie beim Hand-
ler, als Initializer stattfinden. An dieser Stelle konnen in menschenlesbarer Kodie-
rung die Einstellungen getatigt werden. Fur so wenige simpel aufgebaute Einstel-
lungen wie in trackbuddy ist aber der Aufwand fur die Implementierung einer DSL
7 Implementierung Seite 42
Abbildung 12: Zusammenspiel der aktiven Tracking-Komponenten
unrealistisch hoch. Informationen zur Implementierung einer DSL in Ruby bietet
Perrotta (2010, S. 235).
Setzen von Variablen zur Laufzeit Die Einstellungen konnten auch direkt im
ApplicationController gesetzt werden. Der ApplicationController ist eine ab-
strakte Definition eines Controllers, wovon alle Controller der Anwendung erben.
Hier eine Konfiguration zu tatigen ist nicht gangig, da die Konfiguration des Gems
mit der Anwendungslogik vermischt wird. Ein weiterer Nachteil ist, dass Instanzen
von Controllern erst erzeugt werden, wenn eine Seite angefordert wird. Die Kon-
figuration ist fur den Gem erst nach dem Erzeugen dieser Instanz vorhanden. Des
Weiteren ergibt sich fur die Anwendung eine schlechtere Performance, weil bei jedem
Request der Seite die Einstellungen erneut gesetzt werden.
7.3. Modularchitektur
Es gibt vier sammelnde Module, welche in Abbildung 12, in der linken Reihe, abge-
bildet sind:
• Hit
• Email-Extension
• Restapi
• Custom
Diese rufen eine Methode des Puffers auf um die erfassten Daten zu speichern. Die
Modul-Namen ergeben sich durch die Stelle, an welcher die Daten erhoben werden.
Samtliche in den Anforderungen aufgefuhrten Punkte konnen in diese vier Arten,
7 Implementierung Seite 43
Hit E-Mail- REST-API CustomExtension
Impression E-Mail Dashboard-News track actionInstallation Dashboard-Counter
Deinstallation Veroffentlichung (System)Veroffentlichung (Nutzer)
Einladungen
Tabelle 2: Datenerhebung der verschiedenen Module
wie die Daten erhoben werden, unterteilt werden (Tabelle 2).
Neben den fur das Tracking zustandigen Modulen aus Abbildung 12 gibt es auch
unterstutzende Module. Diese werden am Ende dieses Kapitels ebenfalls aufgefuhrt.
7.3.1. Hit
Dieses Modul enthalt als Komponenten mehrere Klassen, die als Rack-Middleware
eingehangt werden. Die zu erkennenden Eigenschaften werden dabei auf einzelne
Klassen verteilt. So kann die Reihenfolge der Ausfuhrung der Klassen an einer Stelle
zentral bestimmt werden. Abbildung 13 veranschaulicht die Abarbeitung der Midd-
leware mit Klassen von trackbuddy.
Dabei werden Middleware-Klassen fur die folgenden Eigenschaften benotigt:
• Autorisierung (Installation/Deinstallation per Callback)
• Manuelle Veroffentlichung (per Callback)
• Seitenaufruf
• Eingeladene Freunde
Alle diese Klassen werden in den Stack der Rack-Middleware eingehangt und des-
wegen bei jedem Request durchlaufen. Samtliche Funktionalitat ist in einer eigenen
Klasse implementiert, um wahrend der Entwicklung einzelne Klassen einhangen zu
konnen. Auch konnen zur Fehlersuche einzelne Klassen ohne Weiteres wieder ent-
fernt werden.
Middleware-Klassen, die Callbacks (Kapitel 5.1.7) erkennen, mussen zuerst aus-
gefuhrt werden, da der Request an dieser Stelle nicht weiter verarbeitet werden
muss, also keine Abarbeitung des vollen Middleware- und Rails-Stacks notwendig
ist.
7 Implementierung Seite 44
Abbildung 13: Erfassung von Requests mittels Middleware
So wird vermieden, dass ein Callback auch als Impression gezahlt wird. Ein Call-
back wird von Facebook an die Anwendung gesendet, wenn diese vom Benutzer
deinstalliert wurde. Ein Callback wird ebenfalls von der Anwendung erzeugt, wenn
der Benutzer aus der Anwendung heraus eine Veroffentlichung auf seiner Pinnwand
tatigt.
Bei der Verwendung der Middleware um Seitenaufrufe zu erfassen, ergibt sich ein
weiterer, im Folgenden beschriebener, Vorteil. Wenn Seiten von Rails im Page Cache
vorgehalten werden, so sind dies statische Dateien, die bei einer erneuten Anfrage
ausgeliefert werden (Zygmuntowicz u. a., 2008, S. 237). Der entsprechende Code um
die Seite zu erzeugen, wird allerdings nicht mehr ausgefuhrt. Hierbei wird dennoch
der gesamte Middleware-Stack durchlaufen und die Anfrage von trackbuddy erfasst.
Wurde trackbuddy durch eine Methode innerhalb von Controllern Daten erfassen,
wurde dies bei zwischengespeicherten Seiten nicht ohne Umstande funktionieren.
Seitenaufruf Bei der Erfassung von Seitenaufrufen wird uberpruft, ob die Parame-
ter “srcref” und “srctype” gesetzt sind. Dabei steht “srcref” fur die Art des Referrers
und “srctype” fur die Art der Nachricht. Der Referrer wird vorher dem Eintragen
7 Implementierung Seite 45
auf Gultigkeit uberpruft, dieser muss einer den in den Anforderungen (Kapitel 5.1.1)
definierten Arten entsprechen.
Eine Ausnahme bei der Verarbeitung des Referrers bilden Lesezeichen. Lesezeichen
werden von Facebook immer mit dem Parameter ref=bookmarks veroffentlicht. Auf
diesen Parameter hin wird gesondert uberpruft und, wenn gesetzt, dieser auch als
korrekter Referrer erkannt.
Bestimmte URI konnen mittels der Konfigurationsdatei von der Datenerfassung aus-
geschlossen werden. Dies empfiehlt sich z.B. fur Pfade die /images/ beinhalten.
Diese Aufrufe auf Bilder, die nicht erfasst werden sollen, werden vom Rails-Stack
verarbeitet, wenn die entsprechende Ressource nicht als statische Datei ausgeliefert
werden kann. Ein Seitenaufruf wird nur dann erfasst, wenn keiner der geblockten
URI beinhaltet wird.
Authorisierung Jedes Mal, wenn diese Klasse der Middleware durchlaufen wird,
wird uberpruft, ob der aufgerufene URI einem bestimmten Schema entspricht. Hierfur
muss er entweder /middleware/uninstall/ bzw. /middleware/install/ entspre-
chen. Ist dies der Fall, zahlt es als Installation oder Deinstallation und wird zusam-
men mit dem entsprechenden Nutzer erfasst.
Manuelle Veroffentlichung Wird eine manuelle Veroffentlichung per Javascript
von einem Benutzer ausgelost, muss von der Anwendung selbst ein Callback ge-
schickt werden. Fur die Wissensgewinnung, um welche Veroffentlichung es sich han-
delt, ruft der Callback /middleware/publish/ mit einem zusatzlichen POST-Parameter
“srctype”, welcher die Art der Veroffentlichung beinhaltet, auf. So konnen die unter-
schiedlichen Arten von Veroffentlichungen erfasst werden, um auszuwerten, welche
am beliebtesten sind.
Einladungen Durch einen Multi-Friend-Selector (Abbildung 2 in Kapitel 3.3.2)
eingeladene Freunde werden der Anwendung mittels dem POST-Parameter “ids”
mitgeteilt. Dies ist ein Array mit den IDs der eingeladenen Benutzer. Jede einge-
ladene ID wird zusammen mit der ID des Nutzers, der die Einladung getatigt hat,
erfasst. In der Anwendung muss innerhalb des Formular der Parameters “srctype”
gesetzt werden. Auf diesen wird beim Verarbeiten gepruft, um den Typ der Einla-
dung festzustellen, falls eine Anwendung mehrere Einladungen bietet.
7 Implementierung Seite 46
7.3.2. Custom
Das Modul fur benutzerdefiniertes Tracking hat lediglich eine einzige Methode, wel-
che die Erfassung der Daten handhabt, wenn sie aufgerufen wird. Es wurde in einem
eigenen Modul implementiert, um die verschiedenen Quellen der erfassten Daten zu
separieren.
Wie dieses Modul dem Controller und den Views verfugbar gemacht wird, ist in
Kapitel 7.3.7 beschrieben.
7.3.3. Email-Extension
Um versendete E-Mails zu erfassen, muss dieses Modul den ActionMailer von Rails
erweitern, weshalb der Name des Moduls “-Extension” enthalt. Verschickt werden
E-Mails innerhalb der Anwendung mittels der Methode “deliver” in der Klasse
Mail::Message.
Innerhalb von trackbuddy wird in dieser Klasse ein Alias auf die Methode “deliver”
angelegt, “real deliver”. Anschließend wird die Methode “deliver” uberschrieben und
dabei mit der zusatzlichen Moglichkeit erweitert, einen Hash mit Optionen zu uber-
geben. In diesem zusatzlichen Hash kann im Parameter “srctype” die Art der E-Mail
ubergeben werden. So kann erfasst werden, von welchem Typ die E-Mail war, die
verschickt wurde. Des Weiteren existiert der Schlussel “args”, mit welchem zusatz-
liche Informationen wie etwa der Nutzer an den die E-Mail geschickt wird, erfasst
werden konnen. Falls die Datenerfassung anonym stattfinden soll, wird dieser Pa-
rameter komplett anonymisiert. Wurden die Daten erfasst, wird anschließend die
Methode “real deliver” aufgerufen und deren Ergebnis zuruckgegeben.
Eine Alternative, wie E-Mails auch erfasst werden konnten, ist eine Instanzvariable
innerhalb der E-Mail-Definition zu setzen. So konnte aber lediglich die Art der E-
Mail bestimmt werden. Weitere Informationen des Kontextes, beispielsweise an wen
und wie viele Empfanger gleichzeitig diese gesendet wird, sind zu diesem Zeitpunkt
nicht vorhanden.
7.3.4. Restapi
Um ein Profil der Anwendung zu erstellen, werden alle REST-Aufrufe erfasst. Dies
bietet den Entwicklern Anhaltspunkte zur Optimierung.
Durch Kombination und Abfrage dieser Parameter kann festgestellt werden, welchen
API-Aufruf die Anwendung in Facebook tatigt und welche gefiltert fur die Datener-
fassung im Speziellen relevant sind. So konnen die Aufrufe, die erfasst werden sollen,
in den Puffer geschrieben werden.
7 Implementierung Seite 47
Abbildung 14: Erfassung von Aufrufen der REST-API
Eine Instanz der Klasse, welche die Aufrufe der REST-API zahlt, registriert sich als
Observer bei dem Gem buddy, welcher fur die Verbindung zu Facebook zustandig
ist. Bei jedem Aufruf der API werden die Observer mit folgenden Argumenten auf-
gerufen:
• api method
• params
• options
Wissensgewinnung Um Information uber den Inhalt des Aufrufes zu erlangen,
wird in der Anwendung dem ubergebenen options-Hash, der jedem REST-API-
Aufruf mitgegeben wird, ein weiterer Parameter “srctype” gesetzt. Dieser wird mit
den restlichen Daten des Aufrufs auch dem Observer ubergeben. Wenn es sich bei
dem Aufruf um eine Pinnwand-Veroffentlichung handelt, wird dieser Parameter aus-
gelesen und die Art der Veroffentlichung somit erfasst.
7 Implementierung Seite 48
Abbildung 15: Eintrag fur Schlussel :request in Puffer
7.3.5. Buffer
In diesem Modul wird der lokale Puffer implementiert. Dem Puffer liegt eine In-
stanz von ActiveSupport::Cache::MemoryStore zugrunde. Im Arbeitsspeicher des
Computers konnen so, auch uber mehrere Anfragen hinweg, Werte einem Schlussel
zugeordnet werden.
Als Schlussel fur einen Eintrag im MemoryStore fungiert ein Ruby-Symbol.
Der Wert zu einem Schlussel im MemoryStore ist ein Array, um beliebig viele Da-
tensatze eines bestimmten Schlussels zu speichern. Jeder Eintrag in diesem Array ist
ein Hash. Die Inhalte des Hashes sind die verschiedenen Details eines Datensatzes,
die erfasst werden sollen. Diese sind fur jeden Schlussel individuell - enthalten aber
immer einen Zeitstempel. Beispiele fur die Rohdaten, die in Redis abgelegt werden,
finden sich in Anhang B.1.
Erreicht der Puffer die im Konfigurationsmodul angegebene Anzahl von Datensatzen,
so fuhrt er die Methode “push” des Moduls Backend aus. War die Ubertragung er-
folgreich, wird der Puffer anschließend komplett zuruckgesetzt. War die Ubertragung
nicht erfolgreich, so wird der Puffer nicht geleert. Wenn der Puffer wieder die konfi-
gurierte Anzahl an Eintragen erreicht, wird nochmals versucht den gesamten Puffer
zu ubertragen.
Trackbuddy : : Buf f e r . i n s t a l l ( { : u se r => 12345})
Listing 8: Aufruf des Puffers fur das Zahlen einer Installation
Die sammelnden Module rufen eine Methode, die der Eigenschaft entspricht, die
erfasst werden soll im Kontext des Buffer-Moduls auf. Innerhalb des Moduls ist die
Methode “method missing” (Anhang C.1.3) implementiert. So wird ein Fallback ge-
7 Implementierung Seite 49
boten, wenn die Methode, welche ausgefuhrt werden soll, nicht gefunden wird. Durch
den Methodennamen, der nicht gefunden wird, kennt der Puffer den Schlussel, unter
dem der erfasste Datensatz abgelegt werden soll.
Alternativ hatte ein Eintrag in einen Puffer auch mit einer eigenen Methode im-
plementiert werden konnen. Dieser liegt dann aber eine kompliziertere Syntax, mit
mehr als einem Argument, zugrunde.
Der ubergebene Hash wird um einen Zeitstempel erganzt, bevor er abgelegt wird.
Dies wird hier einmal zentral realisiert, damit dieser nicht in jedem erfassenden Mo-
dul angehangt werden muss.
Die Fehlerbehandlung findet ebenfalls im Puffer statt. Das Backend meldet mit ei-
nem Wahrheitswert, ob die Ubertragung erfolgreich war. War sie es nicht, so setzt
der Puffer die, in Kapitel 5.6.2 beschriebene, Logik zur Eskalation um. Ein Backend
muss sich auf diesem Weg nicht um die Eskalation bei einem Fehler kummern, dies
kann der Puffer zentral fur alle moglichen Backends ubernehmen.
Trackbuddy : : Buf f e r . put ( : i n s t a l l , { user => 0})
Listing 9: Moglichkeit fur alternative Syntax zum Eintrag in Puffer
7.3.6. Backend
In trackbuddy ist bereits eine beispielhafte Implementierung eines Backends inte-
griert. Dieses kann als Gerust dienen, um selbst ein Backend zu entwickeln. Das
bereits integrierte Backend bietet eine Basislosung, die alle erfassten Daten in die
Logdatei der Rails-Anwendung schreibt. Die Implementierung des Redis-Backends
ist in Kapitel 7.5 beschrieben.
7.3.7. Helper
Dieses Modul stellt Helper fur Views und Controller zur Verfugung. Es beinhaltet,
in die Untermodule View und Controller unterteilt, folgende Funktionalitat:
View: Template fur Veroffentlichungscallback Dies ist ein Template, welches
auf jeder Seite eingefugt werden muss, an welcher manuelle Pinnwand-Veroffentli-
chungen erfasst werden sollen. Der Callback, den Facebook nach Abschicken des
Javascript-Dialogs fur eine Veroffentlichung absendet, muss auf diese Funktion ge-
setzt werden. Zusatzlich kann die Art der Veroffentlichung als Parameter ubergeben
werden.
7 Implementierung Seite 50
<s c r i p t >
f unc t i on t r a c k i n g c a l l b a c k ( s r c type ) {var ajax = new Ajax ( ) ;
a jax . responseType = Ajax .RAW;
ajax . post ( ’ http :// apps . facebook . com/ t e t r i s g i f t s / middleware
/ pub l i sh /? s r c type=’ + src type ) ;
}</s c r i p t >
Listing 10: Helper-Methode mit Template “trackingcallback”
View: URL-Generierung Es muss ein moglichst einfacher Weg gefunden werden,
um extern angezeigte Links, sogenannte URLs (Uniform Resource Locator), nach
einem Schema, wie in Kapitel 5.2 beschrieben, zu manipulieren. Hier soll erfasst wer-
den, uber welche Links, die nach außen sichtbar sind, Benutzer in die Anwendung
gezogen werden. Rails bietet bereits URL-Helper fur das Generieren von Links. Die-
se haben beispielsweise das Format root url(: parameter => 42). So wird eine URL
wie beispielsweise http : //apps.facebook.com/anwendungsname/?parameter = 42
generiert. Das Ziel ist, die fur das Tracking benotigten Parameter anzuhangen.
Um die Parameter anzuhangen, wird der Rails-UrHhelper von einer eigenen Metho-
de umschlossen. Diese beinhaltet Typ und Art der Veroffentlichung. Beispielsweise
gibt es fur Veroffentlichungen des Typs publish, der von der Art win ist, eine Me-
thode publish win, welche die ursprungliche URL beinhaltet.
pub l i sh win ( r o o t u r l ( : parameter => 42) )
Listing 11: Anwendung der View-Helper zur URL-Generierung
Um dieses Verhalten zu erreichen, ohne fur jeden Typ und jede Art (die nicht
vorher definiert werden), eine eigene Methode erstellen zu mussen, wird auf “me-
thod missing” (Anhang C.1.3) zuruckgegriffen.
In diesem Fall muss “method missing” fur die Klasse ActionView::Base implemen-
tiert werden. Dies geschieht an der Stelle, an der URLs angewendet werden. Den
ubergebenen ursprunglichen URLs werden die Parameter, die sich aus dem aufge-
rufenen nicht vorhandenen Methodennamen ergeben, angehangt.
Eine Alternative ist es, die Parameter direkt an den vorhanden URL-Helpern an-
zuhangen.
7 Implementierung Seite 51
r o o t u r l ( : parameter => 42 , : s r c r e f => ” pub l i sh ” , : s r c type =>
”new” )
Listing 12: Mogliche Alternative zur URL-Generierung
Die Funktionalitat, die implementiert wurde, schrankt diese weitere Moglichkeit
nicht ein. Auf diesem Wege werden genauso gultige URLs generiert. Die imple-
mentierte Funktionalitat bietet lediglich einen weiteren Weg.
Es ist nicht zwingend notwendig, “method missing” von Actionview::Base zu uber-
schreiben. Anstelle dessen hatte auch eine eigene, lediglich uber den Gem verfugba-
re Klasse die Methode anbieten konnen. Aufrufe auf diese mussten mit dem Prafix
des Klassennamens geschehen. Diese Methode bedeutet bei der Integration einen
erhohten Aufwand.
Trackbuddy : : Helper . pub l i sh win ( r o o t u r l ( : parameter => 42) )
Listing 13: Verworfene Alternative zur URL-Generierung
Controller: anwendungsspezifische Datenerfassung Wie in der Anforderung zur
anwendungsspezifischen Datenerfassung (Kapitel 5.1.9) definiert, muss die Methode
track action in den Controllern der Anwendung vorhanden sein. Zu diesem Zweck
wurde sie in einem Modul definiert, das von trackbuddy im ApplicationController
der Anwendung eingebunden wird.
Einbindung Die Methoden der Module werden fur die Anwendung verfugbar ge-
macht, indem sie per include dem ApplicationController bzw. der ActionView
von der Anwendung eingefugt werden. Dies geschieht innerhalb des Railties-Moduls
(Kapitel 7.3.8). Die beiden Klassen haben anschließend die Methoden der Module,
die in sie eingebunden wurden.
ActionView : : He lpers . send ( : inc lude , Trackbuddy : : Helper : : View )
Act i onCont ro l l e r : : Base . send ( : inc lude , Trackbuddy : : Helper : :
C o n t r o l l e r )
Listing 14: Einbindung der Helper
Die Methode “send” ruft die als Symbol ubergebene Methode, zusammen mit dem
ubergebenen Argument, im Kontext der Klasse auf. Alternativ hatte auch eine
ausfuhrlichere Syntax verwendet werden konnen, welche aber umstandlicher zu schrei-
ben ist.
7 Implementierung Seite 52
module : : Ac t i onCont ro l l e r
class Base
in c lude Trackbuddy : : Helper : : C o n t r o l l e r
end
end
Listing 15: Alternative Syntax fur Einbindung der Helper
Die Alternative Syntax empfiehlt sich, wenn mehr als ein einziger Aufruf auf die
Klasse gemacht werden muss. Die gesamten Helper konnten auch direkt im Kontext
der Klasse definiert werden. Auf so einem Weg wird sehr viel Programmcode in den
Railtie hinein verlagert. Die vom Railtie aufzurufenden Klassen in einem eigenen
Modul, welches anschließend eingebunden wird, verhelfen zu einer ubersichtlicheren
Struktur.
7.3.8. Railtie
Dies ist das Modul innerhalb des Gems, welches von Rails wahrend des Bootstrap-
Prozesses einer Anwendung eingebunden wird. Hier werden die einzelnen Middleware-
Klassen des Moduls Hit in den Middleware-Stack integriert, damit sie bei jedem
Seitenaufruf durchlaufen werden.
Auch werden hier die Module mit den Helper-Methoden fur Controller und View,
mittels “include” (Anhang C.1.5), in die Anwendung eingebunden.
Railties werden verwendet, weil es sich dabei um einen stabilen Hook handelt. Theo-
retisch konnten die Helper direkt im Code des Gems in den entsprechenden Klassen
eingebunden werden. Dieser wird immer ausgefuhrt, wenn die Anwendung initial
gestartet wird. Hier kann es vorkommen, dass Klassen und Module, die verwendet
werden sollen, zu dem Zeitpunkt nicht geladen sind. Railties werden wahrend dem
Bootstrapping einer Anwendung ausgefuhrt, nachdem alle Gems geladen sind.
7.3.9. Support
Dieses Modul enthalt zwei Methoden, die an mehreren Stellen von anderen Modulen
gebraucht werden.
anonymize Diese Methode bekommt als Argument eine Nutzer-ID. Die ID wird,
sofern der Parameter zur Anonymisierung in der Konfiguration gesetzt wurde, mit-
tels einem MD5-Hash anonymisiert. Ist der Parameter nicht gesetzt, wird die ID in
ihrer ursprunglichen Form zuruckgegeben.
7 Implementierung Seite 53
“anonymize” wird an jeder Stelle aufgerufen an der, je nach Konfiguration, ein Pa-
rameter anonymisiert werden soll.
blocked uri? Um zu definieren, welche URI nicht erfasst werden sollen, konnen
diese in der Konfiguration angegeben werden. Diese Methode uberpruft, ob die uber-
gebene URI in der Konfiguration aufgefuhrt ist.
Der Ruckgabewert der Methode blocked uri? ist ein Wahrheitswert. Falsch wird
zuruckgeliefert, wenn die zu uberprufende URI nicht mittels der Konfiguration von
der Datenerfassung ausgeschlossen wurde. Enthalt die ubergebene URI, auch ledig-
lich partiell, eine der als geblockt definierten URI, wird Wahr zuruck gegeben.
Ist beispielsweise images als geblockte URI in der Konfiguration eingetragen, wird
auch der URI /images/Bild.jpg nicht als gultiger Seitenaufruf erfasst. Dies ist not-
wendig, da Bilder, wenn Rails sie nicht als statische Datei ausliefern kann, mittels
des Routings von Rails aufgelost werden.
7.4. Fehlerbenachrichtigung
Zur Fehlerbenachrichtigung der Entwickler wird bei buddybrand der Drittanbieter
Hoptoad benutzt (Anhang E). Hoptoad bietet Bibliotheken fur die meisten im Web
verwendeten Programmiersprachen. Fehler, die uber die API von Hoptoad eingegan-
gen sind, werden uber mehrere Projekten aggregiert dargestellt.
Fur Ruby im allgemeinen gibt es den Gem toadhopper, fur Rails im speziellen den
Gem HoptoadNotifier. Der HoptoadNotifier fur Rails aktiviert sich, wenn eine Rails-
Anwendung auf eine Exception stoßt, d.h. die Seite nicht ausgeliefert werden konnte.
Im Gegensatz dazu kann der allgemein fur Ruby programmierte Gem toadhopper die
API von Hoptoad direkt und manuell anzusprechen.
So bietet sich die Moglichkeit einen Fehler zu melden, bei dem die Seite dennoch
ausgeliefert werden kann. Da die Nichtverfugbarkeit des Tracking-Servers eben einen
solchen Fall darstellt, in dem der Besucher keinen Fehler sehen soll, empfiehlt sich
toadhopper, um dieses Poblem zu melden.
Jede Anwendung, die mittels Hoptoad uberwacht wird, bekommt von dem Dienst
einen API-Schlusel welcher in einem Initializer-Script hinterlegt werden muss. Diese
Datei muss von trackbuddy ausgelesen werden, um mittels toadhopper die Fehler-
meldung im Kontext der richtigen Anwendung zu ubermitteln. Alternativ konnte
der API-Key auch in die Konfigurationsdatei von trackbuddy geschrieben werden.
Da der Schlussel ohnehin hinterlegt ist, wurde diese Methode gewahlt, um nicht
gegen DRY zu verstoßen.
7 Implementierung Seite 54
begin
r a i s e ”Kaboom ! ”
rescue => e
r e q u i r e ’ toadhopper ’
Toadhopper ( ”YOURAPIKEY” ) . post ! ( e )
end
Listing 16: Toadhopper-Schnittstelle (Quelle: Anhang F.2.4)
Die Schnittstelle von Toadhopper ist lediglich ein einziger Aufruf, welcher als Argu-
ment einen API-Schlussel und eine Exception annimmt.
7.5. trackbuddy-redis
Das Backend ist, wie in Kapitel 9.1.1 beschrieben, in einem eigenen Gem imple-
mentiert. Dieser Gem ist fur die Ubertragung der Daten zu einem Tracking-Server
zustandig. Das Modul soll moglichst einfach austauschbar sein. Fur das Absenden
wird die Methode “push” aufgerufen, welche die Daten ubertragt. War die Uber-
tragung erfolgreich, ist der Ruckgabewert true, andernfalls false.
Es muss sicher gestellt werden, dass das Backend-Modul richtig implementiert wur-
de, da es austauschbar sein soll. Hierfur wird uberpruft, ob die Methode “push”
vorhanden ist, bevor der Puffer die Methode aufruft.
Das Sequenzdiagramm in Abbildung 16 bildet die Verarbeitung eines kompletten
Seitenaufrufes ab. Naher ausgefuhrt wird an dieser Stelle lediglich die Erfassung
einer Impression. Die anderen in die Middleware eingehangten Klassen uberprufen
spezielle Parameter und erfassen andere Daten. Bei dem Status des Diagramms ist
die Anwendung bereits initialisiert sowie die Railties geladen.
7.5.1. Namespace
Der Namespace ergibt sich durch das Schema, welches in Kapitel 5.6 definiert wurde.
Der Name der Anwendung, welche den Gem geladen hat, kann uber den Root-
Namespace der Anwendung herausgefunden werden. So ist an dieser Stelle keine
explizite Konfiguration notwendig, da diese Eigenschaft in der Anwendung definiert
wird.
” trackbuddy : ” + : : Ra i l s . a p p l i c a t i o n . class . t o s . s p l i t ( ’ : : ’ ) .
f i r s t . downcase
Listing 17: Generierung des Tracking-Namespaces
7 Implementierung Seite 55
Abbildung 16: Erfassung eines Seitenaufrufes mit Ubertragung auf Tracking-Server
7 Implementierung Seite 56
7.5.2. Schnittstelle
Redis ist eine Key-Value-Datenbank. Eine vollstandige Befehlsreferenz findet sich in
Anhang F.3.1. Es gibt folgende Datentypen, die einem Schlussel zugeordnet werden
konnen:
• Strings
• Lists
• Sets
• Sorted sets
• Hashes
Sets sind unsortierte Sammlungen von Strings (Anhang F.3.2). Diese werden fur das
Tracking verwendet. Eine spezielle Sortierung (Sorted sets) oder Reihenfolge (Lists)
ist dabei nicht notig, weil die einzelnen Datensatze bereits uber einen Zeitstempel
verfugen. Dieser reicht aus, da die Daten ohnehin lediglich in ihrer Gesamtheit auf-
bereitet werden.
Um auf Redis zuzugreifen wird der Gem redis verwendet. Dieser implementiert die
Methoden der Befehlsreferenz und bietet sie mittels Methoden eines mit Redis.new
erzeugten Objektes an (Anhang F.2.5). Erstellt werden kann dieses Objekt unter An-
gabe der Server, auf die die Daten verteilt werden, mittels der Klasse RedisFactory.
Anschließend wird der Namespace initialisiert und in diesen konnen Objekte, un-
ter Angabe ihres jeweiligen Schlussels, in einem Set abgelegt werden. Diese drei
grundsatzlichen Schritte sollen in folgendem Minimalbeispiel veranschaulicht wer-
den.
@r = RedisFactory . c r e a t e ( [ ”db . buddybrand . de” , ” f e 1 .
buddybrand . de” , ” f e 2 . buddybrand . de” ] )
@data = Redis : : Namespace . new( ”namespace” , : r e d i s => @r)
@data . sadd ”key” , ” value ”
Listing 18: Redis-Schnittstelle
Es muss sichergestellt werden, dass eine exakte Datenerhebung (Kapitel 5.6.1) statt-
findet. Innerhalb der Schleife, die die Datensatze von trackbuddy ubertragt, findet
aus diesem Grund eine Fehlerbehandlung statt. Tritt ein Fehler bei der Ubertragung
auf, wirft der Redis-Gem eine Exception aus. Einzelne Datensatze werden geloscht,
wenn keine Exception auftritt und somit die Ubertragung erfolgreich war. Tritt
hingegen bei einem Datensatz eine Exception auf, wird die Ubertragung danach
komplett abgebrochen.
7 Implementierung Seite 57
user CPU system CPU total CPU reale ZeitObjekt 0.820000 0.190000 1.010000 1.579243JSON 0.820000 0.270000 1.090000 1.666429
Tabelle 3: Ergebnis vom Redis-Benchmark (Zeit in Sekunden)
7.5.3. Datenformat
Durch den Redis-Gem konnen direkt komplette Ruby-Objekte gespeichert werden.
Diese sind auch nach dem Auslesen wieder Objekte. Eine Alternative fur das Able-
gen von gesamten Objekten ist es, die Objekte in JSON-Notation umzuwandeln.
Um die hochstmogliche Performance zu erreichen, wurde ein Benchmark durch-
gefuhrt. Untersucht wurde, ob es schneller ist, die Objekte explizit durch den Gem in
JSON umzuwandeln. Der Benchmark ist unter Anhang D zu finden. Die Ergebnisse,
dargestellt in Tabelle 3, sprechen dafur, dass es schneller ist dem Redis-Gem direkt
die Ruby-Objekte zu ubergeben. Wie sich erst nach dem Benchmark heraus gestellt
hat, ist das direkte Speichern von Objekten ausschließlich in Ruby 1.9 moglich. Un-
ter Ruby 1.8 konnen keine kompletten Objekte in Redis gespeichert werden. Damit
der Gem nicht abhangig von einer Ruby-Version ist, mussen die erfassten Daten
explizit in eine JSON-Notation umgewandelt werden.
Durch dieses Vorgehen wird gleichzeitig auch Plattformneutralitat geschaffen. Die
Daten, welche in Redis gespeichert werden, konnen auch von Clients in anderen
Programmiersprachen ausgelesen werden.
7.6. Initialisierung
Die Gems einer Rails-Anwendung werden in alphabetischer Reihenfolge geladen. So
wird sichergestellt, dass der Gem buddy, bei welchem sich trackbuddy als Observer
registriert, geladen ist.
Wird trackbuddy geladen, so ladt dieser zuerst seine eigenen Module. Anschließend
werden die Konfigurationsdateien von trackbuddy und Hoptoad, die innerhalb der
Anwendung liegen, eingelesen. Wenn keine Konfigurationsdatei trackbuddy.yml in
der Anwendung hinterlegt ist, werden vorbestimmten Werten geladen.
7.6.1. Railties
Die Initialisierung der Railties geschieht nicht manuell. Rails uberpruft auf das Vor-
handensein einer Implementierung von Rails::Railtie, sofern diese Klasse durch
den Gem per “require” eingebunden wurde. Ist eine solche Implementierung vorhan-
den, wird diese eingebunden.
7 Implementierung Seite 58
Abbildung 17: Initialisierung von trackbuddy
7 Implementierung Seite 59
7.6.2. Backend
Als Abschluss der Initialisierung des Gems, nach dem alles andere inklusive der
Konfiguration geladen wurde, wird das spezifische Backend geladen. Hierbei ist auf
einen Fallback zu achten, damit kein Fehler ausgeworfen wird, wenn das in der Kon-
figuration angegebene Backend nicht geladen werden kann.
Wichtig ist, dass die Implementierung des Backends als letztes geladen wird. An-
schließend kann die Methode “push” des Backend-Moduls uberschrieben werden.
Wenn der neue Gem diese Methode nicht uberschreibt, andert sich fur trackbuddy
nichts, da die bereits implementierte Methode verwendet wird.
Kann die Implementierung des Backends nicht geladen werden, so wird dies den
Entwicklern wie jeder andere Fehler uber Hoptoad mitgeteilt. Die Anwendung nutzt
auch in diesem Fall dann die bereits mitgelieferte Implementierung des Backends.
Um absolut sicher zu gehen, dass in einem solchen Fall kein Fehler auftritt, wird vor
jeder Ubertragung uberpruft ob die Methode “push” vorhanden ist. Hierfur wird
der unter Anhang C.1.5 beschriebene Mechanismus benutzt.
7.7. Generator
Generatoren, mit denen Dateien und Dateigeruste innerhalb von Rails-Anwendungen
erzeugt werden, sind durch eine Konvention von Rails festgelegt. Fur einen Genera-
tor mit dem Namen trackbuddyconfig wird folgende Ordnerstruktur benotigt:
|−− l i b
| |−− gene ra to r s
| | ‘−− t rackbuddyconf ig
| | |−− templates
| | | ‘−− trackbuddy . yml
| | ‘−− t rackbuddycon f i g gene ra to r . rb
Listing 19: Ordnerstruktur fur Rails Generator
Anschließend kann die Konfigurationsdatei durch einen solchen Generator mittels
des Befehls rails generate trackbuddyconfig erstellt werden. Diese wird an ei-
nem im Generator definierten Ort innerhalb der Anwendung abgelegt.
8 Integration Seite 60
8. Integration
Um die Datenerfassung in eine bestehende Anwendung zu integrieren, sind drei
Schritte notwendig.
1. Installation des Gems
2. Einstellungen in Facebook
3. Anpassen der Anwendung
Diese drei Schritte werden im Folgenden erlautert. Zusatzlich muss bereits Hoptoad
installiert sein, weil ansonsten die Fehlerbenachrichtigung nicht funktioniert.
Erganzt werden konnen diese Schritte anschließend mit einer eigenen Backend-
Implementierung, beschrieben in Kapitel 9.2.
8.1. Installation des Gems
Gem eintragen Seit Rails 3 werden alle Gems in einem zentralen Gemfile eingetra-
gen. Ist es ein Gem, welcher nicht offentlich verfugbar ist, muss die Quelle des Gems
angegeben werden. In diesem Fall wird die Quelle in Form eines Git-Repositories
eingetragen. Der von trackbuddy benutzte weitere Gem toadhopper muss an dieser
Stelle nicht explizit eingebunden werden. Diese Abhangigkeit wird aufgelost, da sie
in der Spezifikation des Gems, der Datei trackbuddy.gemspec, (Anhang 7.1) ein-
getragen ist.
Der Gem mit der Implementierung des Backends muss auch manuell eingebunden
werden, da es sich nicht um einen offentlich verfugbaren Gem handelt.
gem ’ trackbuddy ’ , : g i t => ’ g i t@g i t . buddybrand . de : buddybrand/
trackbuddy . g i t ’
gem ’ trackbuddy−r e d i s ’ , : g i t => ’ g i t@g i t . buddybrand . de :
buddybrand/trackbuddy−r e d i s . g i t ’
Listing 20: Zusatzliche Eintrage in Gemfile mit Eintrag fur trackbuddy
Auf Git kann mittels den Protokollen SSH, git und HTTP/HTTPS zugegriffen wer-
den (Swicegood, 2008, S. 91-93). Mittels SSH loggt man sich direkt auf dem Datei-
system des Servers ein, von dem das Repository bezogen wird. Diese Moglichkeit
ist bei buddybrand und im generellen ublich, wenn es sich um ein Repository han-
delt, auf das nur eingeschrankte Benutzer Zugang haben. Das Git-eigene Protokoll,
8 Integration Seite 61
welches auf Geschwindigkeit hin entwickelt wurde, bereitet Probleme mit Firewalls,
weshalb es auch bei buddybrand nicht eingesetzt wird. Eine Auslieferung des Repo-
sitories uber HTTP ist wegen der schlechten Effizienz nur eine Notlosung.
Anschließend mussen die in dem Gemfile eingetragenen Gems mit dem Kommando
bundle install installiert werden. bundler schaut daraufhin, welche Gems bereits
im System installiert sind sowie welche neu bezogen werden mussen.
Generierung der Konfiguration Der Generator fur die Konfigurationsdatei kann
aufgerufen werden um diese innerhalb des Ordners config anzulegen. Die Konfigu-
rationsdatei kann an die speziellen Anforderungen der jeweiligen Anwendung ange-
passt werden. Dies ist nicht zwingend notwendig, da der Gem ohne Konfigurations-
datei mit vordefinierten Werten arbeitet. Die vordefinierten Werte ließt der Gem
direkt aus dem Template der Datei, welche auch als Basiskonfiguration erzeugt wer-
den wurde.
% r a i l s generate trackbuddyconf ig
c r e a t e c o n f i g / trackbuddy . yml
Listing 21: Generierung der Konfiguration
Neustart Anschließend muss die Anwendung neu gestartet werden.
Weitere Schritte sind nicht notwendig. Der Namespace fur Redis muss nicht ex-
plizit zuvor erzeugt werden. Es ist ausreichend, Werte mit den jeweiligen Schlusseln
abzulegen.
8.2. Facebook-Einstellungen
Fur ein vollstandiges Tracking sind auch zwei Angaben innerhalb von Facebook zu
tatigen. Facebook kann nach einer Installation, bzw. nach einer Deinstallation, eine
Adresse auf dem Anwendungsserver aufrufen. Welche Adresse dies sein soll, kann in
den Anwendungseinstellungen unter dem Punkt der Authentifizierung (Abbildung
18) definiert werden. Diese darf keine Adresse innerhalb von Facebook sein, sondern
muss den Server direkt ansprechen.
8 Integration Seite 62
Abbildung 18: Post-Remove-Callback URL
8.3. Anpassung der Views
8.3.1. Setzen von Referrer-Parametern in Links
Die Pfade von URLs an den Stellen, an welchen Links generiert werden, die nach
außen sichtbar sind, mussen modifiziert werden.
In der Beispielanwendung sind das folgende Links:
• Annehmen der Einladung
• Pinnwand-Veroffentlichungen
• Inhalt der E-Mails
Links in diesen viralen Kanalen mussen zur Datenerfassung zusatzlich die Parameter
“srcref” und “srctype” tragen, um den Weg zu erfassen, wie ein Benutzer wieder in
die Anwendung kommt.
Eine exemplarische Anpassung von einer Einladung ist in Anhang B.5 zu finden.
8.3.2. Callback-Aufruf bei manueller Pinnwand-Veroffentlichung
Da Facebook eine manuelle Pinnwand-Veroffentlichung nicht mitteilt, benotigt die
Anwendung diese Information per Ajax-Callback. Manuelle Veroffentlichungen wer-
den per FBJS-Popup ausgelost. In der Beispielanwendung ist dies der Fall, wenn ein
Nutzer ein Geschenk verschickt, aber keine erweiterte Berechtigung vergeben hat
(Abbildung 8 in Kapitel 4.1.5).
8 Integration Seite 63
Die Integration dessen teilt sich in zwei Schritte:
1. Aufruf des View-Helpers, welcher Javascript mit Callback-Funktion liefert
2. Ubergabe der Callback-Funktion an FBJS-Funktion zur Veroffentlichung
Die Callback-Funktion ist ein optionaler-Parameter, der der FBJS-Funktion uber-
geben werden kann. Dieser wird von Facebook ausgefuhrt, wenn der Benutzer die
Veroffentlichung abschickt. Eine beispielgebende Anpassung einer manuellen Veroffent-
lichung mit View-Helpern und dem Callback-Aufruf findet sich in Anhang B.6.
9 Erweiterung Seite 64
9. Erweiterung
Im Folgenden werden die verschiedenen Moglichkeiten um den Gem und dessen
Funktionalitat zu erweitern diskutiert.
9.1. Erweiterung des Gems
Um den Gem zu erweitern bieten sich 3 grundlegend verschiedene Moglichkeiten.
Alle 3 werden untereinander verglichen.
9.1.1. Weiterer Gem mit Abhangigkeit
Um vollstandige Freiheit bei der Erweiterung zu haben, kann diese auch als eigener
Gem umgesetzt werden. Der neue Gem muss trackbuddy als Abhangigkeit angeben.
Anschließend konnen die Methoden uberschrieben werden, die auf anderem Wege
implementiert werden sollen. Bei den Methoden, die ein weiterer Gem nicht uber-
schreibt, wird auf die Ursprunglichen von trackbuddy zuruckgegriffen.
Um dieses Verhalten zu erreichen, wird die Eigenschaft von Ruby verwendet, eine
Klasse oder ein Modul in mehreren Dateien definieren zu konnen. Wird der Mo-
duldefinition in einer Datei, welche spater geladen wird, eine Methode mit gleicher
Signatur hinzugefugt, so uberschreibt diese die fruhere Methode. Dies ist der Grund,
warum der Gem mit einem alternativen Backend nach dem eigentlichen trackbuddy
geladen werden muss.
Vorteil dieser Methode ist es, dass kein Aufwand entsteht, den originalen Gem ak-
tuell zu halten. Aktualisierungen, welche die Datenerfassung betreffen, mussen aus-
schließlich in trackbuddy implementiert werden.
Soll die alte Version einer Methode nicht uberschrieben werden, kann auf das Ver-
ketten von Methoden (Anhang C.1.4) zuruckgegriffen werden. In diesem Fall wird
ein Alias fur die alte Methode erstellt und dies Uberschriebene wieder aufgerufen.
9.1.2. Hooks und Handler
Der entwickelte Gem kann Hooks anbieten. Diese sind an folgenden Stellen denkbar:
• Nach der Erfassung jedes Datensatzes
• Nach der Erfassung eines speziellen Datensatzes (z.B. die Erfassung einer ver-
sendeten E-Mail)
• Vor / direkt nach der Initialisierung
• Vor / nach Ubertragung der Daten an den Tracking-Server
9 Erweiterung Seite 65
Anschließend konnen innerhalb der Anwendung Handler geschrieben werden, die
sich in diese Hooks einhangen. In diesem Fall fließt damit Programmcode der Da-
tenerfassung in die Anwendung mit ein. Dies widerspricht dem Ziel, die Anwendung
moglichst wenig zu beeinflussen. Muss die Datenerfassung an vielen Stellen fur eine
spezielle Anwendung angepasst werden, empfiehlt sich das Erstellen eines weiteren
Gems mit Abhangigkeit auf den originalen Gem (Kapitel 9.1.1). So kann alles An-
zupassende uberschrieben werden.
9.1.3. Fork
Als Fork wird die Abspaltung eines Gems (bzw. auch eines Softwareprojektes im
Allgemeinen) bezeichnet, welcher auf der Basis eines gemeinsamen Quellcodes eine
andere Entwicklungsrichtung einschlagt. Der Nachteil eines Forks, im Gegensatz zu
dem Erstellen eines weiteren Gems (Kapitel 9.1.1), liegt in der Wartung des Forks.
Wird am originalen Gem der Code modifiziert, mussen die Anderungen auch in den
Fork zuruckfließen - sofern gewunscht. Auf jeden Fall aber muss der Quellcode von
zwei Projekten synchronisiert werden.
Ein Fork empfiehlt sich nicht als einfache Erweiterung, sondern, wenn der Gem in
einem neuen Produkt enden soll. Beispielsweise kann dies der Fall fur eine Datener-
fassung bei Anwendungen anderer Plattformen als Facebook sein.
9.2. Implementierung eines eigenen Backend-Moduls
Das Backend-Modul kann je nach Anwendungsfall neu geschrieben werden. Fur fol-
gende Anwendungsfalle konnten alternative Backends verwendet werden:
• Anbindung an SNMP-Software
• Speicherung in ein RDBMS (Relational Database Management System)
• Ubergabe der Daten an eine REST-API
• Speicherung mittels Webservice
Zur Implementierung eines eigenen Backends muss ein neuer Gem erstellt werden.
Dieser benotigt im einfachsten Fall eine einzige Datei. In dieser kann das im fol-
genden Listing aufgefuhrte Gerust mit Funktionalitat gefullt werden. Anschließend
muss der neue Gem Backend installiert und in der Konfiguration von trackbuddy
angegeben werden.
9 Erweiterung Seite 66
module Trackbuddy
module Backend
class << s e l f
def push b u f f e r
return true
end
end
end
end
Listing 22: Gerust fur weiteres Backend-Modul
10 Zusammenfassung und Ausblick Seite 67
10. Zusammenfassung und Ausblick
In der Bachelor-Thesis wurde die Entwicklung eines Gems zur automatischen Da-
tenerfassung von Facebook-Anwendungen in Ruby on Rails beschrieben. Die Arbeit
wurde fur die Firma buddybrand erstellt.
Zur Einleitung des Themas werden am Anfang die Elemente erklart, die wichtig sind,
um fur Facebook zu programmieren. Bevor die Anforderungen aufgestellt werden,
wird eine Beispielanwendung eingefuhrt, um zu den geforderten und zu implemen-
tierenden Punkten Beispiele zu liefern. Vor der Implementierung wird allgemein die
Architektur beschrieben. Besonderheiten, die sich durch Ruby, und Rails, ergeben,
werden ebenso beleuchtet wie Alternativen. Den Abschluss bieten Informationen zur
Integration und Erweiterung des Gems.
Der Anhang zu diesem Dokument bietet unter anderem Material, welches Metapro-
grammierung in Ruby behandelt, da dieses nicht ein direkter Teil der Thesis ist.
Internetquellen und Gesprachsprotokolle, die fur den Text von Relevanz sind, sind
ebenfalls im Anhang zu finden.
Der Gem kann so wie er hier entwickelt wurde, in den momentanen und den in Zu-
kunft bei buddybrand entwickelten Anwendungen eingesetzt werden.
Fur die neue Graph-API (Kapitel 3.3.6), muss der Gem angepasst werden. Zu dem
jetzigen Zeitpunkt gibt es keine Anwendung von buddybrand, welche diese API be-
nutzt. Um dafur kompatibel zu sein, muss das Modul welches die REST-API erfasst,
um die neuen Aufrufe erganzt werden. Alternativ kann ein weiteres Modul fur die
Graph-API
Der Gem kann einfach auf ein neues Backend angepasst werden, indem dafur ein
eigener Gem geschrieben wird, der in der Konfiguration angegeben wird.
Zu Demonstrationszwecken innerhalb des Unternehmens ist trackbuddy in die am
hochsten frequentierte Anwendung uLikeMe integriert worden. Eine beispielhafte
Auswertung der Daten, die gewonnen werden konnten, ist in Anhang B.2 zu finden.
Diese Demonstration lieferte nach der Integration Daten, mittels denen Verbesserun-
gen an der Anwendung realisiert werden konnten. Ergebnisse und daraus abgeleitete
Aktionen sind ebenfalls in diesem Anhang zu finden.
Als konkrete nachste Schritte muss von buddybrand eine vollstandige automatisierte
Auswertung der Daten geschehen. Diese konnte im Optimalfall so aussehen, dass
der Kunde Zugang zu einem Online-Portal bekommt und die Auswertung seiner
Anwendung in Echtzeit beobachten kann.
Lessons learned Seite 68
Lessons learned
Das Programmieren von Facebook-Anwendungen war mir bereits vor der Thesis
bekannt. In Ruby on Rails habe ich wahrend des Wintersemesters 2009/2010 fur
buddybrand an solchen Anwendungen gearbeitet.
Den Sourcecode des entwickelten Gems habe ich in einem Git-Repository verwaltet.
Gehostet wurde das Repository auf einem der Server von buddybrand. Hier waren
auch die zusatzlichen Anwendungen abgelegt.
Fur das Management meiner Aufgaben und Notizen habe ich die von buddybrand
intern verwendete Groupware Basecamp (http://basecamphq.com/) benutzt. Die-
se hat mir sehr zugesagt, ich wurde sie jederzeit wieder verwenden.
Bevor ich diese Thesis begonnen hatte, habe ich bis dato nie eine Erweiterung zu
Ruby oder Rails selbst programmiert. Die Thesis war eine willkommene Motivation,
mich an das Thema heranzuwagen.
Ich habe den grundsatzlichen Aufbau von Plugins und Gems kennengelernt. In erster
Linie hat sich damit eine Hemmschwelle abgebaut. Viele der Mechanismen, die ich
wahrend der Thesis erlernt habe, kann ich auch weiterhin verwenden. Das Wissen,
welches sich mir an Metaprogramming in Ruby eroffnet hat, bot ganz neue Ansich-
ten, aber auch Anspruche, die ich an die Sprache hatte.
Das Kennenlernen der Erweiterungsmoglichkeiten von Rails, wie die Middleware ab-
gearbeitet wird, aber auch wie vorhandene Funktionalitaten erganzt oder abgefangen
wird, bot mir einen tiefen Einblick hinter die Kulissen. Gerade, da das Tracking eine
so umfassende Sache ist, die fast an allen Aspekten von Rails beteiligt ist, musste
ich mich auch mit all diesen beschaftigen.
Auch mit der Redis-Datenbank hatte ich vor der Thesis keine Erfahrungen. Fur eine
“einfache” Key-Value-Datenbank bietet sie geradezu erschreckend viele Moglichkei-
ten, Daten zu speichern. Hinzu kommt auch viele Befehlen, die auf der Konsole oder
in Ruby beherrscht werden mussen, um sie umfassend anzusprechen.
Wahrend des Schreibens der Thesis habe ich immer nach Alternativen gesucht, wie
ein Vorhaben am elegantesten umgesetzt werden kann. Unter anderem auch um die
Pramisse einzuhalten, die Anwendung moglichst wenig zu beeinflussen. Ich habe
stets die Absicht verfolgt, diese verschiedenen Aspekte in die Thesis einfließen zu
lassen. Anfangs setzte ich diese Absicht zu selten in die Tat um, weshalb ich auch
Herrn Prof. Dr. Winckler dankbar bin, dass er mich mehrmals darauf aufmerksam
machte. Dies motivierte mich dahingehend, dass ich mich auch mit bereits zu Papier
gebrachten Teilen der Arbeit weiterhin beschaftigte.
Etwas schade ist, dass gerade fur Rails 3 sehr wenig Literatur vorhanden ist. Rails
3 war zum Zeitpunkt der Thesis noch in der Beta-Phase. Gerne hatte ich die eine
Lessons learned Seite 69
oder andere Stelle diesbezuglich naher veranschaulicht.
Alternativen zu finden und zu argumentieren, wieso ein bestimmter Entschluss ge-
fallen ist, macht die Vorgange fur alle Beteiligten transparenter. Wenn die Vorgange
transparent und nachvollziehbar dargestellt werden, stoßt man wahrend dieses Vor-
gangs auf weitere Alternativen.
Ich mochte mich fur die Betreuung bei allen Mitarbeitern von buddybrand, allen
voran bei Ole Riesenberg bedanken, ebenso geht mein Dank an Herrn Prof. Dr.
Winckler an der Hochschule Heilbronn, ohne den die Thesis in dieser Form nicht
moglich gewesen ware.
Quellenverzeichnis Seite 70
Quellenverzeichnis
[Fowler 2006] Fowler, Chad: Rails Recipes. 2006-5-15. Pragmatic Bookshelf, 2006
[Mangino 2008] Mangino, Michael: Developing Facebook Platform Applications
with Rails. 2008-9-16. Pragmatic Bookshelf, 2008
[Perrotta 2010] Perrotta, Paolo: Metaprogramming Ruby, Program Like the Ruby
Pros. 2010-1-15. Pragmatic Bookshelf, 2010
[Ruby u. a. 2009] Ruby, Sam ; Thomas, Dave ; Hansson, David: Agile Web
Development with Rails, Third Edition. 2009-2-26. Pragmatic Bookshelf, 2009
[Swicegood 2008] Swicegood, Travis: Pragmatic Version Control Using Git, The
Pragmatic Starter Kit - Volume 1. 2008-11-18. Pragmatic Bookshelf, 2008
[Thomas 2009] Thomas, Chad; Hunt A. Dave; Fowler F. Dave; Fowler: Programming
Ruby 1.9, The Pragmatic Programmers’ Guide. 2009-3-31. Pragmatic Bookshelf,
2009
[Zygmuntowicz u. a. 2008] Zygmuntowicz, Ezra ; Tate, Bruce ; Begin, Clin-
ton: Deploying Rails Applications, A Step-by-Step Guide. 2008-04-21. Pragmatic
Bookshelf, 2008
A Protokolle Seite 71
A. Protokolle
A.1. Meeting wegen Tracking-Anforderungen
Datum: 29.03.2010 15:00 Uhr
Teilnehmer: Ole Riesenberg, Klaus Breyer, Vincent Nicolai, Lars Kranholdt
Prioritat 1: unique User tracken pro Tag
Daten aus HTTP-Header: Werden nicht gebraucht fur den Kunden.
Jede Page-Impression wird mit Daten an den Server geschickt. (unique User pro Tag
oder Monat durch serverseitige Auswertung).
Daten: timestamp, userid, installiert, quelle
Quellen:
• Einladung
• Pinnwand
• Dashboard-News
• Lesezeichen
• ohne Referrer (direkter Aufruf)
Verschiedene Typen von Pinnwand-Veroffentlichungen
• Manuell Ajax-Callback auf spezielle URL der Anwendung
• automatische
Gesendete Dashboard Notifications bekommen eigenen Datentyp.
Gesendete Einladungen erfassen.
Parameter “srcref” fur Referer verwenden, da ref schon von Facebook benutzt wird.
Deinstallationen erfassen uber Post-Remove-Callback URL. Eigener Key der incre-
mented wird.
Ideen, wie die aggregierten Daten spater ausgewertet werden konnen:
• Nutzungsdauer: ersten Request und letzten Request tracken (mit Timeout
ergibt dies die Zeit, die der User auf der Page verbringt).
• Wiederkehrende User (Nutzungsdauer pro User)
A Protokolle Seite 72
Serverseitig konnen spater bei der Auswertung zu den User-IDs auch demografische
Daten erfasst werden.
To-do: Policies nach entsprechenden Klauseln durchsuchen.
Ebenso einholen, wenn die Daten geholt werden.
A.2. Review-Meeting Bachelor-Thesis
Datum: 19.05.2010 8:00 Uhr
Teilnehmer: Klaus Breyer, Prof. Dr. Jorg Winckler
• Griffigeren Namen fur”Transfer“
• Es ist in der Dokumentation bis jetzt noch nicht erwahnt, was passiert, wenn
der Trackingserver wahrend der Ubertragung offline geht, oder einen Fehler
produziert.
– Entweder gibt es nicht die Anforderung fur exaktes Tracking oder es muss
beschrieben werden
– Diskussion mit Auftraggeber: Transaktionsmanagement
– Redis-Gem untersuchen, welche Semantik dieser bietet und dann diese
benutzen (evtl. schon Transaktionsmanagement?)
• Griffigeren Namen fur Modul”Cache“
• Reihenfolge in der Modulbeschreibung andern
– Beginnen mit dem Kernmodul
– Oder zuerst die Sammelnden Module v.l.n.r. wie in Abbildung 12
• Problemlosung ohne Rails als eigenes Kapitel
– Alternativen zu einer Realisierung mit Gem
– Reine REST-API
– ..
– Generell viel Diskussion in Architekturbeschreibung
• Ruby/Rails-Erklarung evtl. in den Anhang
• Ziel klarer machen am Anfang
– Minimale Beeinflussung der Anwendung
A Protokolle Seite 73
– Ziel auch in Diskussion einbringen
• Den Leser mit einer Beispielanwendung durch die Thesis fuhren
– Vorher erklaren
– Anschließend beim Tracken der Features darauf verweisen
– Raumt Unklarheiten verschiedener Features aus.
• Im Rails-Realisierungsteil
– die Callbacks ausfuhrlicher beschreiben oder auf Beschreibung verweisen
– Ausfuhrlicher (z.B. E-Mail)
• Beispiel mit Railties in Rails-Erweiterungsteil mehr ausfuhren WARUM
• Wissen uber eingesammelte Daten im sammelnden Modul (momentan noch
weiterhin”Cache“ genannt)
– Welche E-Mails sind es? Evtl. parsen der E-Mails.
– Welche Publishes
– Mindestens Diskussion, wie das angegangen werden konnte
– Konzeption zur Erweiterung
– Evtl. auch alle Rest-Aufrufe tracken um ein Profil der Anwendung zu
erstellen
– Diskussionspunkt: Gem fur das Wissen nicht umprogrammieren
∗ Konfiguration
· Schlusselworte
· Parsen der Mails auf Schlusselworte
∗ Handler fur Cache
· Handler in Ruby-Code innerhalb der Anwendung
· Handlermethoden ubernehmen das Parsing/bzw. die Erkennung
mit Anwendungsspezifischen Abfragen
· Evtl. auch gesamte Konfiguration in den Handler rein
• Schnittstellenbeschreibung in Implementierungsdetails
– Redis
– Handler
A Protokolle Seite 74
• Welche Alternativen gibt es noch zum Redis-Backend
• Wie signalisiert der Gem, dass etwas schief lauft?
– Wenn Trackingserver im Backend langer nicht erreichbar
– Eskalationsstrategie
– Anbindung an Systemmanagementsoftware (SNMP) diskutieren
– Cache muss Probleme feststellen und signalisieren konnen
– Evtl. Handler dafur einklinken oder Callback
– So, dass man konfigurieren kann, was in welchem Fall passiert
– Was ist ublich an dieser Stelle? Was machen andere Gems?
– Rails-Logger?
B trackbuddy Seite 75
B. trackbuddy
B.1. Erfasste Rohdaten innerhalb von Redis
Im folgenden ein Beispiel fur erfasste JSON-Rohdaten, wie sie unter den jeweiligen
Schlusseln auf dem Redis-Server abgelegt werden. Diese sind mit der Beispielan-
wendung Tetris-Gifts erzeugt worden. Die Daten wurden mit gesetzter Anonymisie-
rungsoption fur Benutzer-IDs erfasst.
{” user ” : ” a6445fc0be0e1baa063bcc3d220f f41b ” , ” s r c r e f ” : ” pub l i sh
” , ” s r c type ” : ”” , ” query ” : ”/ t r a n s f e r s /73? s r c r e f=pub l i sh&
%3Bsrctype=sent ” , ” time ” : ”2010−07−28T08 :41 :33+02 :00 ”}{” user ” : ” a6445fc0be0e1baa063bcc3d220f f41b ” , ” s r c r e f ” : ” pub l i sh
” , ” s r c type ” : ” sent ” , ” query ” : ”/ t r a n s f e r s /73? s r c r e f=pub l i sh&
src type=sent ” , ” time ” : ”2010−07−28T08 :41 :50+02 :00 ”}{” user ” : ” de28e f6097d03d6e212935 f6 f ec714c f ” , ” s r c r e f ” : ”” , ”
s r c type ” : ”” , ” query ” : ”//? ac t i on=index&c o n t r o l l e r=pages&
only path=true&perms=use r photos%2Cemail%2Cuser about me&
s e l e c t e d p r o f i l e s =707892557& i n s t a l l e d=1&s e s s i o n=%7B%22
s e s s i o n k e y%22%3A%222.hN PGnx hd6mMvgEHP6aSQ
.3600.1280304000−707892557%22%2C%22uid%22%3A707892557%2C
%22e x p i r e s%22%3A1280304000%2C%22 s e c r e t%22%3A%222
RDEx62HaYXgI2U pg74qg %22%2C%22 s i g%22%3A%226
a52fd69d985b4e3c75d5af3a326c f fa%22%7D” , ” time ” : ”2010−07−28
T08 :39 :35+02 :00 ”}{” user ” : nu l l , ” s r c r e f ” : ”” , ” s r c type ” : ”” , ” query ” : ”/” , ” time ” : ”
2010−07−28T08 :39 :54+02 :00 ”}{” user ” : ” a6445fc0be0e1baa063bcc3d220f f41b ” , ” s r c r e f ” : ”” , ”
s r c type ” : ”” , ” query ” : ”/ t r a n s f e r s /73? pub l i sh=true ” , ” time ” : ”
2010−07−28T08 :40 :43+02 :00 ”}{” user ” : ” a6445fc0be0e1baa063bcc3d220f f41b ” , ” s r c r e f ” : ”” , ”
s r c type ” : ”” , ” query ” : ”/ t r a n s f e r s ” , ” time ” : ”2010−07−28T08
:40 :31+02 :00 ”}{” user ” : ” de28e f6097d03d6e212935 f6 f ec714c f ” , ” s r c r e f ” : ”” , ”
s r c type ” : ”” , ” query ” : ”/” , ” time ” : ”2010−07−28T08 :38 :15+02 :00
”}
Listing 23: Redis-Rohdaten fur Schlussel “impression”
B trackbuddy Seite 76
{” user ” : ” a6445fc0be0e1baa063bcc3d220f f41b ” , ” time ” : ”
2010−07−28T08 :39 :58+02 :00 ”}{” user ” : ” de28e f6097d03d6e212935 f6 f ec714c f ” , ” time ” : ”
2010−07−28T08 :39 :34+02 :00 ”}
Listing 24: Redis-Rohdaten fur Schlussel “install”
{” user ” : ” de28e f6097d03d6e212935 f6 f ec714c f ” , ” time ” : ”
2010−07−28T08 :39 :16+02 :00 ”}
Listing 25: Redis-Rohdaten fur Schlussel “uninstall”
{” value ” : ” g i f t s e n t ” , ” time ” : ”2010−07−28T08 :40 :42+02 :00 ”}
Listing 26: Redis-Rohdaten fur Schlussel “custom”
{” s r c type ” : ” r e c e i v e d ” , ” args ” : ”
cb6c116881103d76fcc8c9604f05ea3b ” , ” time ” : ”2010−07−28T08
:40 :36+02 :00 ”}
Listing 27: Redis-Rohdaten fur Schlussel “email”
{” from” : ” user ” , ” s r c type ” : ” sent ” , ” user ” : ”
a6445fc0be0e1baa063bcc3d220f f41b ” , ” time ” : ”2010−07−28T08
:40 :46+02 :00 ”}
Listing 28: Redis-Rohdaten fur Schlussel “publish”
{” from” : ” a6445fc0be0e1baa063bcc3d220f f41b ” , ” to ” : ”
a557b45c fb f f296ee8c0c46c245b283d ” , ” s r c type ” : ” s e n d i n g g i f t
” , ” time ” : ”2010−07−28T08 :40 :31+02 :00 ”}
Listing 29: Redis-Rohdaten fur Schlussel “invite”
{” user ” : ” a557b45c fb f f296ee8c0c46c245b283d ” , ” s r c type ” : ”
multiaddnews” , ” time ” : ”2010−07−28T08 :40 :33+02 :00 ”}
Listing 30: Redis-Rohdaten fur Schlussel “dashboardnews”
{” user ” : ” a557b45c fb f f296ee8c0c46c245b283d ” , ” time ” : ”
2010−07−28T08 :40 :32+02 :00 ”}
Listing 31: Redis-Rohdaten fur Schlussel “dashboardcounter”
B trackbuddy Seite 77
B.2. Beispiel-Auswertung der erfassten Daten
Dies sind Statistiken, die im Rahmen der Anwendung uLikeMe von buddybrand
erfasst wurden. In der Anwendung wird bis auf Dashboard-News jeder Kommuni-
kationskanal von Facebook benutzt. Die Statistik beruht auf Daten, die trackbuddy
erfasst hat.
Gewonnene Ergebnisse Von hochstem Interesse war der Erfolg von Veroffentli-
chungen. Es konnte teilweise nachvollzogen werden, an welcher Stelle die virale Ver-
breitung der Anwendung stoppt. Wenn Benutzer durch eine bestimmte Veroffentli-
chung (trivia-question, Abbildung 25) in die Anwendung kommen, aber die Reaktion
(trivia-choice, Abbildung 24) daraufhin nicht selbst veroffentlichen, muss an dieser
Stelle ein weiterer Anreiz eingebaut werden, um den viralen Impuls weiter zu tragen.
Des Weiteren war zu sehen, dass viele Einladungen verschickt werden (Abbildung
20), diese aber so gut wie nie angenommen wurden (Abbildung 23). So kann der
Schluss gezogen werden, dass an Stellen, an denen Benutzer ihre Freunde einladen
sollen, andere virale Kanale geoffnet werden sollten.
Graphen Die Auswertung geschieht im internen Backend von buddybrand. Fur die
Darstellung der Graphen wird das JQuery-Plugin Flot (http://code.google.com/
p/flot/) verwendet.
B trackbuddy Seite 78
Abbildung 19: Statistik uber Seitenaufrufe
Abbildung 20: Statistik uber Installationen, Deinstallationen, Veroffentlichungen,
E-Mails und Einladungen
B trackbuddy Seite 79
Abbildung 21: Anwendungsspezifische Datenerfassung von versendeten Nachrichten
Abbildung 22: Statistik, welche E-Mails wie oft versendet wurden
B trackbuddy Seite 80
Abbildung 23: Statistik, uber welche viralen Kanale Benutzer wieder in die Anwen-
dung kommen (srcref-Parameter)
Abbildung 24: Statistik, welche Veroffentlichungen wie oft getatigt wurden
B trackbuddy Seite 81
Abbildung 25: Statistik, uber welche Veroffentlichungen Benutzer wieder in die An-
wendung kommen
Abbildung 26: Statistik, wie viele automatisierte und manuelle Veroffentlichungen
getatigt wurden
B trackbuddy Seite 82
B.3. Gem-Spezifikation trackbuddy.gemspec
# Generated by j e w e l e r
# DO NOT EDIT THIS FILE DIRECTLY
# Instead , e d i t Jewe ler : : Tasks in R a k e f i l e , and run the
gemspec command
# −∗− encoding : u t f−8 −∗−
Gem : : S p e c i f i c a t i o n . new do | s |s . name = %q{ trackbuddy}s . v e r s i on = ” 1 . 0 . 0 ”
s . r equ i r ed rubygems ve r s i on = Gem : : Requirement . new( ”>= 0” )
i f s . r e spond to ? : r equ i r ed rubygems ve r s i on=
s . authors = [ ”Klaus Breyer ” ]
s . date = %q{2010−07−27}s . d e s c r i p t i o n = %q{buddybrand ’ s t r a ck ing l i b r a r y f o r
facebook }s . emai l = %q{ labs@buddybrand . de}s . e x t r a r d o c f i l e s = [
”README”
]
s . f i l e s = [
” l i b / gene ra to r s / trackbuddyconf ig /
t rackbuddycon f i g gene ra to r . rb” ,
” l i b / rack / h i t . rb” ,
” l i b / r a i l s / ema i l e x t en s i on . rb” ,
” l i b / r a i l s / h e l p e r s . rb” ,
” l i b / trackbuddy . rb” ,
” l i b / trackbuddy /backend . rb” ,
” l i b / trackbuddy / b u f f e r . rb” ,
” l i b / trackbuddy /custom . rb” ,
” l i b / trackbuddy / r a i l t i e . rb” ,
” l i b / trackbuddy / r e s t a p i . rb” ,
” l i b / trackbuddy / support . rb” ,
” t e s t / te s t t rackbuddy . rb”
]
s . homepage = %q{http :// buddybrand . de}
B trackbuddy Seite 83
s . rdoc op t i on s = [ ”−−cha r s e t=UTF−8” ]
s . r e q u i r e p a t h s = [ ” l i b ” ]
s . rubygems vers ion = %q{ 1 . 3 . 7 }s . summary = %q{buddybrand ’ s t r a ck ing l i b r a r y f o r facebook }s . t e s t f i l e s = [
” t e s t / te s t t rackbuddy . rb”
]
i f s . r e spond to ? : s p e c i f i c a t i o n v e r s i o n then
c u r r e n t v e r s i o n = Gem : : S p e c i f i c a t i o n : :
CURRENT SPECIFICATION VERSION
s . s p e c i f i c a t i o n v e r s i o n = 3
i f Gem : : Vers ion . new(Gem : : VERSION) >= Gem : : Vers ion . new( ’
1 . 2 . 0 ’ ) then
s . add runtime dependency(%q<toadhopper >, [ ”>= 0” ] )
s . add runtime dependency(%q<buddy>, [ ”>= 0 . 1 . 0 ” ] )
s . add runtime dependency(%q<r ed i s >, [ ”>= 0” ] )
s . add runtime dependency(%q<r ed i s−namespace>, [ ”>= 0”
] )
else
s . add dependency(%q<toadhopper >, [ ”>= 0” ] )
s . add dependency(%q<buddy>, [ ”>= 0 . 1 . 0 ” ] )
s . add dependency(%q<r ed i s >, [ ”>= 0” ] )
s . add dependency(%q<r ed i s−namespace>, [ ”>= 0” ] )
end
else
s . add dependency(%q<toadhopper >, [ ”>= 0” ] )
s . add dependency(%q<buddy>, [ ”>= 0 . 1 . 0 ” ] )
s . add dependency(%q<r ed i s >, [ ”>= 0” ] )
s . add dependency(%q<r ed i s−namespace>, [ ”>= 0” ] )
end
end
Listing 32: trackbuddy.gemspec
B trackbuddy Seite 84
B.4. Konfigurationsdatei trackbuddy.yml
# Conf i gura t ion f o r the buddybrand t r a c k i n g l i b r a r y .
l o c a l b u f f e r : 1
backend : ” trackbuddy−r e d i s ”
track anonymously : fa l se
t r a c k r e s t a p i : true
n o t i f y t h r e s h o l d : 5
b l o c k e d u r i s :
− ”/ pages / blocked ”
− ”/ images /”
backend hosts :
− ”db . buddybrand . de”
− ” f e1 . buddybrand . de”
− ” f e2 . buddybrand . de”
s r c r e f :
− a d v e r t i s i n g
− promotion
Listing 33: Konfigurationsdatei fur trackbuddy in YAML-Notation
B.5. Anpassung einer Einladung
Im Folgenden Beispiel wird der FBML-Code einer Einladung modifiziert. Danach
entsteht ein Link, welcher zusatzlich die Parameter “srcref” und “srctype” mitsen-
det. Diese konnen bei einem Wiedereintreten eines Benutzers in die Anwendung
erfasst werden. So kann die Effizienz von viralen Kanalen festgestellt werden.
<fb : request−formact ion=”<%= t r a n s f e r s u r l %>” method=”POST”
i n v i t e=” true ” type=” Tetr i s−G i f t s ”
content=” I have something f o r you ! <fb : req−cho i c e u r l
=’<%= t r a n s f e r u r l ( @trans f e r ) %>’ l a b e l =’Accept my
Tetr i s−Gi f t ’ />
”>
<!−− Se l e c to r , e t c . −−>
</fb : request−form>
Listing 34: FBML-Code einer Einladung vor Anpassung
B trackbuddy Seite 85
<fb : request−form ac t i on=”<%= t r a n s f e r s u r l %>” method=”POST”
i n v i t e=” true ” type=” Tetr i s−G i f t s ”
content=” I have something f o r you ! <fb : req−cho i c e u r l=’<%=
i n v i t e s e n t ( t r a n s f e r u r l ( @trans f e r ) ) %>’ l a b e l =’
Accept my Tetr i s−Gi f t ’ />
”>
<!−− Se l e c to r , e t c . −−>
</fb : request−form>
Listing 35: FBML-Code einer Einladung nach der Anpassung
<fb : request−form ac t i on=” http :// apps . facebook . com/
t e t r i s g i f t s / t r a n s f e r s ” method=”POST” i n v i t e=” true ” type=”
T e t r i s G i f t s ”
content=” I have something f o r you ! <fb : r e q c h o i c e u r l =’
http :// apps . facebook . com/ t e t r i s g i f t s / t r a n s f e r s /55?
s r c r e f=i n v i t e&src type=sent ’ l a b e l =’Accept my Tetr i s−Gi f t ’ />
”>
Listing 36: Geparster FBML-Code einer Einladung
B.6. Integration eines Callbacks bei manueller
Pinnwand-Veroffentlichung
In diesem Beispiel wird der FBJS-Code einer manuellen Pinnwand-Veroffentlichung
so modifiziert, dass danach ein Callback auf den Anwendungsserver gesendet wird.
<s c r i p t >
var attachment sent = { ’name ’ : ’New Tetr i s−Gi f t ’ ,
’ h r e f ’ : ’<%= t r a n s f e r u r l ( @trans f e r ) %> ’ ,
’ d e s c r i p t i o n ’ : ’A new <%= @trans f e r . b r i ck . desc %> i s wa i t ing
f o r you in Tetr i s−G i f t s . ’ ,
’ media ’ : [ { ’ type ’ : ’ image ’ ,
’ s r c ’ : ’<%= image path @trans f e r . b r i ck . image %> ’ ,
’ h r e f ’ : ’<%= t r a n s f e r u r l ( @trans f e r ) %> ’ } ]
B trackbuddy Seite 86
} ;
var a c t i o n L i n k s s e n t = [{ ’ t ex t ’ : ’ I l i k e ’ , ’ h r e f ’ : ’<%=
t r a n s f e r u r l ( @trans f e r ) %> ’ } ] ;
Facebook . streamPubl ish ( ’ ’ , attachment sent , a c t i onL inks s en t
, <%= @trans f e r . r e c e i v e r . f a c ebook id %>, nu l l , n u l l ) ;
</s c r i p t >
Listing 37: FBJS-Code einer Veroffentlichung vor der Anpassung
<%= t r a c k i n g c a l l b a c k %>
<s c r i p t >
f unc t i on c a l l b a c k ( ) {return fa l se ;
}var attachment sent = { ’name ’ : ’New Tetr i s−Gi f t ’ ,
’ h r e f ’ : ’<%= p u b l i s h s e n t ( t r a n s f e r u r l ( @trans f e r ) ) %> ’ ,
’ d e s c r i p t i o n ’ : ’A new <%= @trans f e r . b r i ck . desc %> i s wa i t ing
f o r you in Tetr i s−G i f t s . ’ ,
’ media ’ : [ { ’ type ’ : ’ image ’ ,
’ s r c ’ : ’<%= image path @trans f e r . b r i ck . image %> ’ ,
’ h r e f ’ : ’<%= p u b l i s h s e n t ( t r a n s f e r u r l ( @trans f e r ) )
%> ’ } ]
} ;
var a c t i o n L i n k s s e n t = [{ ’ t ex t ’ : ’ I l i k e ’ , ’ h r e f ’ : ’<%=
p u b l i s h s e n t ( t r a n s f e r u r l ( @trans f e r ) ) %> ’ } ] ;
Facebook . streamPubl ish ( ’ ’ , attachment sent , a c t i onL inks s en t
, <%= @trans f e r . r e c e i v e r . f a c ebook id %>, nu l l ,
t r a c k i n g c a l l b a c k ( ’ s ent ’ ) ) ;
</s c r i p t >
Listing 38: FBJS-Code einer Pinnwand-Veroffentlichung nach der Anpassung
B trackbuddy Seite 87
<s c r i p t >
f unc t i on t r a c k i n g c a l l b a c k ( s r c type ) {var ajax = new Ajax ( ) ;
a jax . responseType = Ajax .RAW;
ajax . post ( ’ http :// kahbeh . de :4007/ middleware / pub l i sh /?
s r c type=’ + src type ) ;
}
var attachment sent = { ’name ’ : ’New T e t r i s G i f t ’ ,
’ h r e f ’ : ’ http :// apps . facebook . com/ t e t r i s g i f t s / t r a n s f e r s /53?
s r c r e f=pub l i sh&src type=sent ’ ,
’ d e s c r i p t i o n ’ : ’A new J shaped Brick i s wa i t ing f o r you in
T e t r i s G i f t s . ’ ,
’ media ’ : [{ ’ type ’ : ’ image ’ , ’ s r c ’ : ’ http :// kahbeh . de :4007/
images / j s 1 . png ’ , ’ h r e f ’ : ’ http :// apps . facebook . com/
t e t r i s g i f t s / t r a n s f e r s /53? s r c r e f=pub l i sh&src type=sent ’ } ]
} ;
var a c t i o n L i n k s s e n t = [{ ’ t ex t ’ : ’ I l i k e ’ , ’ h r e f ’ :
’ http :// apps . facebook . com/ t e t r i s g i f t s / t r a n s f e r s /53? s r c r e f=
pub l i sh&src type=sent ’ } ] ;
Facebook . streamPubl ish ( ’ ’ , attachment sent ,
a c t i onL inks s en t , 100000480357701 , nu l l , t r a c k i n g c a l l b a c k
( ’ sent ’ ) ) ;
</s c r i p t >
Listing 39: Geparster FBJS-Code einer Pinnwand-Veroffentlichung
C Ruby Seite 88
C. Ruby
C.1. Metaprogrammierung in Ruby
Dieses Kapitel soll die Metaprogrammierungsaspekte von Ruby naher beleuchten,
die auch in der Thesis verwendet werden. Eine Einfuhrung in Ruby kann im Litera-
turverzeichnis (Thomas, 2009, S. 3-86) gefunden werden.
C.1.1. Module einbeziehen
Ein Plugin oder ein Gem wird in seinem eigenen Namespace, das heißt, in einem
eigenen Modul, entwickelt. Ruby-Klassen und Module mussen nicht in einer einzel-
nen Datei definiert werden. Ein Modul kann jederzeit in einer anderen Datei weiter
geschrieben werden. Dies wird von Erweiterungen jeglicher Art benutzt. Erweitert
ein Modul ein anderes, muss lediglich sichergestellt werden, dass das zu erweiternde
Modul bereits geladen ist, und dass die Erweiterung vor der Verwendung stattfin-
det. So kann von der Erweiterung die Funktionalitat uberschrieben oder um neue
Methoden erweitert werden.
include In diesem Listing wird eine Klasse zu einem spateren Zeitpunkt mittels der
Methode “include” um die Methoden eines Modules erweitert. Eine solche Erweiter-
ung von einer Klasse, auch Mixin genannt, kann auch an einer anderen Stelle des
Programms und in einer anderen Datei geschehen. Wenn ein Modul uber “include”
in eine Klassendefinition einbezogen wird, erhalt die Klasse samtliche Konstanten,
Klassenvariablen und Instanzmethoden (Thomas, 2009, S. 349)
module Einzubeziehen
def neue
” zwei ”
end
end
class Bas i s
def a l t e
” e i n s ”
end
end
class Bas i s
i n c lude Einzubez iehen
end
C Ruby Seite 89
in s tanz = Bas i s . new
puts in s tanz . a l t e # e i n s
puts in s tanz . neue # zwei
Listing 40: Einbeziehen eines Moduls mit include
extend Klassen in Ruby konnen nicht ausschließlich bei dem Zeitpunkt der Klas-
sendefinition um Methoden erweitert werden, sondern auch, wenn bereits eine In-
stanz von einem Objekt erzeugt worden ist. In diesem Falle wird das Statement
“extend” verwendet. Dies kann genutzt werden, um Instanzmethoden speziell fur
ein bestimmtes Objekt hinzuzufugen (Thomas, 2009, S. 385).
module Einzubeziehen
def neue
” zwei ”
end
end
class Bas i s
def a l t e
” e i n s ”
end
end
i n s t anz = Bas i s . new
puts in s tanz . a l t e # e i n s
i n s t anz . extend Einzubeziehen
puts in s tanz . neue # zwei
Listing 41: Einbeziehen eines Moduls mit extend
C.1.2. Methodenaufrufe als Parameter
Mittels der Methode “send” von Objekten konnen Methoden aufgerufen werden,
indem sie der Methode als Symbol-Parameter mitgegeben werden. Argumente der
Methode werden als weitere Parameter angehangt.
C Ruby Seite 90
class A
def methode ( argument )
argument ∗ 2
end
end
i n s t anz = A. new
puts in s tanz . methode (3 ) # Ergebnis : 6
puts in s tanz . send : methode , 3 # Ergebnis : 6
Listing 42: Send-Methode
Dies kann sich als sehr nutzlich erweisen, da fur eine Erweiterung eines Objektes
nicht die komplette, mehrzeilige Definition, eines Modules mit innenliegenden Klas-
sen benutzt werden muss.
Act i onCont ro l l e r : : Base . send ( : inc lude , Trackbuddy )
Listing 43: Einbindung mittels send-Methode
C.1.3. Behandlung fehlender Methoden
Jedes Objekt, jede Klasse und jedes Modul in Ruby besitzt eine Methode mit dem
Namen “method missing”. Argumente dieser Methode sind der Name, die Argu-
mente und ein Block von der Methode, die eigentlich aufgerufen werden sollte. Die
Methode wird aufgerufen, wenn ein Aufruf auf eine Methode stattfinden soll, welche
nicht vorhanden ist (Perrotta, 2010, S. 48-50). Ist diese Methode uberschrieben, wird
keine Exception geworfen sondern der Code der Methode ausgefuhrt. So kann ein
alternatives Verhalten mit Methodennamen implementiert werden, die nicht existie-
ren.
class Klasse
def method missing (name , ∗args , &block )
puts ”Die Methode #{name} mit den Argumenten #{args .
i n s p e c t } i s t l e i d e r n i cht implement ie r t . ”
end
end
i n s t anz = Klasse . new
in s tanz . methode der wahl (100 , 200 , { : key => ” value ”})
Listing 44: Definiertes Verhalten bei nicht vorhandener Methode
C Ruby Seite 91
C.1.4. Method-Chaining
Da es die Moglichkeit gibt, im Nachhinein Methoden von einem Modul zu uberschrei-
ben, besteht auch die Notwendigkeit, auf die ursprungliche Version der Methode
zuzugreifen. Ruby bietet die Moglichkeit, ein Alias fur eine Methode zu erstellen.
Wenn eine einzige Methode um eine Funktionalitat erweitert werden soll, kann dies
in folgenden Schritten geschehen:
• Alias von der ursprunglichen Methode erstellen
• Erstellen einer neuen Methode mit dem ursprunglichen Namen
• Aufrufen des Alias in der neuen Methode
Mit dem Verketten von Methoden (engl. chaining) bietet sich die Moglichkeit, im
Nachhinein eine Methode um Funktionalitat zu erweitern und dabei die ursprungli-
che Methode weiter zu verwenden.
class Orgina l
def a
’ a ’
end
end
i n s t anz = Orgina l . new
puts in s tanz . a #Ergebnis : a
class Orgina l
a l i a s method : a a l t , : a
def a
’ Neue und . . ’ + a a l t
end
end
i n s t anz = Orgina l . new
puts in s tanz . a #Ergebnis : Neue und . . a
Listing 45: Method Chaining in Ruby
C Ruby Seite 92
C.1.5. methods.include?
Jedes Objekt kann in Ruby gefragt werden, ob es eine Methode mit einem gegebenen
Namen beinhaltet. In trackbuddy wird dies verwendet, um zu uberprufen, ob das
Modul fur das Backend auch die Methode “push” implementiert hat. Hierfur wird
das von “methods” zuruckgegebene Array mittels “include?” auf das Vorhandensein
eines Wertes uberpruft.
class Klasse
def vorhanden
puts ”Methode vorhanden”
end
end
ob jekt = Klasse . new
#ruby 1 . 8 . 7
puts ob jekt . methods . i n c lude ?( ”vorhanden” ) #t r u e
puts ob jekt . methods . i n c lude ?( ” nicht vorhanden ” ) #f a l s e
#ruby 1 . 9 . 1
puts ob jekt . methods . i n c lude ? ( : vorhanden ) #t r u e
puts ob jekt . methods . i n c lude ? ( : n icht vorhanden ) #f a l s e
Listing 46: Uberprufung auf vorhandene Methode
Zu beachten ist, dass Ruby 1.8 einen String bei diesem Vergleich erwartet, Ruby 1.9
aber an dieser Stelle ein Symbol.
C.1.6. Oberserver-Pattern
Das Observer-Pattern erlaubt es, dass sich ein Objekt bei einem anderen registriert,
um uber dessen Anderungen informiert zu werden. Die “update”-Methode des Ob-
servers wird aufgerufen, wenn es in dem Objekt, welches Observable eingebunden
hat, Anderungen gab und diese den Observern mit “notify observers” mitgeteilt wer-
den. Zuvor mussen sich die Observer mit “add observer” an dem Objekt registrieren.
Die Anzahl der Argumente muss in “notify observers” und “update” dieselbe sein.
Ansonsten bedarf es keiner weiteren Definition. Um uber Aufrufe der REST-API
informiert zu werden, registriert sich trackbuddy als Observer in dem Service-Modul
des Gems buddy.
C Ruby Seite 93
r e q u i r e ’ obse rve r ’
class Akt i v i t a e t
i n c lude Observable
def machen
1 . upto (3 ) do | i |changed
n o t i f y o b s e r v e r s ( i )
end
end
end
class Waechter
def update ( i )
puts ”Angekommener Wert : #{ i }”
end
end
etwas = Akt i v i t a e t . new
jemand = Waechter . new
etwas . add observer ( jemand )
etwas . machen
# Ergebnis :
# Angekommener Wert : 1
# Angekommener Wert : 2
# Angekommener Wert : 3
Listing 47: Observer Pattern in Ruby
C.2. Schnittstellen von Rails
C.2.1. Rack
Rack ist eine Middleware und ein Interface fur Ruby, welches auch Rails zugrunde
liegt. Innerhalb von Rack konnen sich Ruby-Klassen einhangen. Das Einhangen in
Rails 3 geschieht mittels Railties (Anhang C.2.2). Die Komponenten der Middleware
werden in der eingetragenen Reihenfolge abgearbeitet. Eingetragene Middleware-
Komponenten konnen mittels dem Befehl rake middleware ermittelt werden.
C Ruby Seite 94
use ActionDispatch : : S t a t i c
use Rack : : Lock
use Rack : : Runtime
use Ra i l s : : Rack : : Logger
use ActionDispatch : : ShowExceptions
use ActionDispatch : : RemoteIp
use Rack : : S e n d f i l e
use ActionDispatch : : Ca l lbacks
use ActionDispatch : : Cookies
use ActionDispatch : : S e s s i on : : CookieStore
use ActionDispatch : : Flash
use ActionDispatch : : ParamsParser
use Rack : : MethodOverride
use ActionDispatch : : Head
use ActiveRecord : : ConnectionAdapters : : ConnectionManagement
use ActiveRecord : : QueryCache
run Rateyourdate : : App l i ca t ion . route s
Listing 48: Middleware-Komponenten mittels “rake middleware”
Eine gultige Klasse, welche sich in die Middleware einhangen kann, muss folgende
Methoden implementiert haben:
• Einen Konstruktor, welcher eine Referenz auf die Anwendung bekommt und
diese in einer Instanzvariable speichert.
• Ein Aufruf der Middleware-Klasse mit Environment, welche danach den Aufruf
weiter verarbeitet.
Soll ein Aufruf nicht ganz ausgefuhrt werden, wie es bei den zu erfassenden Call-
backs der Fall ist, kann auch direkt eine Antwort geliefert werden anstelle den Aufruf
weiter zu verarbeiten.
Alternativen zu Rack als Middleware gibt es keine, weil Rails darauf basiert. Al-
lerdings gibt es die Moglichkeit, die Funktionalitat, welche uber die Middleware
verfugbar gemacht wird, an anderer Stelle zu implementieren. Da die Middlewa-
re lediglich bei jedem Aufruf durchlaufen wird, konnte die Funktionalitat auch im
Application-Controller implementiert werden. Mittels eines Method-Chaining (An-
hang C.1.4) auf die Methode “inherited”, welche bei jeder Vererbung aufgerufen
wird, konnte die Datenerfassung an dieser Stelle durchgeschleift werden. Dann wird
zuerst die Datenerfassung durchgefuhrt, bevor der Controller anschließend vererbt
C Ruby Seite 95
wird. Dies ist so moglich, da jeder Seitenaufruf einen Controller instanziiert, welcher
von dem ApplicationController erbt.
Dabei geht der Vorteil verloren, einen Request vorzeitig abzubrechen. Bei jedem
Aufruf wird der vollstandige Stack abgearbeitet.
module Rack
module Hit
class Request
def i n i t i a l i z e ( app )
@app = app
end
def c a l l ( env )
@app . c a l l ( env )
end
end
end
end
Listing 49: Implementierung einer Middleware-Klasse
C.2.2. Railties
Samtliche Gems werden innerhalb einer Rails-Anwendung geladen, bevor der Boot-
strap-Prozess gestartet wird. Mittels Railties kann sich ein Gem in den Bootstrap-
Prozess einklinken. Railties organisieren die Initialisierung einer Railsanwendung.
Auch jede Standardkomponente wird mittels Railties eingebunden. Des Weiteren
kann dieses Interface auch von jedem Gem, der Rails als Abhangigkeit hat, ver-
wendet werden. Dies wird realisiert, indem jeder Gem auf das Vorhandensein eines
Railtie uberpruft wird.
Railties bieten ein einheitliches Interface zur Konfiguration verschiedener Kompo-
nenten. Beispiele fur Anwendungen von Railties sind das Anhangen eines View-
Pfades oder das Bereitstellen einer Middleware-Komponente.
Diese Komponente wird an dieser Stelle in die Middleware nach
ActionDispatch::ParamsParser eingehangt. An dieser Stelle sind bereits die
HTTP-Parameter verarbeitet worden, so dass sie mittels Variablen angesprochen
werden konnen. Da das Verarbeiten eines Requests außer den HTTP-Parametern
nichts Weiteres benotigt, wird dieses Modul an der Stelle eingehangt.
C Ruby Seite 96
module Trackbuddy
class R a i l t i e < : : Ra i l s : : R a i l t i e
i n i t i a l i z e r ” trackbuddy . c o n f i g u r e r a i l s i n i t i a l i z a t i o n ”
do | app |app . c o n f i g . middleware . i n s e r t b e f o r e ( ActionDispatch : :
ParamsParser , : : Trackbuddy : : Rack : : Request )
end
end
end
Listing 50: Verfugbarmachen einer Middleware-Komponente mittels Railtie
D Redis-Benchmark Seite 97
D. Redis-Benchmark
D.1. Programmcode
r e q u i r e ’ r e d i s ’
r e q u i r e ’ r e d i s / d i s t r i b u t e d ’
r e q u i r e ’ r e d i s / r e d i s f a c t o r y ’
r e q u i r e ’ r e d i s /namespace ’
r e q u i r e ’ r e d i s / mar sha l ed r ed i s ’
r e q u i r e ’ j son ’
r e q u i r e ’ benchmark ’
namespace = ” te s t env ”
@r = RedisFactory . c r e a t e
@data = Redis : : Namespace . new( namespace , : r e d i s => @r)
puts Benchmark . measure {0 . upto (10000) { | x |
r ecord = { : id => x ,
: use r =>” d1b4f7d74ecf3f32ccca7adb0d6a8d47 ” ,
: s r c r e f => ”” ,
: query =>”/ pages / i n v i t e ” ,
: time => Time . new
}
@data . sadd : impress ion , r ecord
}}
puts Benchmark . measure {0 . upto (10000) { | x |
r ecord = { : id => x ,
: use r =>” d1b4f7d74ecf3f32ccca7adb0d6a8d47 ” ,
: s r c r e f => ”” ,
: query =>”/ pages / i n v i t e ” ,
: time => Time . new
}
D Redis-Benchmark Seite 98
@data . sadd : impress ion , r ecord . t o j s o n
}}
Listing 51: Programmcode des Redis-Benchmarks
D.2. Ergebnis
% ruby redisbenchmark . rb
0.820000 0.190000 1.010000 ( 1 .579243)
0 .820000 0.270000 1.090000 ( 1 .666429)
Listing 52: Ergebnis des Redis-Benchmarks
E Hoptoad Seite 99
E. Hoptoad
E.1. Oberflache mit aggregierten Fehlermeldungen
Abbildung 27: Hoptoad-Oberflache (Fehlermeldungen wurden unkenntlich gemacht)
E.2. Hoptoad-E-Mail mit Fehlermeldung
Datum: 03.06.2010
Inhalt: E-Mail mit einer Fehlermeldung, welche ein Problem in der Produktivum-
gebung beschreibt. In diesem Fall fehlt ein Argument fur einen String, der eine
Ubersetzung beinhaltet.
Von: [email protected]: [Buddybrand RateUrDate] Production: I18n::MissingInterpolationArgument: missing interpolation
argument in "Beantworte auch Fragen über {{user}}!" ({:question=>"<fb:name linked=\"false\" useyou=\"false\" firstnameonly=\"true\" uid=\"100001083140636\" />"} given)
Datum: 3. Juni 2010 22:06:11 MESZAn: [email protected], [email protected]
http://buddybrand.hoptoadapp.com/errors/1882341
Error Message:--------------I18n::MissingInterpolationArgument: missing interpolation argument in "Beantworte auch Fragen über {{user}}!"({:question=>"<fb:name linked=\"false\" useyou=\"false\" firstnameonly=\"true\" uid=\"100001083140636\" />"}given)
Where:------interview/answers#create[PROJECT_ROOT]/vendor/gems/i18n-0.3.7/lib/i18n/backend/base.rb, line 204
Request:--------params: action: create authenticity_token: DNzmo53esobEYaTXJQw9rPKejHN2WX/GZl/PxmBxY0E= controller: interview/answers fb_sig: cb13c94f802c7367390fb6eac0730efd fb_sig_added: "true" fb_sig_api_key: 7fe23a2ad0ed3775260e47c8196f5450 fb_sig_app_id: "118248144857525" fb_sig_country: de fb_sig_expires: "2010-06-04 00:00:00 +0200" fb_sig_ext_perms:"status_update,photo_upload,video_upload,email,create_note,share_item,auto_publish_short_feed,publish_stream,auto_publish_recent_activity,user_photos,user_about_me" fb_sig_in_new_facebook: "true" fb_sig_is_mockajax: "1" fb_sig_locale: de_DE fb_sig_profile_update_time: "2010-05-14 23:07:23 +0200" fb_sig_session_key: 2.Nl5c21AzK2dECyAy4OA6MA__.3600.1275602400-100001083140636 fb_sig_time: "2010-06-03 22:06:09 +0200" fb_sig_user: "100001083140636" fb_target_id: "0" format: fbjs interview: answer_id: "1187" aw_question_id: "502" friend_ids: "100000504573704,100000991626598,100000406130258,100000516742887" question_id: "428" selected_friend_ids: ? "0" : "100000991626598" post_form_id_source: AsyncRequest publish: "true"rails_root: /var/www/buddybrand/rateurdate/releases/20100603183237url: "http://rateurdate.bounce19.buddybrand.de/interview/answers?publish=true"
Session:--------? !ruby/symbol data: facebook_session: "#<Buddy::Session:0x000000045f3ab0>" session_id: d734d3093ade7a519ae06d8316058cf0
Environment:------------CONTENT_LENGTH: "981"CONTENT_TYPE: application/x-www-form-urlencodedDOCUMENT_ROOT: /var/www/buddybrand/rateurdate/current/publicHTTP_ACCEPT: "*/*"HTTP_ACCEPT_ENCODING: gzipHTTP_CONNECTION: closeHTTP_HOST: rateurdate.bounce19.buddybrand.deHTTP_USER_AGENT: "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NETCLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)"HTTP_X_FORWARDED_FOR: "66.220.146.249"HTTP_X_REAL_IP: "66.220.146.249"PATH_INFO: /interview/answersQUERY_STRING: publish=trueRAILS_ENV: productionREMOTE_ADDR: "127.0.0.1"REMOTE_PORT: "37780"REQUEST_METHOD: POSTREQUEST_URI: /interview/answers?publish=trueSCRIPT_NAME: ""SERVER_ADDR: "127.0.0.1"SERVER_ADMIN: "[no address given]"SERVER_NAME: rateurdate.bounce19.buddybrand.deSERVER_PORT: "80"SERVER_PROTOCOL: HTTP/1.0SERVER_SOFTWARE: ApacheUNIQUE_ID: TAgLMn8AAAEAAGTLLt8AAAAC_: _action_dispatch.parameter_filter: "[\"fb_sig_friends\", \"password\"]"action_dispatch.remote_ip: "66.220.146.249"action_dispatch.secret_token:bbfce80767f5626378debc5eb996ee3302121fa153b8fc2176320621f2ff951f6882c15ae9de5b9165c2cd97fc3bdebfe2636726d653d3483e90825f24b66d42rack.errors: "#<IO:0x00000000a3d758>"rack.input: "#<PhusionPassenger::Utils::RewindableInput:0x000000047d92b8>"rack.multiprocess: "true"rack.multithread: "false"rack.request.form_hash: authenticity_token: DNzmo53esobEYaTXJQw9rPKejHN2WX/GZl/PxmBxY0E= fb_sig_added: "1" fb_sig_api_key: 7fe23a2ad0ed3775260e47c8196f5450 fb_sig_app_id: "118248144857525" fb_sig_country: de fb_sig_expires: "1275602400" fb_sig_ext_perms:"status_update,photo_upload,video_upload,email,create_note,share_item,auto_publish_short_feed,publish_stream,auto_publish_recent_activity,user_photos,user_about_me" fb_sig_in_new_facebook: "1" fb_sig_is_mockajax: "1" fb_sig_locale: de_DE fb_sig_profile_update_time: "1273871243" fb_sig_session_key: 2.Nl5c21AzK2dECyAy4OA6MA__.3600.1275602400-100001083140636
fb_sig_time: "1275595569.8487" fb_sig_user: "100001083140636" fb_target_id: "0" interview: answer_id: "1187" aw_question_id: "502" friend_ids: "100000504573704,100000991626598,100000406130258,100000516742887" question_id: "428" selected_friend_ids: ? "0" : "100000991626598" post_form_id_source: AsyncRequestrack.request.form_input: "#<PhusionPassenger::Utils::RewindableInput:0x000000047d92b8>"rack.run_once: "false"rack.session: facebook_session: "#<Buddy::Session:0x000000045f3ab0>" session_id: d734d3093ade7a519ae06d8316058cf0rack.session.options: domain: "" expire_after: "" httponly: "true" id: d734d3093ade7a519ae06d8316058cf0 key: _session_id path: /rack.url_scheme: httprack.version: "[\"1\", \"0\"]"
Backtrace:----------[PROJECT_ROOT]/vendor/gems/i18n-0.3.7/lib/i18n/backend/base.rb:204:in `rescue in interpolate'[PROJECT_ROOT]/vendor/gems/i18n-0.3.7/lib/i18n/backend/base.rb:180:in `interpolate'[PROJECT_ROOT]/vendor/gems/i18n-0.3.7/lib/i18n/backend/base.rb:45:in `translate'[PROJECT_ROOT]/vendor/gems/i18n-0.3.7/lib/i18n.rb:235:in `translate'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_view/helpers/translation_helper.rb:15:in `translate'[PROJECT_ROOT]/app/views/interview/answers/show.fbjs.erb:60:in `_render_template_133469630_36097516_0'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_view/template.rb:46:in `block in render'[GEM_ROOT]/gems/activesupport-3.0.0.beta3/lib/active_support/notifications/instrumenter.rb:18:in `instrument'[GEM_ROOT]/gems/activesupport-3.0.0.beta3/lib/active_support/notifications.rb:48:in `instrument'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_view/template.rb:44:in `render'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_view/render/rendering.rb:58:in `block in _render_template'[GEM_ROOT]/gems/activesupport-3.0.0.beta3/lib/active_support/notifications/instrumenter.rb:18:in `instrument'[GEM_ROOT]/gems/activesupport-3.0.0.beta3/lib/active_support/notifications.rb:48:in `instrument'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_view/render/rendering.rb:55:in `_render_template'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_view/render/rendering.rb:25:in `render'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/abstract_controller/rendering.rb:113:in `_render_template'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/abstract_controller/rendering.rb:107:in `render_to_body'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/renderers.rb:47:in `render_to_body'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/compatibility.rb:55:in `render_to_body'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/abstract_controller/rendering.rb:100:in `render_to_string'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/abstract_controller/rendering.rb:91:in `render'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/rendering.rb:17:in `render'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/instrumentation.rb:39:in `block (2 levels) inrender'[GEM_ROOT]/gems/activesupport-3.0.0.beta3/lib/active_support/core_ext/benchmark.rb:17:in `block in ms'/usr/lib64/ruby19/1.9.1/benchmark.rb:309:in `realtime'[GEM_ROOT]/gems/activesupport-3.0.0.beta3/lib/active_support/core_ext/benchmark.rb:17:in `ms'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/instrumentation.rb:39:in `block in render'[GEM_ROOT]/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/instrumentation.rb:77:in`cleanup_view_runtime'[GEM_ROOT]/gems/activerecord-3.0.0.beta3/lib/active_record/railties/controller_runtime.rb:15:in
F Internetmaterial Seite 103
F. Internetmaterial
F.1. Facebook
F.1.1. Graph-API
Quelle: http://developers.facebook.com/docs/api
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Dieser Teil des Facebook-Developers-Wiki befasst sich mit
der Dokumentation zur Graph-API, welche im April 2010 gestartet ist. Mit der
Graph-API versucht Facebook den Entwicklern einen einfachen und konsistenten
Weg anzubieten, mit dem Daten gelesen und geschrieben werden konnen. Jedes
Objekt, auf welches zugegriffen werden soll, besitzt eine eindeutige ID. Objekte
sind beispielsweise Benutzer, Fotos, Veranstaltungen oder Seiten. Um Informatio-
nen uber ein Objekt in Form eines JSON-Strings zu erhalten, genugt es die URL
https://graph.facebook.com/ID mit der entsprechenden ID aufzurufen. Neben
dieser Einfuhrung werden verschiedene weitere Aspekte der Graph-API beleuchtet.
Von Interesse ist auch die unter dem Punkt “Analytics” erlauterte Moglichkeit, Ein-
sicht in die Statistiken einer Anwendung zu bekommen, wie es auch im Uberblick in
Kapitel 1 erwahnt wird.
F.1.2. 500 Million Stories
Quelle: http://blog.facebook.com/blog.php?post=409753352130
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Facebook hatte zum Zeitpunkt, als diese Thesis geschrieben
wurde, mehr als 500 Millionen aktive Nutzer. Mark Zuckerberg, Grunder von Face-
book, schreibt dies in einem Blog-Beitrag vom 21. Juli 2010.
F.1.3. Developer Principles & Policies
Quelle: http://developers.facebook.com/policy/
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Anwendungen fur Facebook mussen, neben den allgemeinen
Geschaftsbedingungen, den auf dieser Seite aufgefuhrten Prinzipien und Richtli-
nien entsprechen. Als Prinzipien werden genannt, dass die Anwendungen vertrau-
enswurdig sein mussen, und fur den Benutzer eine schone Erfahrung sein sollen. Die
Richtlinien werden damit eingeleitet, dass jede Anwendung ihre eigenen Richtlinien
(z.B. fur die Datensicherheit) auf jeder Seite anzeigen mussen. Im Weiteren folgen
F Internetmaterial Seite 104
Richtlinien uber Funktionalitat, Inhalt und Zugriff auf Facebook-Daten. Abgeschlos-
sen wird die Seite durch Beispiele fur spezielle Punkte der Richtlinien.
F.1.4. Pages Guidelines
Quelle: http://www.facebook.com/page_guidelines.php
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Gultige Namen fur Facebook-Seiten mussen 3 Regeln genugen:
• Standardisierte Großschreibung
• Schlichter Text (z.B. keine unnotigen Satzzeichen)
• Prazise Namen (z.B. keine Slogans)
Weiter wird erwahnt, dass Seiten nicht nach allgemeinen Sachbezeichnungen be-
nannt werden durfen. Allgemeine Begriffe (genannt wird unter anderem “Pizza”)
unterliegen offentlichen Interessen. Diese sollen nicht von Marken fur Werbung be-
nutzt werden.
F.2. Ruby
F.2.1. Jeweler
Quelle: http://github.com/technicalpickles/jeweler
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Jeweler ist ein Tool, welches einen Entwickler bei der Erstel-
lung eines Gems unterstutzt. Auf der Seite des Repository werden eine Installa-
tionsanleitung sowie erste Schritte, um ein Projekt zu starten, aufgefuhrt. Neben
Modalitaten zur Veroffentlichung des Gems wird auch erklart wie die Version be-
stimmt werden kann.
F.2.2. Create Your Own Gem
Quelle: http://docs.rubygems.org/read/chapter/5
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Hier wird beschrieben, wie ohne zusatzliche Tools ein eigener
Gem erstellt werden kann. Es muss das Kommando gem build mygem.gemspec
aufgerufen werden, welche unter Zuhilfenahme der dafur notwendigen .gemspec-
Datei, einen Gem mit der Endung .gem erzeugt. Weiter wird erwahnt, dass rake ein
Tool ist, mit dem sich viele Aufgaben beim Erstellen eines Gems abnehmen lassen.
F Internetmaterial Seite 105
F.2.3. DataMapper
Quelle: http://datamapper.org/getting-started
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: DataMapper ist eine Alternative fur das in Rails mitgelierte
ORM, um die Datenhaltung einer Anwendung zu ubernehmen. Das Backend von
DataMapper wird als eigener Gem installiert, welcher einem bestimmten Namens-
schema entspricht, und in der Konfiguration von DataMapper angegeben werden
kann. Anschließend wird erlautert, wie Modelle und Assoziationen in DataMapper
definiert werden konnen. Relevant fur die Thesis ist das Muster, wie ein Gem mittels
einem Namensschema ein eigenes Backend implementiert.
F.2.4. Toadhopper
Quelle: http://github.com/toolmantim/toadhopper
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Dies ist die Seite des Git-Repositories fur den Gem toadhopper.
Das Repository ist ein kostenloses Angebot der Community github. toadhopper kann
mittels Ruby direkt die API von Hoptoad (Kapitel 5.8.2) ansprechen. Neben dem
Repository ist auch eine Anleitung zur Benutzung des Gems zu finden. Das Code-
Beispiel aus Kapitel 7.4 ist aus dieser Anleitung. Neben einem Codebeispiel, wie der
Gem zu verwenden ist, findet sich noch eine Installationsanleitung.
F.2.5. Redis-Gem
Quelle: http://github.com/ezmobius/redis-rb
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Wie auch der Gem toadhopper (Anhang F.2.4), ist der Gem,
welcher die Schnittstelle zu Redis bietet, innerhalb der Community von github zu
finden. Neben dem Repository findet sich auch bei diesem Gem eine Anleitung, wie
die Schnittstellen, die der Gem bietet, zu benutzen sind.
F.3. Redis
F.3.1. Befehlsreferenz
Quelle: http://code.google.com/p/redis/wiki/CommandReference
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Die Befehlsreferenz fur Redis befindet sich innerhalb eines
Wikis, welches von Google Code gehostet ist. Die Referenz listet Befehle, mit denen
F Internetmaterial Seite 106
Redis in der Kommandozeile gesteuert werden kann, auf. Die Befehle sind in folgende
Bereiche unterteilt.
• Verbindungsaufbau
• Befehle auf alle Datentypen
• Befehle auf String-Datentypen
• Befehle auf Listen
• Befehle auf Sets
• Befehle auf sortierte Sets
• Befehle auf Hashes
• Sortierung
• Transaktionen
• Persistenz
• Befehle zur Wartung von entfernten Servern
Wie auf jeder Seite innerhalb eines Wikis, welches bei Google Code gehostet ist,
bietet sich auch die Moglichkeit uber die Seite zu diskutieren.
F.3.2. Sets
Quelle: http://code.google.com/p/redis/wiki/Sets
Zuletzt uberpruft: 27.07.2010
Zusammenfassung: Diese Seite des Redis-Wikis bei Google Code handelt im spe-
ziellen uber die Verwendung von Sets. Die Information, dass Sets unsortierte Samm-
lungen von Strings sind, welche in Kapitel 7.5.2 verwendet wird, ist hier zu finden.
Neben Details zur Implementierung, werden die Befehle welche auf Sets angewendet
werden konnen, aufgefuhrt und zu der jeweils eigenen Wiki-Seite verlinkt.
Eidesstattliche Erklarung Seite 107
Eidesstattliche Erklarung
Hiermit erklare ich eidesstattlich, dass die vorliegende Arbeit von mir selbststandig
und ohne unerlaubte Hilfe angefertigt wurde, insbesondere, dass ich alle Stellen,
die wortlich oder annahernd wortlich oder dem Gedanken nach aus Veroffentlichun-
gen und unveroffentlichten Unterlagen und Gesprachen entnommen worden sind, als
solche an den entsprechenden Stellen innerhalb der Arbeit durch Zitate kenntlich
gemacht habe, wobei in den Zitaten jeweils der Umfang der entnommenen Original-
zitate kenntlich gemacht wurde. Ich bin mir bewusst, dass eine falsche Versicherung
rechtliche Folgen haben wird.
Ort, Datum Unterschrift