ActionPack 1.12.0 ActiveRecord 1.14.0 ActiveSupport 1.3.0 | RailTies 1.1.0 Prototype 1.5.0 Scriptaculous 1.6.0 |
Neues in ActionPack 1.12.0RJS-TemplatesAnalog zu rxml und rhtml gibt es jetzt die Fusion von Ruby- und JavaScript-Code. In RJS-Dateien steht Ruby-Code, der JavaScript erzeugt, ähnlich den rxml-Templates. Dieser Code wird als Ergebnis eines AJAX-Aufrufs an den Browser gesendet und dort ausgeführt. Kurz: RJS-Templates sind Browser-Scripte. Es klingt kompliziert, aber damit ist AJAX-Entwicklung bedeutend einfacher geworden. Hintergrund (englisch):
BeispielSolche Dinge können in einer .rjs-Datei stehen:# Der erste Kauf lässt "cart" erscheinen, folgende lassen ihn blinken page[:cart].visual_effect(@cart.size == 1 ? :appear : :highlight) # Ersetze "cart" mit dem frischen Inhalt aus dem Partial "cart" page[:cart].replace_html :partial => "cart" # Alle DOM-Elemente der Klasse "product" blinken page.select(".product").each do |element| element.visual_effect :highlight end # Rufe die JavaScript-Funktion AddressBook.cancel() auf page.address_book.cancel # Setze in 4 Sekunden den font-style aller spans auf "normal" page.delay(4) do page.select("td span.company").each do |column| column.set_style :fontStyle => "normal" end end pageDas
Inline-RJSZusätzlich zu den .rjs Dateien im Ordner app/views gibt es auch die Möglichkeit, Inline-RJS zu benutzen: class UserController < ApplicationController def refresh render :update do |page| page.replace_html 'user_list', :partial => 'user', :collection => @users) page.visual_effect :highlight, 'user_list' end end end HilfsmoduleNatürlich kann man RJS-Hilfsmodule schreiben und sie mit dem module ApplicationHelper def update_time page.replace_html 'time', Time.now.to_s(:db) page.visual_effect :highlight, 'time' end end class UserController < ApplicationController def poll render :update { |page| page.update_time } end end respond_toMit class WeblogController < ActionController::Base def index @posts = Post.find :all respond_to do |wants| wants.html # Normales Template in app/views/weblog/index.rhtml wants.xml { render :xml => @posts.to_xml } # es wird XML generiert und mit dem korrekten MIME-Typ gesendet wants.js # nutzt das RJS-Template in app/views/weblog/index.rjs end end end Damit ist es möglich, ganz nebenbei zur Applikationsentwicklung für den Browser auch noch einen WebService zu erstellen. Mehr dazu findet man bei Jamis Buck: Web services, Rails-style. Integration TestsIntegration Tests sind eine weitere Sorte von Tests. Sie erlauben es, innerhalb einer Rails-Applikation das Zusammenspiel von mehreren Controllern und Aktionen zu testen. Für diese Art von Tests existiert seit Rails 1.1 der Ordner test/integration. Ein einfacher Integrationstest unterscheidet sich kaum von einem funktionalen Test: require "#{File.dirname(__FILE__)}/test_helper" require "integration_test" class ExampleTest < ActionController::IntegrationTest fixtures :people def test_login # fordere die Login Seite an get "/login" assert_equal 200, status # sende die Logindaten per POST-Request und folge der Applikation zur Homepage post "/login", :username => people(:jamis).username, :password => people(:jamis).password follow_redirect! assert_equal 200, status assert_equal "/home", path end end Mit Integrations-Tests besitzt man weiterhin die Möglichkeit, mehrere Sessions pro Test zu erzeugen und eine Interaktion dieser Instanzen zu testen. Zum Beispiel verwendet 37Signals für Campfire die Tests so: def test_login_and_speak jamis, david = login(:jamis), login(:david) room = rooms :office jamis.enter room jamis.speak room, "jemand da?" david.enter room david.speak room, "hallo!" end module CustomAssertions def enter room # benutze eine benannte Route, um die interne Konsistenz zu prüfen get room_url(:id => room.id) assert ... end def speak room, message xml_http_request "/say/#{room.id}", :message => message assert ... end end def login who open_session do |sess| sess.extend CustomAssertions who = people who sess.post "/login", :username => who.username, :password => who.password assert ... end end Wie man sieht, kann mit geringem Aufwand eine sehr mächtige Test-Sprache (DSL) erstellt werden, die beliebig erweiterbar ist. Auch hier hat Jamis eine Einführung geschrieben: Jamis Buck: Integration Testing in Rails 1.1 render:xmlrender :xml => '<quiek><foo>bar</foo></quiek>' ...funktioniert wie content-typerender hat jetzt eine neue Option, um den Inhaltstyp der Antwort anzugeben, sollte sie von text/html
abweichen:
render 'atom.rxml', :content_type => Mime::ATOM render :text => mein_hund.to_yaml, :content_type => 'text/yaml' Helperselect :selected => auswahlDie neue Option auto_link mit BlockJeder gefundene Link wird durch den Block geschickt, bevor er ausgegeben wird:auto_link post_body { |link| truncate link, 10 } Neue Form-Helfer
<%= form_tag :action => "update" %> Vorname: <%= text_field 'person', :first_name %> Nachname: <%= text_field 'person', :last_name %> Administrator?: <%= check_box 'person', :admin %> <%= end_form_tag %> <% form_for :person, @person, :url => { :action => "update" } do |p| -%> Vorname: <%= p.text_field :first_name %> Nachname: <%= p.text_field :last_name %> Administrator?: <%= p.check_box :admin %> <% end -%> Bitte die verschiedenen ERb-Modi beachten: Die englische API-Doku hierzu ist inzwischen sehr informativ. JavaScript-HelferAus dem Einige Methoden bieten neue Möglichkeiten:
Kleinere Änderungen
Sonstigesparam_parsersMit der neuen automatisierten Behandlung Request-Parameter ist das Erstellen moderner REST-WebServices ein Kinderspiel.
ini = Mime::Type.new 'application/ini', :ini ActionController::Base.param_parsers[ini] = proc do |data| ini = IniFile.new data { 'ini' => ini } end CachingAction- und FragmentCaching ist nun problemlos möglich, die Daten werden im Verzeichnis tmp/cache gespeichert; siehe hierzu die Liste erzeugter Dateien und Ordner. Bugfixes
|