ArcadeDB

Bridgetown-basierende Internetauftritte können auf Inhalte der NoSQL-Datenbank ArcadeDB zugreifen.

nothing

Setup für eine Ruby-Anwendung

Gemfile


Skript

 require 'arcade'
 require 'arcarde-time-graph'

 Arcade::Init.connect 

 DB =  Arcade::Init.db 

 # test
 DB.hierarchy

ArcadeDB ist eine universale NoSQL-Datenbank. »NoSQL« steht für »Not Only SQL«. Die Datenbank ist eine Alternative zu klassischen rationalen Datenbanken.

Die Daten sind entweder als Graphen angelegt, werden über Schlüssel abgespeichert (Key/Value) oder als lose strukturierte Dokumente. Die Datenbank verwendet Standardprotokolle für die Datenzugriffe.

Über das Plugin können mit Bridgetown verwaltete Webinhalte auf Datenbankinhalte zugreifen. Im statischen Modus liest das Framework die Daten bei der Erstellung der Webseiten aus der Datenbank. Die Internetseite selbst ist weiterhin statisch. Wenn sich der Datenbankinhalt ändert, muss die Webseite neu erstellt werden.

Im SSR-Modus wird die Datenbank bei jedem Aufruf der Webseite erneut abgefragt und die Webseite dynamisch erstellt.

Das Plugin verwendet das ArcadeDB-Gem für den Datenbankzugriff.

Initialisierung

Die Integration gelingt mit wenigen Befehlen

  • Im Gemfile werden die Bibliotheken arcadedb und (optional) arcade-time-graph eingebunden, zusätzlich das Plugin
    gem 'arcadedb'
    gem 'arcade-time-graph'
    gem 'bridgetown-arcade-db'
    
  • In der config/initialisers.rb wird mindestens das arcade-db-Plugin aktiviert. Für die Wiedergabe dynamischer Inhalte wird zusätzlich ssr und bridgetown-routes benötigt.
init :ssr
init :"bridgetown-routes"
init :"bridgetown-arcade-db"

Der Initializer

Beim Start liest Bridgetown die Datei config/initializers ein und führt die dort verzeichneten Befehle aus.

Das Ruby-Symbol :"bridgetown-arcade-db" zieht den Aufruf von Bridgetown.initializer mit dem Argument :bridgtown-arcade-db nach sich. Das Plugin ist im Kern das Ergebnis der Ausführung dieser Methode.

Bridgetown.initializer :"bridgetown-arcade-db" do |config|
    BridgetownArcadeDb.load_models config
    Arcade.const_set :ProjectRoot, Pathname.new( config.root_dir  )
    Arcade::Init.connect Bridgetown.environment
end
  • Zuerst werden über load_models Datenbank-Model-Dateien eingebunden. Diese werden üblicherwiese unterhalb des Verzeichnisses /model angelegt.
  • Dem Arcade-Gem muss danach mitgeteilt werden, wo es diese Dateien finden kann. Dazu wird das ProjektRoot gesetzt.
  • Abschließend ruft der Initializer die connect-Methode auf. Welche Datenbank geöffnet werden soll, wird aus config/arcade.yml eingelesen.
--- #/config/arcade.yml
:environment:
  :test:
    dbname: test
    user:  root
     pass: ****
   :development:
     dbname: playground
     user: root
     pass: ****      
   :production:
     dbname: bridgetown
     user: root
     pass: ****      
 :admin:
   :host: localhost
   :port: 2480
   :user: root
   :pass: ****
 :modeldir: model
 :logger: stdout           # 'file' or 'stdout'
 :namespace: Arcade

Für die unterschiedlichen Umgebungen können unterschiedliche Datenbanken angegeben werden, die von unterschiedlichen Nutzern mit angepassten Zugriffsrechten genutzt werden. Die Angabe des Namespaces ist für die Modelfiles relevant.

Modelfiles

Die Datenbank ist hoch flexibel und kann weitgehend mit adhoc-Daten gefüllt werden. Trotzdem müssen die Datanbanktabellen selbst als Modelfile definiert werden.

Hier ein Beispiel für die Definition einer Person

 module Arcade
  class Person
    attribute :name,        Types::Nominal::String
    attribute :surname,     Types::Nominal::String.default( "".freeze  )
    attribute :email?,      Types::Email
    attribute :age?,        Types::Nominal::Integer
    attribute :active,      Types::Nominal::Bool.default( true  )
    attribute :conterfeil?, Types::Nominal::Any

    def self.db_init
       File.read(__FILE__).gsub(/.*__END__/m, '')
    end
  end
 end
 ## The code below is executed on the database after the database-type is created
 ## Use the output of `ModelClass.database_name` as DB type  name
 ##
 __END__
 CREATE PROPERTY user.name STRING
 CREATE PROPERTY user.surname STRING
 CREATE PROPERTY user.email STRING
 CREATE INDEX  ON user ( name  ) NOTUNIQUE
 CREATE INDEX  ON user ( name, surname, email  ) UNIQUE

Die Definitionen sind weitgehend selbsterklärend. Attribute mit einem Fragezeichen sind optional. Die Daten sind streng typisiert, das ist Voraussetzung für einen konsistenten Datenbankaufbau.

Adhoc Datenbank

Zusätzlich zu den definierten Datenbankfeldern können weitere, untypisierte Felder angelegt werden.

So können dynamisch unidirektionale Abhängigkeiten adhoc dargestellt werden:

Person.create name: 'Hugo', surname: 'Gans'
            father: Person.create( name: 'Otto', surname: 'Gans' ),                        
          children: [ "Eva", "Ulli", "Uwe", "Georg" ].map{ |c| Person.create( name: c, surname: 'Gans'  )  }  
                                     

Diese Anweisung legt father und children-Felder an und füllt sie mit Personen. Die Ausgabe des Datensatzes zeigt die angelegten Personen in Form ihrer Datenbank-Identitäten.

puts hugo.to_human
<person[#187:0]: {->}{->}}, active: true, 
                children: ["#175:0", "#178:0", "#181:0", "#184:0"], 
                  father: <person[#172:0]: active : true, name : Otto, surname : Gans>, 
                    name: Hugo, surname: Gans> 

puts hugo.children.map &:expand
<person[#175:0]: active : true, name : Eva, surname : Gans> 
<person[#178:0]: active : true, name : Ulli, surname : Gans>
<person[#181:0]: active : true, name : Uwe, surname : Gans>
<person[#184:0]: active : true, name : Georg, surname : Gans>

#