Ich erstelle momentan ein kleines, sehr spezielles CMS mit Ruby on Rails, mein erstes komplettes Rails Projekt. Der Umstieg von Java in die Rails-Welt war zwar gewöhnungsbedürftig und hatte einige Hürden, aber es hat sich gelohnt. Hier ein kleines, schönes Beispiel wie man mit wenigen Zeilen Ruby ziemlich universellen Code erzeugen kann.
Die Anforderung war, alle Eingabefelder im CMS, z.B. die Beschriftung der Bilder oder Überschriften und Artikel, einzeln editierbar zu machen. D.h. man klickt bzw. doppelklickt das Feld an, editiert es und die Änderung wird beim Verlassen des Feldes gespeichert.
Undenkbar hier für jedes Feld eigene Methoden im Controller oder JavaScript anzulegen.
Die Lösung besteht aus drei Teilen wobei ich hier nur den Controller näher erläutern möchte.
Teil 1 ist eine Helpermethode die ein entspr. Eingabefeld erzeugt.
Teil 2 ist eine kleine JavaScript Funktion die den Wert des Feldes per Ajax an den Controller sendet.
Teil 3 ist der Controller der den neuen Wert speichern soll.
Idee war es dem Controller folgende Werte zu liefern:
- Name der Model Klasse
- ID des Datensatzes
- Name des Attributes
- Wert des Attributes
Die ersten drei Werte werden durch einen Punkt getrennt als ID des HTML input gesetzt, z.B.: Image.34.caption
Jetzt aber zum Controller, der nur aus einer public Methode besteht:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class FieldsController < ApplicationController layout nil def update a = params[:key].split('.') update_field a[0], a[1], a[2], params[:value] head :status => 200 end private def update_field classname, id, attr, value # must be a ActiveRecord::Base obj = ActiveRecord::Base.const_get(classname).find(id) obj.update_attribute(attr, value) end end |
Die als “key” übergebenen Werte werden erstmal zerlegt und der Methode update_field übergeben. Hier wird die Model-Klasse über die Kernel Funktion const_get geladen (Klassennamen sind in Ruby Konstanten). Das machen wir direkt auf ActiveRecord::Base, weil wir dort alle Model Klassen finden werden und somit nicht Kernel.const_get verwenden müssen. Auf der Modelklasse rufen wir direkt ein find mit der ID auf und bekommen die Instanz unseres Datenobjekts. Auf diesem setzen wir den Wert des Attributs mit update_attribute neu. Fertig.
Der Controller liefert dann noch den Status 200 zurück, damit unser AjaxRequest weiß, dass alles ok ist.
Auf ActiveRecord::Base gibt es noch weitere update Methoden, so könnte man z.B. auch mehrere Attribute updaten.