Łamanie zasad: używanie SQLite do demonstracyjnych aplikacji internetowych
Opublikowany: 2022-03-10Większość potencjalnych użytkowników będzie chciała wypróbować oprogramowanie lub usługę przed poświęceniem czasu i pieniędzy. Niektóre produkty działają świetnie, po prostu udostępniając użytkownikom bezpłatną wersję próbną, podczas gdy inne aplikacje najlepiej sprawdzają się, gdy przykładowe dane są już na miejscu. Często jest to miejsce, w którym w grę wchodzi stare konto demo.
Jednak każdy, kto kiedykolwiek wdrożył konto demo, może potwierdzić związane z tym problemy. Wiesz, jak to się dzieje w Internecie: każdy może wprowadzić dane (bez względu na to, czy ma to sens, czy nie) i jest duża szansa, że treści dodawane przez anonimowych użytkowników lub boty mogą być obraźliwe dla innych. Jasne, zawsze możesz zresetować bazę danych, ale jak często i kiedy? I ostatecznie, czy to naprawdę rozwiązuje problem? Moje rozwiązanie do korzystania z SQLite .
Dlaczego nie używać SQLite do wersji produkcyjnej?
Powszechnie wiadomo, że SQLite nie obsługuje wielu wątków, ponieważ cała baza danych jest blokowana podczas polecenia zapisu, co jest jednym z powodów, dla których nie należy go używać w normalnym środowisku produkcyjnym. Jednak w moim rozwiązaniu dla każdego użytkownika demonstrującego oprogramowanie używany jest osobny plik SQLite. Oznacza to, że ograniczenie zapisu jest ograniczone tylko do tego jednego użytkownika, ale wielu jednoczesnych użytkowników (każdy z własnym plikiem bazy danych) nie doświadczy tego ograniczenia. Pozwala to na kontrolowane wrażenia użytkownika podczas testowania oprogramowania i pozwala im zobaczyć dokładnie to, co chcesz , aby zobaczyli.
Ten samouczek jest oparty na rzeczywistym rozwiązaniu, które z powodzeniem uruchamiam dla aplikacji internetowej demonstracyjnej SaaS od 2015 roku. Samouczek jest napisany dla Ruby on Rails (mój wybrany framework) w wersji 3 i nowszych, ale podstawowe koncepcje powinny być możliwość dostosowania do dowolnego innego języka lub struktury. W rzeczywistości, ponieważ Ruby on Rails przestrzega paradygmatu oprogramowania „konwencja ponad konfiguracją”, może być nawet łatwiej zaimplementować w innych frameworkach, zwłaszcza w gołych językach (takich jak proste PHP) lub frameworkach, które nie robią wiele w zakresie zarządzania połączeniami z bazami danych .
Biorąc to pod uwagę, ta technika jest szczególnie odpowiednia dla Ruby on Rails. Czemu? Ponieważ w większości jest to „niezależny od bazy danych”. Oznacza to, że powinieneś być w stanie napisać swój kod Ruby i przełączać się między bazami danych bez żadnych problemów.
Próbkę gotowej wersji tego procesu można pobrać z serwisu GitHub.
Pierwszy krok: środowisko wdrażania
Wdrożenie zajmiemy się później, ale Ruby on Rails jest domyślnie podzielony na środowiska programistyczne, testowe i produkcyjne. Zamierzamy dodać do tej listy nowe środowisko demonstracyjne naszej aplikacji, które będzie prawie identyczne ze środowiskiem produkcyjnym, ale pozwoli nam korzystać z innych ustawień bazy danych.
W Railsach utwórz nowe środowisko, duplikując plik config/environments/production.rb
i zmieniając jego nazwę na demo.rb
. Ponieważ środowisko demonstracyjne będzie używane w środowisku produkcyjnym, być może nie będziesz musiał zmieniać wielu opcji konfiguracyjnych dla tego nowego środowiska, chociaż sugerowałbym zmianę config.assets.compile
z false
na true
, co ułatwi testowanie lokalne bez konieczność prekompilacji.
Jeśli używasz Railsów 4 lub nowszych, będziesz musiał również zaktualizować config/secrets.yml
, aby dodać secret_key_base
dla środowiska demo. Upewnij się, że ten tajny klucz jest inny niż produkcyjny, aby upewnić się, że sesje są unikatowe w każdym środowisku, co dodatkowo zabezpiecza Twoją aplikację.
Następnie musisz zdefiniować konfigurację bazy danych w config/database.yml
. Chociaż środowisko demonstracyjne będzie głównie korzystało ze zduplikowanej bazy danych, którą omówimy w następnej sekcji, musimy zdefiniować domyślny plik bazy danych i ustawienia, które będą używane w naszym demo. Dodaj następujące elementy do config/database.yml
:
demo: adapter: sqlite3 pool: 5 timeout: 5000 database: db/demo.sqlite3
W Rails możesz również sprawdzić swój Gemfile
, aby upewnić się, że SQLite3 jest dostępny w nowym środowisku demonstracyjnym. Możesz to ustawić na wiele sposobów, ale może to wyglądać tak:
group :development, :test, :demo do gem 'sqlite3' end
Po skonfigurowaniu bazy danych musisz rake db:migrate RAILS_ENV=demo
, a następnie umieścić dane w bazie danych w dowolny sposób (czy to z pliku seed, ręcznie wprowadzić nowe dane lub nawet zduplikować plik development.sqlite3
). W tym momencie powinieneś sprawdzić, czy wszystko działa, uruchamiając rails server -e demo
z wiersza poleceń. Podczas uruchamiania serwera w nowym środowisku demonstracyjnym możesz upewnić się, że dane testowe są takie, jak chcesz, ale zawsze możesz wrócić i edytować te treści później. Przy dodawaniu treści do bazy demo sugerowałbym utworzenie czystego zestawu danych, tak aby plik był jak najmniejszy. Jeśli jednak musisz przenieść dane z innej bazy danych, polecam YamlDb, który tworzy niezależny od bazy danych format do zrzucania i przywracania danych.
Jeśli Twoja aplikacja Railsowa działa zgodnie z oczekiwaniami, możesz przejść do następnego kroku.
Drugi krok: korzystanie z demonstracyjnej bazy danych
Zasadniczą częścią tego samouczka jest umożliwienie każdej sesji korzystania z innego pliku bazy danych SQLite. Zwykle Twoja aplikacja połączy się z tą samą bazą danych dla każdego użytkownika, więc do tego zadania potrzebny będzie dodatkowy kod.
Aby zacząć zezwalanie Ruby on Rails na przełączanie baz danych, najpierw musimy dodać następujące cztery prywatne metody do application_controller.rb
. Będziesz także musiał zdefiniować filtr przed dla metody set_demo_database
, aby logika odwołująca się do prawidłowej bazy danych demonstracyjnych była wywoływana przy każdym ładowaniu strony.
# 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
Ponieważ każda sesja serwera będzie miała inną bazę danych, nazwę pliku bazy danych będziesz przechowywać w zmiennej sesji. Jak widać, używamy session[:demo_db]
do śledzenia konkretnej bazy danych dla użytkownika. Metoda set_demo_database
kontroluje, która baza danych ma być używana przez nawiązanie połączenia z bazą danych ustawioną w zmiennej sesji. Metoda default_demo_database
po prostu ładuje ścieżkę bazy danych określoną w pliku konfiguracyjnym database.yml
.
Jeśli używasz samego języka, w tym momencie prawdopodobnie możesz po prostu zaktualizować skrypt połączenia z bazą danych, aby wskazywał nową bazę danych, a następnie przejść do następnej sekcji. W Railsach potrzeba jeszcze kilku kroków, ponieważ jest to zgodne z paradygmatem oprogramowania „konwencja nad konfiguracją”.
Trzeci krok: powielanie pliku SQLite
Teraz, gdy aplikacja jest skonfigurowana do korzystania z nowej bazy danych, potrzebujemy wyzwalacza dla nowej sesji demonstracyjnej. Dla uproszczenia zacznij od użycia podstawowego przycisku „Rozpocznij demo”. Możesz również zrobić z niego formularz, w którym zbierasz imię i nazwisko oraz adres e-mail (w celu kontynuacji ze strony zespołu sprzedaży itp.) lub dowolną liczbę rzeczy.
Trzymając się konwencji Rails, utwórz nowy kontroler „Demo”:
rails generate controller demos new
Następnie należy zaktualizować trasy, aby wskazywały na nowe akcje kontrolera, owijając je warunkowo, aby zapobiec ich wywoływaniu w środowisku produkcyjnym. Możesz nazwać trasy jak chcesz lub używając standardowych konwencji Rails:
if Rails.env == 'demo' get 'demos/new', as: 'new_demo' post 'demos' => 'demos#create', as: 'demos' end
Następnie dodajmy bardzo podstawowy formularz do views/demos/new.html.erb
. Możesz dodać dodatkowe pola formularza do przechwycenia:
<h1>Start a Demo</h1> <%= form_tag demos_path, method: :post do %> <%= submit_tag 'Start Demo' %> <% end %>
Magia dzieje się w akcji create
. Gdy użytkownik poda się do tej trasy, akcja skopiuje plik demo.sqlite3
z nową unikalną nazwą, ustawi zmienne sesji, zaloguje użytkownika (jeśli dotyczy), a następnie przekieruje użytkownika na odpowiednią stronę (nazwiemy to 'deska rozdzielcza').
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
Teraz powinieneś być w stanie wypróbować kod demo lokalnie, ponownie uruchamiając serwer za pomocą uruchomionego rails server -e demo
.
Jeśli serwer był już uruchomiony, musisz go ponownie uruchomić w celu wprowadzenia zmian, ponieważ jest skonfigurowany do buforowania kodu, podobnie jak serwer produkcyjny.
Gdy cały kod będzie działał zgodnie z oczekiwaniami, zatwierdź zmiany w kontroli wersji i upewnij się, że zatwierdzasz plik demo.sqlite3
, ale nie pliki w katalogu db/demos
. Jeśli używasz git, możesz po prostu dodać następujące elementy do pliku .gitignore
:
Jeśli chcesz zebrać dodatkowe informacje od użytkownika demonstracyjnego (takie jak imię i nazwisko lub adres e-mail), prawdopodobnie będziesz chciał wysłać te informacje za pośrednictwem interfejsu API do swojej głównej aplikacji lub innego potoku sprzedaży, ponieważ baza danych demonstracyjnych nie będzie wiarygodna (resetuje się za każdym razem, gdy ponownie wdrażasz).
!/db/demo.sqlite3 db/demos/*
Ostatni krok: wdrożenie serwera demonstracyjnego
Teraz, gdy masz konfigurację demonstracyjną działającą lokalnie, oczywiście będziesz chciał ją wdrożyć, aby każdy mógł z niej korzystać. Chociaż każda aplikacja jest inna, zalecam, aby aplikacja demonstracyjna znajdowała się na osobnym serwerze, a zatem w domenie jako aplikacja produkcyjna (np. demo.myapp.com). Zapewni to izolację tych dwóch środowisk. Dodatkowo, ponieważ plik SQLite jest przechowywany na serwerze, usługi takie jak Heroku nie będą działać, ponieważ nie zapewniają dostępu do systemu plików. Jednak nadal możesz korzystać z praktycznie dowolnego dostawcy VPS (takiego jak AWS EC2, Microsoft Azure itp.). Jeśli podoba Ci się zautomatyzowana wygoda, istnieją inne opcje Platform as Service, które umożliwiają pracę z VPS.
Niezależnie od procesu wdrażania może być również konieczne sprawdzenie, czy aplikacja ma odpowiednie uprawnienia do odczytu/zapisu w katalogu, w którym przechowujesz demonstracyjne pliki SQLite. Może to być obsługiwane ręcznie lub za pomocą haka wdrażania.
SQLite nie będzie dla mnie działać. A co z innymi systemami baz danych?
Żadne dwie aplikacje nie są tworzone tak samo, podobnie jak ich wymagania dotyczące bazy danych. Korzystając z SQLite, masz tę zaletę, że możesz szybko zduplikować bazę danych, a także możesz przechowywać plik w kontroli wersji. Chociaż wierzę, że SQLite zadziała w większości sytuacji (szczególnie z Railsami), są sytuacje, w których SQLite może nie być odpowiedni dla potrzeb Twojej aplikacji. Na szczęście nadal można używać tych samych koncepcji w innych systemach baz danych. Proces duplikowania bazy danych będzie nieco inny dla każdego systemu, ale przedstawię rozwiązanie dla MySQL i podobny proces istnieje w PostgreSQL i innych.
Większość opisanych powyżej metod działa bez żadnych dodatkowych modyfikacji. Jednak zamiast przechowywać plik SQLite w kontroli wersji, powinieneś użyć mysqldump
(lub pg_dump
dla PostgreSQL), aby wyeksportować plik SQL z dowolnej bazy danych, która zawiera zawartość, której chcesz użyć podczas demonstracji. Ten plik powinien być również przechowywany w Twojej kontroli wersji.
Jedyne zmiany w poprzednim kodzie zostaną znalezione w akcji demos#create
. Zamiast kopiować plik SQLite3, akcja kontrolera utworzy nową bazę danych, załaduje plik sql do tej bazy danych i w razie potrzeby przyzna uprawnienia użytkownikowi bazy danych. Trzeci krok przyznawania dostępu jest konieczny tylko wtedy, gdy administrator bazy danych jest inny niż użytkownik, którego aplikacja używa do połączenia. Poniższy kod wykorzystuje standardowe polecenia MySQL do obsługi tych kroków:
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, podobnie jak wiele innych języków, w tym PHP, pozwala na użycie backticków do wykonania polecenia powłoki (np. `ls -a`
) z poziomu kodu. Należy jednak używać tego ostrożnie i upewnić się, że do polecenia nie można wstawić żadnych parametrów ani zmiennych skierowanych do użytkownika, aby chronić serwer przed złośliwie wstrzykniętym kodem. W tym przykładzie bezpośrednio wchodzimy w interakcję z narzędziami wiersza poleceń MySQL, co jest jedynym sposobem na utworzenie nowej bazy danych. W ten sam sposób framework Ruby on Rails tworzy nową bazę danych. Pamiętaj, aby zastąpić ENV['DB_ADMIN']
i ENV['DB_ADMIN_PASSWORD']
własną zmienną środowiskową lub w inny sposób ustawić nazwę użytkownika bazy danych. Musisz zrobić to samo dla ENV['DB_USERNAME']
, jeśli Twój administrator jest inny niż użytkownik Twojej aplikacji.
To wszystko, czego potrzeba, aby przejść na MySQL! Najbardziej oczywistą zaletą tego rozwiązania jest to, że nie musisz się martwić o potencjalne problemy, które mogą wynikać z różnej składni między systemami baz danych.
Ostatecznie ostateczna decyzja jest podejmowana na podstawie oczekiwanej jakości i obsługi, a nie wygody i szybkości, i niekoniecznie zależy od samej ceny.
Końcowe przemyślenia
To tylko punkt wyjścia do tego, co możesz zrobić z nowym serwerem demonstracyjnym. Na przykład witryna marketingowa może zawierać link „Wypróbuj funkcję XYZ”. Jeśli nie potrzebujesz nazwiska ani adresu e-mail, możesz połączyć metodę demos#create
z linkiem, takim jak /demos/?feature=xyz
, a akcja po prostu przekieruje do żądanej funkcji i/lub strony, a nie do pulpitu nawigacyjnego w w powyższym przykładzie.
Ponadto, jeśli używasz SQLite w środowiskach programistycznych i demonstracyjnych, zawsze posiadanie tej przykładowej bazy danych w kontroli wersji dałoby wszystkim programistom dostęp do czystej bazy danych do użytku w lokalnych środowiskach programistycznych, testowych lub testowaniu jakości. Możliwości są nieskończone.
Możesz pobrać ukończone demo z GitHub.