noSQL – Rails 2 Models mit SOAP

Als Rails-Entwickler ist es eine Selbstverständlichkeit eine Datenbank in seiner Anwendung zu nutzen. Das ist keine große Überaschung, da Rails ein datenbankgetriebenes Framework ist. Oft genug wird man aber durch die Plattformumgebung dazu gezwungen auf sein liebstes Werkzeug zu verzichten, eben diese Datenbank …

Man stelle sich eine serviceorientierte Java-Landschaft vor, in der es zwar tonnenweise Webservices gibt, man aber vergeblich nach einem Zugang zu einer Transaktionsdatenbank ausschau hält.

Schön wäre es, wenn man anstelle einer Datenbank einfach einen SOAP-Dienst in seine Rails Anwendung einbinden könnte, der sich um die Datenhaltung kümmert. Da Rails 2, im Gegensatz zum modularisierten Rails 3, sehr stark an eine Datenbank gekoppelt ist, muss man man selber etwas Hand anlegen, um die Stärke von ActiveRecord auch ohne DB nutzen zu können.

Warum überhaupt noch Rails?

Mit sicherheit gibt es einige Leute, die jetzt sagen würden: “Warum denn an Rails rumfummeln, nimm doch lieber Sinatra?!”.

Gegenüber Frameworks wie Sinatra hat Rails den großen Vorteil, dass fast jeder Ruby-Entwickler schon mal mit Rails gearbeitet hat. Die Rails-Community ist groß, lebendig und eine großartige Wissensquelle. Mit Rails bekommt man Features wie REST frei Haus und darüber hinaus will niemand den unerschöpflichen Pool an Rails-Plugins missen.

Arbeiten mit ActiveForm

Der wahrscheinlich einfachste Weg, um einen SOAP-Dienst für die Datenpersistenz in Rails zu benutzen und dabei nicht auf die Dienste von ActiveRecord::Validations verzichten zu müssen, ist durch den Einsatz von ActiveForm. Dies erlaubt Validierungen für Rails-Models, die keine ActiveRecords sind und ist auf github frei verfügbar.

Man kann es direkt als Rails-Plugin installieren:

# (re)install from git as a plugin
script/plugin install --force git://github.com/remvee/active_form.git

Um das Plugin zu benutzen, muss man nur das Model von ActiveForm anstelle von ActiveRecord::Base erben lassen:

# app/models/blog.rb
class Blog  :text
   
  validates_presence_of :title, :message
end

Will man auch noch die letzten Spuren der Datenbankanbindung verwischen, dann muss noch ein wenig an der Konfiguration gebastelt werden. Entfernt man ActiveRecord von der Liste der Rails-Frameworks und fügt es wieder als Gem hinzu, kann man anschließend sogar die database.yml löschen:

# config/environment.rb
Rails::Initializer.run do |config|
  config.gem "activerecord", :version => '2.3.5'
  config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
end

Savon als Basis für Multi-Tier-Persistenz

Einen Enterprise-SOAP-Dienst mit Savon anzusprechen ist einfach und die Integration in ein Rails-Model erfordert lediglich zwei Schritte:

  • Implementierung einer to_hash-Methode
  • Implementierung eines save-Hooks

Da die Savon-Kommunikation auf Hashes basiert, muss man nur eine dünne Schmierschicht für das Mapping zwischen Model und SOAP-Schnittstelle legen:

# app/models/blog.rb
def to_hash
  { :data => {:title => title, :message => message} }
end

Um die Daten im richtigen Moment über die Leitung zu schieben muss man seine eigene Persistenz-Logik implementieren. Ein guter Platz hierfür ist in einem save-Hook des Rails-Models:

# app/models/blog.rb
def after_save
  client = Savon::Client.new "http://localhost:8080/"

  client.post! do |soap|
    soap.namespace = "urn:savon:blog"
    soap.body = to_hash
  end
end

Das Überschreiben der after_save-Methode ist nette Idee, damit der Controller-Code weiterhin für andere Rails-Entwickler verständlich bleibt. Man sollte immer versuchen sich an Konventionen zu halten, denn dadurch verringert man drastisch die Komplexität!

Weitere Informationen?

Es gibt ein lauffähiges Beispiel auf github, dass mit einem soap4r-Server läuft.

Dieser Artikel wurde ins Deutsche übersetzt, das Original findet sich hier

Mehr? Aktuelle Artikel oder alle Artikel im Archiv.