Die Regeln brechen: Verwendung von SQLite zur Demo von Web-Apps
Veröffentlicht: 2022-03-10Die meisten potenziellen Benutzer werden die Software oder den Service ausprobieren wollen, bevor sie Zeit und Geld investieren. Einige Produkte funktionieren hervorragend, indem sie den Benutzern einfach eine kostenlose Testversion geben, während andere Apps am besten mit bereits vorhandenen Beispieldaten getestet werden. Oft kommt hier das uralte Demokonto ins Spiel.
Allerdings kann jeder, der schon einmal ein Demokonto implementiert hat, die damit verbundenen Probleme bestätigen. Sie wissen, wie die Dinge im Internet ablaufen: Jeder kann Daten eingeben (ob für das Produkt sinnvoll oder nicht) und es besteht eine gute Chance, dass die von anonymen Benutzern oder Bots hinzugefügten Inhalte für andere anstößig sind. Sicher, Sie können die Datenbank jederzeit zurücksetzen, aber wie oft und wann? Und löst das am Ende wirklich das Problem? Meine Lösung zur Verwendung von SQLite .
Warum nicht SQLite für die Produktionsversion verwenden?
Es ist allgemein bekannt, dass SQLite nicht mehrere Threads verarbeitet, da die gesamte Datenbank während eines Schreibbefehls gesperrt wird, was einer der Gründe ist, warum Sie es nicht in einer normalen Produktionsumgebung verwenden sollten. In meiner Lösung wird jedoch für jeden Benutzer, der die Software demonstriert, eine separate SQLite-Datei verwendet . Das bedeutet, dass die Schreibbeschränkung nur auf diesen einen Benutzer beschränkt ist, aber mehrere gleichzeitige Benutzer (jeder mit seiner eigenen Datenbankdatei) werden diese Beschränkung nicht erfahren. Dies ermöglicht dem Benutzer eine kontrollierte Erfahrung beim Testen der Software und ermöglicht ihm, genau das zu sehen, was Sie sehen möchten.
Dieses Tutorial basiert auf einer realen Lösung, die ich seit 2015 erfolgreich für eine SaaS-Demo-Webanwendung verwende. Das Tutorial ist für Ruby on Rails (mein bevorzugtes Framework) Version 3 und höher geschrieben, aber die grundlegenden Konzepte sollten es sein kann an jede andere Sprache oder jedes Framework angepasst werden. Da Ruby on Rails dem Softwareparadigma „Convention over Configuration“ folgt, kann es sogar einfacher sein, es in anderen Frameworks zu implementieren, insbesondere in reinen Sprachen (wie reinem PHP) oder Frameworks, die nicht viel in Bezug auf die Verwaltung der Datenbankverbindungen tun .
Allerdings eignet sich diese Technik besonders gut für Ruby on Rails. Warum? Weil es zum größten Teil "datenbankunabhängig" ist. Das bedeutet, dass Sie in der Lage sein sollten, Ihren Ruby-Code zu schreiben und ohne Probleme zwischen Datenbanken zu wechseln.
Ein Beispiel einer fertigen Version dieses Prozesses kann von GitHub heruntergeladen werden.
Der erste Schritt: Bereitstellungsumgebung
Zum Deployment kommen wir später, aber Ruby on Rails ist standardmäßig in Entwicklungs-, Test- und Produktionsumgebungen aufgeteilt. Wir werden dieser Liste eine neue Demo-Umgebung für unsere App hinzufügen, die fast identisch mit der Produktionsumgebung sein wird, uns aber erlauben wird, andere Datenbankeinstellungen zu verwenden.
Erstellen Sie in Rails eine neue Umgebung, indem Sie die Datei config/environments/production.rb
duplizieren und demo.rb
umbenennen. Da die Demoumgebung in einer produktionsähnlichen Umgebung verwendet wird, müssen Sie möglicherweise nicht viele Konfigurationsoptionen für diese neue Umgebung ändern, obwohl ich vorschlagen würde, config.assets.compile
von false
auf true
zu ändern, was das lokale Testen ohne erleichtert vorkompilieren müssen.
Wenn Sie Rails 4 oder höher ausführen, müssen Sie auch config/secrets.yml
aktualisieren, um eine secret_key_base
für die Demoumgebung hinzuzufügen. Stellen Sie sicher, dass sich dieser geheime Schlüssel vom Produktionsschlüssel unterscheidet, um sicherzustellen, dass die Sitzungen in jeder Umgebung eindeutig sind, wodurch Ihre App weiter gesichert wird.
Als nächstes müssen Sie die Datenbankkonfiguration in config/database.yml
definieren. Während die Demoumgebung hauptsächlich die duplizierte Datenbank verwendet, die wir im nächsten Abschnitt behandeln werden, müssen wir die Standarddatenbankdatei und die Einstellungen definieren, die für unsere Demo verwendet werden sollen. Fügen Sie Folgendes zu config/database.yml
:
demo: adapter: sqlite3 pool: 5 timeout: 5000 database: db/demo.sqlite3
In Rails möchten Sie möglicherweise auch Ihr Gemfile
überprüfen, um sicherzustellen, dass SQLite3 in der neuen Demoumgebung verfügbar ist. Sie können dies auf verschiedene Arten einstellen, aber es kann so aussehen:
group :development, :test, :demo do gem 'sqlite3' end
Sobald die Datenbank konfiguriert ist, müssen Sie rake db:migrate RAILS_ENV=demo
und dann Daten nach Belieben in die Datenbank eingeben (egal ob aus einer Seed-Datei, manuelle Eingabe neuer Daten oder sogar Duplizieren der Datei development.sqlite3
). An dieser Stelle sollten Sie überprüfen, ob alles funktioniert, indem Sie rails server -e demo
über die Befehlszeile ausführen. Während Sie den Server in der neuen Demoumgebung ausführen, können Sie sicherstellen, dass Ihre Testdaten Ihren Wünschen entsprechen, aber Sie können diesen Inhalt später jederzeit bearbeiten. Beim Hinzufügen Ihrer Inhalte zur Demo-Datenbank würde ich empfehlen, einen sauberen Datensatz zu erstellen, damit die Datei so klein wie möglich ist. Wenn Sie jedoch Daten aus einer anderen Datenbank migrieren müssen, empfehle ich YamlDb, das ein datenbankunabhängiges Format zum Sichern und Wiederherstellen von Daten erstellt.
Wenn Ihre Rails-Anwendung wie erwartet ausgeführt wird, können Sie mit dem nächsten Schritt fortfahren.
Der zweite Schritt: Verwenden der Demo-Datenbank
Der wesentliche Teil dieses Tutorials besteht darin, jeder Sitzung zu erlauben, eine andere SQLite-Datenbankdatei zu verwenden. Normalerweise verbindet sich Ihre Anwendung für jeden Benutzer mit derselben Datenbank, sodass für diese Aufgabe zusätzlicher Code erforderlich ist.
Um Ruby on Rails das Wechseln von Datenbanken zu ermöglichen, müssen wir zunächst die folgenden vier privaten Methoden in application_controller.rb
hinzufügen. Sie müssen auch einen Before-Filter für die Methode set_demo_database
definieren, damit bei jedem Laden der Seite eine Logik aufgerufen wird, die auf die richtige Demo-Datenbank verweist.
# app/controllers/application_controller.rb # use `before_filter` for Rails 3 before_action :set_demo_database, if: -> { Rails.env == 'demo' } private # sets the database for the demo environment def set_demo_database if session[:demo_db] # Use database set by demos_controller db_name = session[:demo_db] else # Use default 'demo' database db_name = default_demo_database end ActiveRecord::Base.establish_connection(demo_connection(db_name)) end # Returns the current database configuration hash def default_connection_config @default_config ||= ActiveRecord::Base.connection.instance_variable_get("@config").dup end # Returns the connection hash but with database name changed # The argument should be a path def demo_connection(db_path) default_connection_config.dup.update(database: db_path) end # Returns the default demo database path defined in config/database.yml def default_demo_database return YAML.load_file("#{Rails.root.to_s}/config/database.yml")['demo']['database'] end
Da jede Serversitzung eine andere Datenbank hat, speichern Sie den Dateinamen der Datenbank in einer Sitzungsvariablen. Wie Sie sehen können, verwenden wir session[:demo_db]
, um die spezifische Datenbank für den Benutzer zu verfolgen. Die Methode set_demo_database
steuert, welche Datenbank verwendet werden soll, indem sie die Verbindung zu der in der Sitzungsvariablen festgelegten Datenbank herstellt. Die Methode default_demo_database
lädt einfach den Pfad der Datenbank, wie er in der Konfigurationsdatei database.yml
definiert ist.
Wenn Sie eine reine Sprache verwenden, können Sie an dieser Stelle wahrscheinlich einfach Ihr Datenbankverbindungsskript so aktualisieren, dass es auf die neue Datenbank verweist, und dann mit dem nächsten Abschnitt fortfahren. In Rails sind einige Schritte mehr erforderlich, da es dem Software-Paradigma „Konvention über Konfiguration“ folgt.
Der dritte Schritt: Duplizieren der SQLite-Datei
Nachdem die App nun für die Verwendung der neuen Datenbank eingerichtet ist, benötigen wir einen Auslöser für die neue Demositzung. Beginnen Sie der Einfachheit halber mit einem einfachen „Start Demo“-Button. Sie könnten es auch zu einem Formular machen, in dem Sie einen Namen und eine E-Mail-Adresse (für eine Nachverfolgung durch das Verkaufsteam usw.) oder eine beliebige Anzahl von Dingen erfassen.
Halten Sie sich an die Rails-Konventionen und erstellen Sie einen neuen 'Demo'-Controller:
rails generate controller demos new
Als Nächstes sollten Sie die Routen so aktualisieren, dass sie auf Ihre neuen Controller-Aktionen zeigen, und sie in eine Bedingung einschließen, um zu verhindern, dass sie in der Produktionsumgebung aufgerufen wird. Sie können die Routen beliebig benennen oder sie mit den Standard-Rails-Konventionen benennen:
if Rails.env == 'demo' get 'demos/new', as: 'new_demo' post 'demos' => 'demos#create', as: 'demos' end
Als nächstes fügen wir ein sehr einfaches Formular zu views/demos/new.html.erb
. Möglicherweise möchten Sie zusätzliche Formularfelder zum Erfassen hinzufügen:
<h1>Start a Demo</h1> <%= form_tag demos_path, method: :post do %> <%= submit_tag 'Start Demo' %> <% end %>
Die Magie geschieht in der create
. Wenn der Benutzer sich an diese Route sendet, kopiert die Aktion die demo.sqlite3
-Datei mit einem neuen eindeutigen Dateinamen, legt Sitzungsvariablen fest, meldet den Benutzer an (falls zutreffend) und leitet den Benutzer dann auf die entsprechende Seite um (wir nennen dies die 'Armaturenbrett').
class DemosController < ApplicationController def new # Optional: setting session[:demo_db] to nil will reset the demo session[:demo_db] = nil end def create # make db/demos dir if doesn't exist unless File.directory?('db/demos/') FileUtils.mkdir('db/demos/') end # copy master 'demo' database master_db = default_demo_database demo_db = "db/demos/demo-#{Time.now.to_i}.sqlite3" FileUtils::cp master_db, demo_db # set session for new db session[:demo_db] = demo_db # Optional: login code (if applicable) # add your own login code or method here login(User.first) # Redirect to wherever you want to send the user next redirect_to dashboard_path end end
Jetzt sollten Sie in der Lage sein, den Democode lokal auszuprobieren, indem Sie den Server erneut mit running rails server -e demo
starten.
Wenn Sie den Server bereits ausgeführt haben, müssen Sie ihn für alle Änderungen, die Sie vornehmen, neu starten, da er so konfiguriert ist, dass der Code wie der Produktionsserver zwischengespeichert wird.
Sobald der gesamte Code wie erwartet funktioniert, übergeben Sie Ihre Änderungen an Ihre Versionskontrolle und stellen Sie sicher, dass Sie die demo.sqlite3
-Datei übergeben, aber nicht die Dateien im Verzeichnis db/demos
. Wenn Sie Git verwenden, können Sie einfach Folgendes zu Ihrer .gitignore
-Datei hinzufügen:
Wenn Sie zusätzliche Informationen vom Demo-Benutzer sammeln möchten (z. B. Name und/oder E-Mail-Adresse), möchten Sie diese Informationen wahrscheinlich über eine API an Ihre Hauptanwendung oder eine andere Vertriebspipeline senden, da Ihre Demo-Datenbank nicht zuverlässig ist (Es wird bei jeder erneuten Bereitstellung zurückgesetzt).
!/db/demo.sqlite3 db/demos/*
Letzter Schritt: Bereitstellen Ihres Demo-Servers
Jetzt, da Ihr Demo-Setup lokal funktioniert, möchten Sie es natürlich bereitstellen, damit jeder es verwenden kann. Obwohl jede App anders ist, würde ich empfehlen, dass die Demo-App auf einem separaten Server und daher als Ihre Produktions-App (z. B. demo.myapp.com) Domäne ist. Dadurch wird sichergestellt, dass die beiden Umgebungen isoliert bleiben. Da die SQLite-Datei außerdem auf dem Server gespeichert ist, funktionieren Dienste wie Heroku nicht, da sie keinen Zugriff auf das Dateisystem bieten. Sie können jedoch weiterhin praktisch jeden VPS-Anbieter (z. B. AWS EC2, Microsoft Azure usw.) verwenden. Wenn Sie den automatisierten Komfort mögen, gibt es andere Plattformen als Service-Optionen, die es Ihnen ermöglichen, mit VPS zu arbeiten.
Unabhängig von Ihrem Bereitstellungsprozess müssen Sie möglicherweise auch überprüfen, ob die App über die entsprechenden Lese-/Schreibberechtigungen für Ihr Verzeichnis verfügt, in dem Sie die Demo-SQLite-Dateien speichern. Dies könnte manuell oder mit einem Bereitstellungshaken gehandhabt werden.
SQLite funktioniert bei mir nicht. Was ist mit anderen Datenbanksystemen?
Keine zwei Apps sind gleich und ihre Datenbankanforderungen auch nicht. Durch die Verwendung von SQLite haben Sie den Vorteil, dass Sie die Datenbank schnell duplizieren können, sowie die Datei in der Versionskontrolle speichern können. Obwohl ich glaube, dass SQLite in den meisten Situationen funktioniert (insbesondere mit Rails), gibt es Situationen, in denen SQLite möglicherweise nicht für die Anforderungen Ihrer Anwendung geeignet ist. Glücklicherweise ist es immer noch möglich, die oben genannten Konzepte mit anderen Datenbanksystemen zu verwenden. Der Prozess des Duplizierens einer Datenbank wird für jedes System etwas anders sein, aber ich werde eine Lösung für MySQL skizzieren, und ein ähnlicher Prozess existiert mit PostgreSQL und anderen.
Die meisten der oben beschriebenen Methoden funktionieren ohne zusätzliche Änderungen. Anstatt jedoch eine SQLite-Datei in Ihrer Versionskontrolle zu speichern, sollten Sie mysqldump
(oder pg_dump
für PostgreSQL) verwenden, um eine SQL-Datei der Datenbank zu exportieren, die den Inhalt enthält, den Sie für Ihre Demo-Erfahrung verwenden möchten. Diese Datei sollte auch in Ihrer Versionskontrolle hinterlegt sein.
Die einzigen Änderungen am vorherigen Code sind in der Aktion demos#create
zu finden. Anstatt die SQLite3-Datei zu kopieren, erstellt die Controller-Aktion eine neue Datenbank, lädt die SQL-Datei in diese Datenbank und erteilt dem Datenbankbenutzer bei Bedarf Berechtigungen. Der dritte Schritt zum Gewähren des Zugriffs ist nur erforderlich, wenn Ihr Datenbankadministrator sich von dem Benutzer unterscheidet, mit dem die App eine Verbindung herstellt. Der folgende Code verwendet standardmäßige MySQL-Befehle, um diese Schritte auszuführen:
def create # database names template_demo_db = default_demo_database new_demo_db = "demo_database_#{Time.now.to_i}" # Create database using admin credentials # In this example the database is on the same server so passing a host argument is not require `mysqladmin -u#{ ENV['DB_ADMIN'] } -p#{ ENV['DB_ADMIN_PASSWORD'] } create #{new_demo_db}` # Load template sql into new database # Update the path if it differs from where you saved the demo_template.sql file `mysql -u#{ ENV['DB_ADMIN'] } -p#{ ENV['DB_ADMIN_PASSWORD'] } #{new_demo_db} < db/demo_template.sql` # Grant access to App user (if applicable) `mysql -u#{ ENV['DB_ADMIN'] } -p#{ ENV['DB_ADMIN_PASSWORD'] } -e "GRANT ALL on #{new_demo_db}.* TO '#{ ENV['DB_USERNAME'] }'@'%';"` # set session for new db session[:demo_db] = new_demo_db # Optional: login code (if applicable) # add your own login code or method here login(User.first) redirect_to dashboard_path end
Ruby erlaubt Ihnen, wie viele andere Sprachen einschließlich PHP, Backticks zu verwenden, um einen Shell-Befehl (dh `ls -a`
) aus Ihrem Code heraus auszuführen. Sie müssen dies jedoch mit Vorsicht verwenden und sicherstellen, dass keine benutzerseitigen Parameter oder Variablen in den Befehl eingefügt werden können, um Ihren Server vor böswillig injiziertem Code zu schützen. In diesem Beispiel interagieren wir explizit mit den MySQL-Befehlszeilentools, was die einzige Möglichkeit ist, eine neue Datenbank zu erstellen. Auf die gleiche Weise erstellt das Ruby on Rails-Framework eine neue Datenbank. Stellen Sie sicher, dass ENV['DB_ADMIN']
und ENV['DB_ADMIN_PASSWORD']
entweder durch Ihre eigene Umgebungsvariable oder eine andere Möglichkeit zum Festlegen des Datenbankbenutzernamens ersetzen. Sie müssen dasselbe für ENV['DB_USERNAME']
wenn Ihr Admin-Benutzer sich von dem Benutzer für Ihre App unterscheidet.
Das ist alles, was Sie brauchen, um zu MySQL zu wechseln! Der offensichtlichste Vorteil dieser Lösung besteht darin, dass Sie sich keine Gedanken über potenzielle Probleme machen müssen, die sich aus der unterschiedlichen Syntax zwischen Datenbanksystemen ergeben könnten.
Letztendlich wird eine endgültige Entscheidung auf der Grundlage der erwarteten Qualität und des erwarteten Service getroffen, und nicht auf Komfort und Geschwindigkeit, und sie wird nicht unbedingt nur vom Preis beeinflusst.
Abschließende Gedanken
Dies ist nur ein Ausgangspunkt dafür, was Sie mit Ihrem neuen Demo-Server machen können. Beispielsweise könnte Ihre Marketing-Website einen Link zu „Funktion XYZ ausprobieren“ enthalten. Wenn Sie keinen Namen oder keine E-Mail-Adresse benötigen, können Sie die demos#create
-Methode mit einem Link wie /demos/?feature=xyz
verknüpfen, und die Aktion würde einfach auf die gewünschte Funktion und/oder Seite umleiten, anstatt auf das Dashboard das obige Beispiel.
Wenn Sie SQLite für die Entwicklungs- und Demoumgebungen verwenden, würde die ständige Versionskontrolle dieser Beispieldatenbank allen Ihren Entwicklern Zugriff auf eine saubere Datenbank zur Verwendung in lokalen Entwicklungs-, Testumgebungen oder Qualitätssicherungstests geben. Die Möglichkeiten sind endlos.
Sie können eine fertige Demo von GitHub herunterladen.