Home
Keine 4. Auflage von RWDMROR
22. February 2010Aufgrund einiger Nachfragen, hier kurz eine "Pressemitteilung" :)
Zum Buch "Rapid Web Development mit Ruby on Rails" wird es erstmal keine 4. Auflage geben.
Ralf und ich sind vor allem aus Zeitgründen privater und beruflicher Art nicht in der Lage, eine neue Auflage zu Rails 3 zu schreiben. Kurzfristig gab es die Idee, dass uns Phillip Oertel unterstützt, aber der hat dann ebenfalls aus Zeitgründen passen müssen.
Die Entscheidung ist uns nicht leicht gefallen, aber vorerst geht es nicht anders.
Vielen Dank an aller Leser für das Lob und die Anregungen!
History der Rails-Console reaktiviert
19. November 2009Irgendwann, vermutlich nach einem Update von Ruby und/oder Rails, stand die History meiner Rails Console nicht mehr zur Verfügung.
Nachdem ich damit eine gewisse Zeit leben konnte, wollte ich heute dem Grund auf die Schliche kommen.
Nach einigem Probieren kam ich darauf, dass die Konsole und deren History unter ~/.irb_history schon funktioniert. Sie wird allerdings durch die Datei ~/.rdebug_hist erweitert.
Ein Durchlaufen der einzelnen Einträge durch "Pfeil-Taste hoch" lief erst durch die Einträge des Debuggers und fand dann irgendwann auch die Einträge aus ~/.irb_history. Man musste nur oft genug Tippen :).
Ein Löschen der Datei ~/.rdebug_hist führte dazu, dass die letzten Einträge in der Konsole beim nächsten Aufruf sofort zur Verfügung standen.
Die Datei ~/.rdebug_hist wird durch ruby-debug (genauer ruby-debug-0.10.3/cli/ruby-debug/interface.rb) eingelesen und geschrieben. Ich habe den Code noch nicht ganz durchschaut, aber die Datei wurde trotz des Einsatzes des Debuggers bisher nicht wieder erzeugt. Sicherheitshalber habe ich die Datei selbst schreibgeschützt angelegt, um eine erneute Erzeugung zu vermeiden.
touch ~/.rdebug_hist
chmod 400 ~/.rdebug_hist
Logging in der Rails-Console reaktiviert
Darüber hinaus habe ich das Aktivieren und Deaktivieren der Logausgaben
in der Rails-Konsole wieder hinbekommen. Meine ~/.irbrc sieht wie folgt aus:
1 2 3 4 5 Wirble.init 6 Wirble.colorize 7 8 9 system(%{ri }) 10 end 11 12 if ENV.include?('RAILS_ENV') 13 14 15 ActiveRecord::Base.connection.select_all(query) 16 end 17 18 19 set_logger Logger.new(STDOUT) 20 end 21 22 23 set_logger @logger 24 end 25 26 27 ActiveRecord::Base.connection.instance_variable_get("@logger") 28 end 29 30 31 @logger ||= get_logger 32 ActiveRecord::Base.connection.instance_variable_set("@logger", logger) 33 end 34 35 end 36
Update: Ich nutze Rails 2.3.4 und Ruby ruby 1.8.7
Ruby include Part I
16. September 2009Ein häufiger Denkfehler beim Einbinden eines Moduls per include in eine Klasse ist, dass die Methoden aus dem Modul tatsächlich in die Klasse eingefügt werden. Dem ist nicht so. Hier ein Beispiel:
"M1#foo"
end
end
include M1
end
Der Aufruf von include M1 führt intern nicht zu folgendem Code:
"M1#foo"
end
end
Tatsächlich wird durch include eine anonyme Proxyklasse erzeugt, die auf das Modul verweist und die Klasse A erhält eine Referenz auf diese Proxy-Klasse:
-> M1
end
-> proxy
end
a = A.new
a.foo
Im obigen Beispiel findet Ruby die Methode foo also nicht in der Klasse A, sondern (über die Proxy-Klasse) im Modul M1.
Suche entlang der Vererbungshierachie
Grundsätzlich gilt: Um eine Methode auszuführen, muss Ruby die Definition der Methode finden und sucht die Methode dazu entlang der Vererbungshierachie. Ein Beispiel:
include M1
include M2
end
a = A.new
a.foo
Damit ergibt sich diese Suchreihenfolge:
1) A 2) M2 (über proxy) 3) M1 (über proxy) 4) B
Die Vererbungshierachie sieht wie folgt aus:
A -> (proxy->M2) -> (proxy->M1) -> B
Es wird bei der Klasse A begonnen. Wird die Methode nicht gefunden, wird im Modul M2 gesucht. Ist die Methode hier nicht vorhanden, wird im Modul M1 gesucht und existiert die Methode hier nicht, wird in der Superklasse B nachgeschaut. Dort wiederholt sich die Suche.
Daher hat eine in der Klasse A definierte Methode immer Vorrang vor einer gleichnamigen aus einem inkludierten Modul:
"M1#foo"
end
end
-> proxy -> M1
"A#foo"
end
end
a = A.new
a.foo # => "A#foo"
Ruby sucht die Methode entlang der Vererbungshierachie und findet die Methode in der Klasse A bevor es im Modul M1 sucht.
Modulmethode über super aufrufen
Es ist sicher bekannt, dass die Methode super dazu dient, eine gleichnamige Methode in der Superklasse aufzurufen. Beispiel:
"SuperClass#foo"
end
end
"A#foo: "
end
end
a = A.new
a.foo # => "A#foo: SuperClass#foo"
Was vielleicht nicht sofort einleuchtet ist, dass auch die Modulmethode über super aufgerufen werden kann. Das Modul befindet sich (wie die Superklasse auch) in der Vererbungshierachie und daher kann sowohl die Superklassenmethode, als auch die Modulmethode über super aufgerufen werden:
"M1#foo"
end
end
include M1
"A#foo: "
end
end
a = A.new
a.foo # => "A#foo: M1#foo"
Vorrang beim Einbinden von Modulen
Werden zwei Modul eingebunden und erhalten diese dieselbe Methode, so wird die Methode des zuletzt inkludierten Moduls verwendet. Im Beispiel M2:
"M1#foo"
end
end
"M2#foo"
end
end
include M1
include M2
end
a = A.new
a.foo # => M2#foo
Einschränkung der Sichtbarkeit
Mit dem Wissen um die Wirkung von include, wird auch klar, warum die Einschränkung der Sichtbarkeit wie folgt nicht möglich ist:
"mod_method1"
end
end
"mod_method2"
end
end
include M1
private
include M2 # method mod_method2 is still public
end
A.new.mod_method1 # => "mod_method1"
A.new.mod_method2 # => "mod_method2"
Die Methoden aus dem Modul M2 sind öffentlich (public), obwohl das Modul nach dem Schlüsselwort private eingebunden wird. Und zwar, weil die Methode aus dem Modul nicht in die Klasse eingebunden werden, sondern die Klasse auf das Modul verweist (über den Proxy) und mod_method2 in M2 öffentlich ist.
Korrekt geht es wie folgt:
private
"mod_method2"
end
end
include M1
include M2
mod_method2
end
end
A.new.foo # => "mod_method2"
A.new.mod_method1 # => "mod_method1"
A.new.mod_method2 # => NoMethodError: private method ‘mod_method2’ called
for #<A:0x108d8>
Wenn eine Modulmethode nur für interne Implementierung dient, sollte die Methode auf jeden Fall als private deklariert werden.
Proxy-Klasse
Wozu dient eigentlich die Proxy-Klasse? Warum wird nicht direkt eine Referenz auf das Modul in die Klasse eingefügt? Wozu der Umweg über die Proxy-Klasse?
Die Proxy-Klasse ist notwendig, da von Modulen keine Instanzen erzeugt werden können. Dennoch möchte man eventuell Instanzvariablen von Modulen nutzen.
Inkludieren die Klassen A und B das Modul M1, so darf die Änderung einer Instanzvariablen in der Klasse A nicht den Wert in B beeinflussen. Daher gibt für A und B jeweils eine Proxy-Klasse und die die Werte hält.
Alle Proxy-Klasse verweisen auf dasselbe Modul, daher werden Änderung an Methoden des Moduls in alle Klassen sichtbar:
@foo = v
end
"M#foo: "
end
end
include M
self.foo = v
end
end
include M
self.foo = v
end
end
a = A.new(47)
p a.foo # => "M#foo 47"
b = B.new(11)
p b.foo # => "M#foo 11"
"modified M#foo "
end
end
p a.foo # => "modified M#foo 47"
p b.foo # => "modified M#foo 11"
Hoffe, ich habe für mehr Klarheit sorgen können und nicht mehr verwirrt :)
to be continued ...
Rails-Konferenz 2009 Review
13. September 2009
Ist schon wieder zwei Wochen her, dass wir die 4. Rails-Konferenz hinter uns gebracht haben.
Diesmal fand die Konferenz im ACHAT Plaza Frankfurt/Offenbach statt. Das Hotel machte einen durchweg guten Eindruck, liegt allerdings verkehrstechnisch nicht besonders günstig. Auch der Vorraum für Pausen ist für 100+ Personen einfach viel zu klein. Die Zimmer waren sauber und geräumig und das Essen gut. Für 2010 werden wir uns aber trotzdem nach einer Alternative umschauen. Wer Tipps hat, bitte melden.
Den Gesprächen und Feedback-Bögen zur Folge, ist die Konferenz auch diese Jahr wieder sehr gut angekommen. Die Workshops, Vorträge und das Socializing zwischendurch ergaben ein rundes Bild.
Nur der Ort des Vorabend-Events kam nicht so gut an, weil die Teilnehmer vom Hotel in Offenbach erst in die Innenstadt von Frankfurt mussten. Das ACHAT-Hotel selbst wäre ein guter Ort gewesen, kostete aber zu viel Geld. Die Lounge im Fleming's Club kam bei den Anwesenden dann aber gut an. Danke auf diesem Wege nochmals an XING für das Sponsoring und die Vorträge!
Danke auch an alle Sponsoren, Speaker und Teilnehmer!!!
Dem Feedback nach zu urteilen, werden auch 2010 wieder genügend Teilnehmer kommen. In diesem Sinne: bis 2010!.
Ticket-Rabatt auf rubyonrails.de
10. August 2009Na, dann mal schnell zuschlagen :)
Vielen Dank an Kaan für die Unterstützung!
Rails Plugin amount_field
07. August 2009
Da ich nichts adäquates an Gems oder Plugins gefunden habe, habe ich mich selbst daran gemacht. Und das war anfangs gar nicht so einfach :)
Es ist die Eingabe (die Übertragung aus dem Formular an die Rails-Anwendung) und die korrekt formatierte Ausgabe (Anzeige im View/Formular) zu betrachten.
Eingabe
Vorweg folgende Definition:- Formatvalidierung: z.B. ist "1.234,56" ein gültiges Format?
- Wertvalidierung: z.B. ist 1.234,56 > 1250 ?
- Damit sichergestellt werden kann, dass der eingegebene Wert wirklich ein gültiges Format hat (z.B. 1.234,56), muss zunächst eine Formatvalidierung erfolgen und danach die (sichere) Konvertierung in eine Zahl 1234.56. Im Anschluss kann optional die Wertvalidierung erfolgen.
Ohne die Formatvalidierung würde Rails aus 1.234,56 den Wert 1.23 machen, ohne dass der Anwender das gegebenenfalls merkt. Und das ist schlecht.
-
Die Formatierung (Ein- und Ausgabe) hat eigentlich nichts mit dem Attribut oder dem ActiveRecord-Modell zu tun. Es handelt sich ja mehr um eine bestimmte Repräsentation eines Betrags und dafür ist das Modell nicht zuständig. Zur formatierten Anzeige werden u.a. die View-Helper von Rails genutzt.
Die Konvertierung von "1.234,56" in 1234.56 kann aber nicht auf Controller/View-Ebene erfolgen, da die Validierung der Attribute in ActiveRecord geschieht. Und die Formatvalidierung ist eben eine solche Validierung. Daher bleibt doch nur das Modell.
- Die Zuweisung als Ruby-Zahl an den Setter (an das Attribute) muss weiterhin wie gewohnt möglich sein:
p = Product.new p.price = '12.345,67' # schlecht p.price = 12345.67 # ok - Der Getter des Attributs muss den Wert als (Ruby-)Zahl liefern, damit Berechnungen weiterhin wie gewohnt möglich sind:
p = Product.new(:price => 1.23) p.price # => 1.23 damit Rechnen möglich tax = p.price * 19.0 / 100.0 - Eine clientseitige Formatvalidierung (und Formatierung) durch JavaScript ist hilfreich, verhindet aber nicht unbedingt die Übertragung falsch formatierter Beträge und daher ist eine serverseitige Formatvalidierung immer notwendig.
- Die Formatierung eines Betrags besteht immer aus den drei Werten:
- Separator (Tausendseparator)
- Delimiter (Trennung Ganzzahl und Nachkommastellen)
- Precision (Anzahl der Nachkommastellen)
Die drei Werte bilden die Formatkonfiguration:
deutsch:{ :precision => 2, :delimiter => '.', :separator => ',' }
amerikanisch:{ :precision => 2, :delimiter => ',', :separator => '.' } - Fehlermeldungen bei einen falschen Format sollten internationalisierbar sein
- Hinweis: Active Record speichert den übergebenen Wert “1.234,56” in dem Attribute "price". Erst beim Lesen des Wertes wird dieser konvertiert zurückgeliefert. Daher liefert "price_before_type_cast" den Wert “1.234,56” und "price" den Wert 1.234 zurück. Die Wertvalidierung erfolgt bei Active Record auf Basis von XXX_before_type_cast.
Als Lösung definiere ich einen eigenen View-Helper "amount_field" als Ersatz für "text_field". Das HTML sieht wie folgt aus:
<input name="product[amount_field_price]" class=" amount_field"... />
Der eingegebene Wert (z.B. "1.234,56") wird dadurch über den Parameter amount_field_price und nicht (wie normalerweise) über den Parameter price übertragen.
Zusätzlich existiert das Validierungsmakro "validates_amount_format_of", dass für jedes angegebene Attribut eine spezielle Setter-Methode (z.B. amount_field_price=(value) definiert, die den Parameter amount_field_price annimmt und Werte im Format "1.234,56" akzeptiert.
validates_amount_format_of :price
end
Nach der Validierung und Konvertierung (z.B. "1.234,56" in 1234.56) wird der Wert an das Originalattribut "price" zugewiesen und kann von weiteren Validierungsmakro geprüft werden (z.B: validates_numericality_of :price).
Ausgabe
Damit die Ausgabe des Wertes 1234.56 formatiert erfolgt (z.B. "1.234,56"), verwendet der View-Helper amount_field intern den View-Helper number_with_precision mit der global definierten Formatkonfiguration. Im Fehlerfall wird der Wert nicht formatiert, sondern wie eingegeben angezeigt.
Das Gem (oder Plugin) inklusive Dokumentation ist unter GitHub zu finden.
Freue mich über Feedback, Fragen oder Fehlermeldungen.
Anmeldung zur Rails-Konferenz.de 2009 online!
22. July 2009Programm Rails-Konferenz 2009 online
20. July 2009Shoulda Macros werden nicht gefunden
16. July 2009
undefined method ‘should_validate_presence_of’ for PoliceTest:Class
Es handelt sich dabei um Rails 2.3 und Shoulda 2.10.2. Der Quellcode dazu sieht wie folgt aus:
Nachdem ich zwei weitere require-Einträge vorgenommen habe, ging es:
Zum Zeitpunkt des Blog-Eintrags werden auf der Shoulda-Seite noch Macros wie should_require_attributes
oder should_require_unique_attributes aufgeführt, die es in der Version 2.10.2 (oder früher) nicht mehr gibt.
Artikel zum Gem- und Plugin-Erstellung
16. April 2009
In der am Montag, dem 20. April erscheinenden dritten Ausgabe des RailsWay-Magazins habe ich wieder einen Artikel beigesteuert. Diesmal geht es um das Thema, wie man ein eigenes Ruby-Gem und Rails-Plugin erstellt.
Weitere spannende Artikel und ein Interview mit David Heinemeier Hansson sind enthalten.
Viel Spaß mit dem neuen Magazin!
Rails-Konferenz.de@twitter
02. April 2009Heiko Webers - Sicherheitsaspekte von Rails-Anwendungen
16. March 2009
Download: MP3 (50:12 Min, 16.7 MB)
Podcast-Abo: RSS mit Enclosures
Weitere Links:
Ruby on Rails Security Project
PDF: Ruby on Rails Security
Ruby On Rails Security Guide
Session auf der Rails-Konferenz 2008
Cross Site Request forgery (csrf)
Newsletter zur Rails-Sicherheit
Newsletter Sicherheitslücken in Ruby
bauland42
Heiko Webers ist Gründer und Geschäftsführer von bauland42. Das Softwarebüro bauland42 erstellt sichere, effiziente und einfach zu bedienende Webanwendungen mit Ruby on Rails. Außerdem bietet bauland42 Sicherheitsberatung, Code-Audits und Training für Ruby on Rails. bauland42 informiert mit dem Ruby On Rails Security Project regelmäßig über neue Entwicklungen im Bereich der Sicherheit von Rails.
Der Podcast ist etwas länger geworden, als geplant, aber das Thema Sicherheits ist nicht mal eben abzuhandeln. Und wir haben sicher noch lange nicht alle Punkte angesprochen :). An der Qualität der Aufnahmen muss ich noch etwas pfeilen, aber besser so, als gar nicht.
Danke an Heiko!
Rails-Konferenz 2009
15. March 2009Gute Neuigkeiten für alle Rails-Interessierten:
Die Rails-Konferenz findet auch dieses Jahr wieder statt!
Termin & Ort
1. und 2. September 2009
ACHAT Plaza Frankfurt/Offenbach
Ernst-Griesheimer-Platz 7
D - 63071 Offenbach
ACHAT Plaza Frankfurt/Offenbach
Auch dieses Jahr freuen wir uns wieder auf spannende Vorträge, interessante Diskussionen, den Erfahrungsaustausch in gemütlicher Atmosphäre und vieles mehr!
Seit dabei, es lohnt sich!Alle Informationen unter Rails-Konferenz.de!
Mac Image mit SuperDuper klonen
03. March 2009Nun ist es da, mein neues MacBook. Ich habe mich für die 13 Zoll Version mit 4 GB Hauptspeicher und 250 GB Festplatte entschieden.
Die Version ist für Reisen leichter und kleiner, als mein altes MacBook Pro mit 15 Zoll. Und da ich über ein 20 Zoll Cinema Display verfüge, habe ich bei längeren Arbeiten auch ein entsprechend großes Display. Für mich im Moment die optimale Kombination.
Die Daten auf dem alten MacBook Pro habe ich regelmäßig mit Hilfe von SuperDuper als Standard Sparse Image auf eine externe Festplatte gesichert. Diese Sicherung ermöglichte mir nun, das neue MacBook einfach mit dem Image zu versehen und somit sofort mit dem neuen Rechner arbeiten zu können. Keine technische Neuigkeit, aber dennoch erfreulich.Einfach eine Image vom alten Rechner auf der externen Festplatte erzeugen. Das kann schon mal 1-2 Stunden dauert. Festplatte am neuen MacBook am USB-Port anschließen (ggf. Firewire-Kabel abziehen!) und neu starten. Dabei Optionstaste (Alt) gedrückt halten. Statt der Mac-Partition, das Image auswählen und davon booten. (Seit dem Intel-Prozessor können Macs auch von USB-Platten booten!). Dann mit Hilfe des Festplatten-Dienstprogramms den Reiter Wiederherstellen klicken, also Quelle das Image und als Ziel die MacBook-Platte wählen. Den Hacken bei "Zielmedium löschen" setzen und "Wiederherstellen" klicken.
Neustart und mit dem neuen Mac loslegen. Prima!
Lohnt sich der Aufwand der Pixelschieberei?
03. March 2009
Warum muss eine Seite im Internet Explorer exakt so aussehen, wie im Firefox oder Safari?
Wer stört sich als Anwender wirklich an kleinen Unterschieden?
Wechselt der Benutzer häufig zwischen den Browsern, so dass ihm die Unterschiede negativ auffallen?
Und machen Sie die Seiten dann für ihn schwerer nutzbar?
Diesem Thema widmet sich Ingo Chao im lesenswerten Artikel Degradation Without Grace.
