Bei Fiona 7 gibt es zwei Betriebsarten, den ausschließlich an Scrivito orientierten standalone
-Modus sowie den legacy
-Modus, in dem Fiona 7 auch kompatibel zum Rails Connector ist.
Im Kompatibilitätsmodus (legacy
) werden die Model-Klassen für Vorlagen von RailsConnector::BasicObj
abgeleitet (meistens indirekt via Obj
). Eine Vorlage muss genau so heißen, wie die Klasse, auf der sie basiert. Dadurch ergibt sich ein Problem, wenn man die APIs des Scrivito SDK benutzen möchte, weil dieses auch von dieser Namensgleichheit ausgeht.
Da es in Ruby keine mehrfache Vererbung gibt, lässt sich dieser Konflikt nicht mit den Mitteln der Programmiersprache lösen.
Fiona 7 löst dieses Problem mit dem Konzept der Shadow Classes: Wenn man in einer Klasse, die von RailsConnector::BasicObj
abgeleitet ist, den in_place
-Block nutzt, dann wird eine zusätzliche, versteckte Klasse angelegt.
Fiona 7 verwendet diese versteckte Klasse als Ersatz für die fehlende globale Klasse für die Abwicklung aller internen Funktionen. Werden beispielsweise die in Homepage
definierten Attribute abgefragt, dann wird zunächst die Klasse Homepage
geladen und verwendet, wenn sie von Scrivito::BasicObj
erbt. Sollte dies nicht der Fall sein, wird es noch einmal probiert, diesmal mit ShadowClasses::Homepage
.
Ein Beispiel: die Vorlage Homepage
hat das Attribut headline
, das in-place bearbeitbar werden soll. In der Applikation gibt es bereits eine Definition für die Klasse Homepage
:
class Homepage < Obj
end
Die Klasse Obj
wiederum erbt ganz normal von RailsConnector::BasicObj
class Obj < RailsConnector::BasicObj
end
Nun wird in der Klasse Homepage
das headline
-Attribut im in_place
-Block hinzugefügt:
class Homepage < Obj
in_place do
attribute :headline, :string
end
end
Nach dieser Änderung kann man an geeigneter Stelle fiona7_tag @obj, :headline
einsetzen, um das Attribut headline
der Homepage
dort in-place bearbeitbar zu machen.
Intern wird durch den in_place
Block die Klasse ShadowClasses::Homepage
angelegt, die von ShadowClasses::Obj
erbt. Wenn man den in_place
Block in der Obj
-Klasse nutzt, dann findet sich die Definition in ShadowClasses::Obj
wieder.
Es werden also automatisch zwei Klassen definiert, die etwa wie folgt aussehen:
class ShadowClasses::Obj < Scrivito::BasicObj
end
class ShadowClasses::Homepage < ShadowClasses::Obj
attribute :headline, :string
end
Es ist somit möglich, ein Attribut global, also für alle definierten Vorlagen, festzulegen, indem man den in_place
-Block in der Obj
-Klasse einträgt:
class Obj < RailsConnector::BasicObj
in_place do
attribute :show_in_navigation, :enum, values: ['yes', 'no']
end
end
Im in_place
Block können alle Funktionen genutzt werden, die sonst in den von Scrivito::BasicObj
abgeleiteten Klassen verfügbar sind, z.B. valid_widget_classes_for
zur Einschränkung der verfügbaren Widgets, oder description_for_editor
zur Festlegung eines Beschreibungstextes von Seiten- und Widgettypen.
Die Klassenhierarchie der Applikation wird bei den Shadow Classes derzeit (1.5.x) nicht abgebildet. Das heißt, es greifen nur die Attribute und Methoden, die man entweder in Obj
oder in der Vorlage selbst definiert hat.
Das folgende Beispiel funktioniert nicht wie beabsichtigt:
class ArticlePage < Obj
in_place do
attribute :headline, :string
end
end
class NewsPage < ArticlePage
in_place do
attribute :summary, :html
end
end
Die Vorlage NewsPage
erhält in diesem Fall lediglich das Attribut summary
(sowie gegebenenfalls auch die Attribute aus Obj
) und nicht headline
.
Sollte Vererbung bei Shadow Classes nicht anders (zum Beispiel mit Mixins) abgebildet werden können, dann kann – als die absolut letzte Lösung – das folgende Muster angewandt werden:
class ArticlePage < Obj
def self.inherited(subclass)
super
subclass.class_eval do
in_place do
attribute :headline, :string
end
end
end
end
class NewsPage < ArticlePage
in_place do
attribute :summary, :html
end
end