كسر القواعد: استخدام SQLite لعرض تطبيقات الويب

نشرت: 2022-03-10
ملخص سريع ↬ إذن ، لقد أنشأت تطبيق الويب القاتل التالي ، ولكنك الآن تقدم لك السؤال الذي يجب على كل منتج جديد مراعاته ، "كيف أظهر للجميع مدى روعة تطبيقي؟"

سيرغب معظم المستخدمين المحتملين في تجربة البرنامج أو الخدمة قبل الالتزام بأي وقت ومال. تعمل بعض المنتجات بشكل رائع بمجرد منح المستخدمين إصدارًا تجريبيًا مجانيًا ، بينما تتمتع التطبيقات الأخرى بأفضل تجربة باستخدام عينات البيانات الموجودة بالفعل. غالبًا ما يكون هذا هو المكان الذي يلعب فيه الحساب التجريبي القديم.

ومع ذلك ، يمكن لأي شخص قام بتطبيق حساب تجريبي أن يشهد على المشكلات المرتبطة به. أنت تعرف كيف تعمل الأشياء على الإنترنت: يمكن لأي شخص إدخال البيانات (سواء كان ذلك منطقيًا أم لا للمنتج) وهناك فرصة جيدة أن المحتوى الذي يضيفه المستخدمون المجهولون أو برامج الروبوت يمكن أن يكون مسيئًا للآخرين. بالتأكيد ، يمكنك دائمًا إعادة تعيين قاعدة البيانات ، ولكن كم مرة ومتى؟ وفي النهاية ، هل هذا حقاً يحل المشكلة؟ الحل الخاص بي لاستخدام سكليتي .

لماذا لا تستخدم SQLite لإصدار الإنتاج؟

من المعروف أن SQLite لا تتعامل مع سلاسل رسائل متعددة نظرًا لأن قاعدة البيانات بأكملها مقفلة أثناء أمر الكتابة ، وهو أحد الأسباب التي تجعلك لا تستخدمها في بيئة إنتاج عادية. ومع ذلك ، في الحل الخاص بي ، يتم استخدام ملف SQLite منفصل لكل مستخدم يقوم بعرض البرنامج. هذا يعني أن قيود الكتابة تقتصر فقط على مستخدم واحد ، لكن العديد من المستخدمين المتزامنين (لكل منهم ملف قاعدة البيانات الخاص بهم) لن يواجهوا هذا القيد. يتيح ذلك تجربة مسيطر عليها لاختبار المستخدم لقيادة البرنامج ويمكنه من عرض ما تريده أن يراه بالضبط.

المزيد بعد القفز! أكمل القراءة أدناه ↓

يعتمد هذا البرنامج التعليمي على حل واقعي قمت بتشغيله بنجاح لتطبيق ويب تجريبي SaaS منذ عام 2015. البرنامج التعليمي مكتوب لـ Ruby on Rails (إطار العمل المفضل لدي) الإصدار 3 وما بعده ، ولكن يجب أن تكون المفاهيم الأساسية كذلك يمكن أن تتكيف مع أي لغة أو إطار عمل آخر. في الواقع ، نظرًا لأن Ruby on Rails يتبع نموذج البرنامج "الاصطلاح على التكوين" ، فقد يكون من الأسهل تنفيذه في أطر أخرى ، خاصة اللغات المجردة (مثل PHP المستقيمة) أو الأطر التي لا تفعل الكثير فيما يتعلق بإدارة اتصالات قاعدة البيانات .

ومع ذلك ، فإن هذه التقنية مناسبة بشكل خاص لـ Ruby on Rails. لماذا ا؟ لأنه ، في معظم الأحيان ، "حيادي قاعدة البيانات". بمعنى أنه يجب أن تكون قادرًا على كتابة كود روبي الخاص بك والتبديل بين قواعد البيانات دون أي مشاكل.

يمكن تنزيل عينة من الإصدار النهائي من هذه العملية من GitHub.

الخطوة الأولى: بيئة النشر

سنبدأ النشر لاحقًا ، ولكن يتم تقسيم Ruby on Rails افتراضيًا إلى بيئات تطوير واختبار وإنتاج. سنضيف إلى هذه القائمة بيئة تجريبية جديدة لتطبيقنا ستكون متطابقة تقريبًا مع بيئة الإنتاج ولكنها ستسمح لنا باستخدام إعدادات قاعدة بيانات مختلفة.

في ريلز ، أنشئ بيئة جديدة عن طريق نسخ ملف config/environments/production.rb وإعادة تسميته demo.rb نظرًا لأنه سيتم استخدام بيئة العرض التوضيحي في إعداد مثل الإنتاج ، فقد لا تحتاج إلى تغيير العديد من خيارات التكوين لهذه البيئة الجديدة ، على الرغم من أنني أقترح تغيير config.assets.compile من false إلى true مما يسهل الاختبار محليًا بدون الاضطرار إلى التجميع المسبق.

إذا كنت تقوم بتشغيل ريلز 4 أو أعلى ، فستحتاج أيضًا إلى تحديث config/secrets.yml secrets.yml لإضافة secret_key_base للبيئة التجريبية. تأكد من جعل هذا المفتاح السري مختلفًا عن الإنتاج لضمان أن تكون الجلسات فريدة بين كل بيئة ، مما يزيد من تأمين تطبيقك.

بعد ذلك ، تحتاج إلى تحديد تكوين قاعدة البيانات في config/database.yml . بينما ستستخدم البيئة التجريبية أساسًا قاعدة البيانات المكررة التي سنغطيها في القسم التالي ، يجب علينا تحديد ملف قاعدة البيانات الافتراضية والإعدادات لاستخدامها في العرض التوضيحي الخاص بنا. أضف ما يلي إلى config/database.yml :

 demo: adapter: sqlite3 pool: 5 timeout: 5000 database: db/demo.sqlite3

في ريلز ، قد ترغب أيضًا في التحقق من Gemfile الخاص بك للتأكد من توفر SQLite3 في بيئة العرض الجديدة. يمكنك تعيين هذا بأي عدد من الطرق ، ولكن قد يبدو كالتالي:

 group :development, :test, :demo do gem 'sqlite3' end

بمجرد تكوين قاعدة البيانات ، ستحتاج إلى rake db:migrate RAILS_ENV=demo ثم إرسال البيانات إلى قاعدة البيانات كما تشاء (سواء كان ذلك من ملف أولي أو إدخال بيانات جديدة يدويًا أو حتى تكرار ملف development.sqlite3 ). في هذه المرحلة ، يجب عليك التحقق للتأكد من أن كل شيء يعمل عن طريق تشغيل rails server -e demo من سطر الأوامر. أثناء تشغيل الخادم في بيئة العرض التوضيحي الجديدة ، يمكنك التأكد من أن بيانات الاختبار الخاصة بك على النحو الذي تريده ، ولكن يمكنك دائمًا العودة وتحرير هذا المحتوى لاحقًا. عند إضافة المحتوى الخاص بك إلى قاعدة البيانات التجريبية ، أوصي بإنشاء مجموعة نظيفة من البيانات بحيث يكون الملف صغيرًا قدر الإمكان. ومع ذلك ، إذا كنت بحاجة إلى ترحيل البيانات من قاعدة بيانات أخرى ، فإنني أوصي بـ YamlDb ، الذي يقوم بإنشاء تنسيق مستقل عن قاعدة البيانات لتفريغ البيانات واستعادتها.

إذا كان تطبيق ريلز الخاص بك يعمل بالشكل المتوقع ، فيمكنك الانتقال إلى الخطوة التالية.

الخطوة الثانية: استخدام قاعدة البيانات التجريبية

الجزء الأساسي من هذا البرنامج التعليمي هو القدرة على السماح لكل جلسة باستخدام ملف قاعدة بيانات SQLite مختلف. عادةً ما يتصل تطبيقك بنفس قاعدة البيانات لكل مستخدم بحيث تكون هناك حاجة إلى رمز إضافي لهذه المهمة.

للبدء في السماح لـ Ruby on Rails بتبديل قواعد البيانات ، نحتاج أولاً إلى إضافة الطرق الخاصة الأربع التالية إلى application_controller.rb . ستحتاج أيضًا إلى تحديد عامل التصفية قبل للطريقة set_demo_database بحيث يتم استدعاء المنطق الذي يشير إلى قاعدة البيانات التجريبية الصحيحة عند كل تحميل للصفحة.

 # 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

نظرًا لأن كل جلسة خادم سيكون لها قاعدة بيانات مختلفة ، فسوف تخزن اسم ملف قاعدة البيانات في متغير جلسة. كما ترى ، نحن نستخدم session[:demo_db] لتتبع قاعدة البيانات المحددة للمستخدم. يتحكم أسلوب set_demo_database قاعدة البيانات التي يجب استخدامها عن طريق إنشاء الاتصال بقاعدة البيانات المحددة في متغير جلسة العمل. تقوم طريقة default_demo_database ببساطة بتحميل مسار قاعدة البيانات كما هو محدد في ملف التكوين database.yml .

إذا كنت تستخدم لغة مجردة ، فمن المحتمل في هذه المرحلة أنه يمكنك فقط تحديث البرنامج النصي لاتصال قاعدة البيانات للإشارة إلى قاعدة البيانات الجديدة ثم الانتقال إلى القسم التالي. في ريلز ، تتطلب الأشياء بضع خطوات أخرى لأنها تتبع نموذج برنامج "الاصطلاح على التكوين".

الخطوة الثالثة: نسخ ملف SQLite

الآن بعد أن تم إعداد التطبيق لاستخدام قاعدة البيانات الجديدة ، نحتاج إلى مشغل للجلسة التجريبية الجديدة. من أجل البساطة ، ابدأ فقط باستخدام زر "بدء العرض التوضيحي" الأساسي. يمكنك أيضًا جعله نموذجًا حيث يمكنك جمع اسم وعنوان بريد إلكتروني (للمتابعة من فريق المبيعات ، وما إلى ذلك) أو أي عدد من الأشياء.

بالتمسك باتفاقيات Rails ، قم بإنشاء وحدة تحكم "Demo" جديدة:

 rails generate controller demos new

بعد ذلك ، يجب عليك تحديث المسارات للإشارة إلى إجراءات وحدة التحكم الجديدة الخاصة بك ، ولفها في شرطي لمنع استدعائها في بيئة الإنتاج. يمكنك تسمية المسارات بالطريقة التي تريدها أو تسميتها باستخدام اصطلاحات ريلز القياسية:

 if Rails.env == 'demo' get 'demos/new', as: 'new_demo' post 'demos' => 'demos#create', as: 'demos' end

بعد ذلك ، دعنا نضيف نموذجًا أساسيًا جدًا إلى views/demos/new.html.erb . قد ترغب في إضافة حقول نموذج إضافية لالتقاط:

 <h1>Start a Demo</h1> <%= form_tag demos_path, method: :post do %> <%= submit_tag 'Start Demo' %> <% end %>

السحر يحدث في عمل create . عندما يرسل المستخدم إلى هذا المسار ، سيقوم الإجراء بنسخ ملف demo.sqlite3 ملف فريد جديد ، وتعيين متغيرات الجلسة ، وتسجيل الدخول إلى المستخدم (إن أمكن) ، ثم إعادة توجيه المستخدم إلى الصفحة المناسبة (سنطلق على هذا اسم 'لوحة القيادة').

 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

الآن يجب أن تكون قادرًا على تجربة الكود التجريبي محليًا عن طريق تشغيل الخادم مرة أخرى باستخدام rails server -e demo .

إذا كان الخادم قيد التشغيل بالفعل ، فستحتاج إلى إعادة تشغيله لأي تغييرات تجريها نظرًا لتكوينه للتخزين المؤقت للرمز مثل خادم الإنتاج.

بمجرد أن تعمل جميع التعليمات البرمجية كما هو متوقع ، قم بتنفيذ التغييرات في التحكم في الإصدار وتأكد من تنفيذ ملف demo.sqlite3 ، ولكن ليس الملفات الموجودة في دليل db/demos . إذا كنت تستخدم git ، فيمكنك ببساطة إضافة ما يلي إلى ملف .gitignore الخاص بك:

إذا كنت ترغب في جمع معلومات إضافية من المستخدم التجريبي (مثل الاسم و / أو البريد الإلكتروني) ، فمن المحتمل أن ترغب في إرسال هذه المعلومات عبر واجهة برمجة التطبيقات (API) إما إلى التطبيق الرئيسي الخاص بك أو إلى بعض خطوط المبيعات الأخرى لأن قاعدة البيانات التجريبية الخاصة بك لن تكون موثوقة (يتم إعادة تعيينه في كل مرة تقوم فيها بإعادة النشر).

 !/db/demo.sqlite3 db/demos/*

الخطوة النهائية: نشر الخادم التجريبي الخاص بك

الآن بعد أن أصبح الإعداد التجريبي الخاص بك يعمل محليًا ، من الواضح أنك تريد نشره حتى يتمكن الجميع من استخدامه. على الرغم من اختلاف كل تطبيق ، فإنني أوصي بأن يكون التطبيق التجريبي موجودًا على خادم منفصل ، وبالتالي فإن النطاق هو تطبيق الإنتاج الخاص بك (مثل demo.myapp.com). سيضمن ذلك الحفاظ على عزل البيئتين. بالإضافة إلى ذلك ، نظرًا لأنه يتم تخزين ملف SQLite على الخادم ، فلن تعمل خدمات مثل Heroku لأنها لا توفر الوصول إلى نظام الملفات. ومع ذلك ، لا يزال بإمكانك استخدام أي مزود VPS عمليًا (مثل AWS EC2 و Microsoft Azure وما إلى ذلك). إذا كنت تحب الراحة الآلية ، فهناك منصات أخرى كخيارات خدمة تتيح لك العمل مع VPS.

بغض النظر عن عملية النشر الخاصة بك ، قد تحتاج أيضًا إلى التحقق من أن التطبيق لديه أذونات القراءة / الكتابة المناسبة للدليل الخاص بك حيث تخزن ملفات SQLite التجريبية. يمكن التعامل مع هذا يدويًا أو باستخدام خطاف نشر.

SQLite لن تعمل بالنسبة لي. ماذا عن أنظمة قواعد البيانات الأخرى؟

لا يتم إنشاء تطبيقين متشابهين ولا متطلبات قاعدة البيانات الخاصة بهما. باستخدام SQLite ، لديك ميزة القدرة على نسخ قاعدة البيانات بسرعة ، فضلاً عن القدرة على تخزين الملف في التحكم في الإصدار. بينما أعتقد أن SQLite ستعمل في معظم المواقف (خاصة مع Rails) ، هناك مواقف قد لا يكون فيها SQLite مناسبًا لاحتياجات تطبيقك. لحسن الحظ ، لا يزال من الممكن استخدام نفس المفاهيم المذكورة أعلاه مع أنظمة قواعد البيانات الأخرى. ستكون عملية نسخ قاعدة البيانات مختلفة قليلاً لكل نظام ، لكنني سأضع الخطوط العريضة لحل لـ MySQL وتوجد عملية مماثلة مع PostgreSQL وغيرها.

تعمل غالبية الطرق التي تمت تغطيتها أعلاه دون أي تعديلات إضافية. ومع ذلك ، بدلاً من تخزين ملف SQLite في التحكم في الإصدار الخاص بك ، يجب عليك استخدام mysqldump (أو pg_dump لـ PostgreSQL) لتصدير ملف SQL لأي قاعدة بيانات بها المحتوى الذي ترغب في استخدامه لتجربتك التجريبية. يجب أيضًا تخزين هذا الملف في التحكم في الإصدار الخاص بك.

سيتم العثور على التغييرات الوحيدة على الكود السابق في العرض demos#create . بدلاً من نسخ ملف SQLite3 ، سيقوم إجراء وحدة التحكم بإنشاء قاعدة بيانات جديدة ، وتحميل ملف sql في قاعدة البيانات هذه ومنح أذونات لمستخدم قاعدة البيانات إذا لزم الأمر. الخطوة الثالثة لمنح الوصول ضرورية فقط إذا كان مستخدم مسؤول قاعدة البيانات الخاص بك مختلفًا عن المستخدم الذي يستخدمه التطبيق للاتصال. يستخدم الكود التالي أوامر MySQL القياسية للتعامل مع هذه الخطوات:

 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 ، ​​مثل العديد من اللغات الأخرى بما في ذلك PHP ، باستخدام backticks لتنفيذ أمر shell ( `ls -a` ) من داخل التعليمات البرمجية الخاصة بك. ومع ذلك ، يجب عليك استخدام هذا بحذر والتأكد من عدم إمكانية إدراج معلمات أو متغيرات تواجه المستخدم في الأمر لحماية خادمك من التعليمات البرمجية التي تم حقنها بشكل ضار. في هذا المثال ، نتفاعل بشكل صريح مع أدوات سطر أوامر MySQL ، وهي الطريقة الوحيدة لإنشاء قاعدة بيانات جديدة. هذه هي الطريقة نفسها التي ينشئ بها إطار عمل Ruby on Rails قاعدة بيانات جديدة. تأكد من استبدال ENV['DB_ADMIN'] و ENV['DB_ADMIN_PASSWORD'] إما بمتغير البيئة الخاص بك أو بأي طريقة أخرى لتعيين اسم مستخدم قاعدة البيانات. ستحتاج إلى أن تفعل الشيء نفسه مع ENV['DB_USERNAME'] إذا كان المستخدم الإداري الخاص بك مختلفًا عن مستخدم تطبيقك.

هذا كل ما يتطلبه الأمر للتبديل إلى MySQL! الميزة الأكثر وضوحًا لهذا الحل هي أنه لا داعي للقلق بشأن المشكلات المحتملة التي قد تظهر من بناء الجملة المختلف بين أنظمة قواعد البيانات.

في النهاية ، يتم اتخاذ القرار النهائي بناءً على الجودة والخدمة المتوقعة ، بدلاً من الراحة والسرعة ، ولا يتأثر بالضرورة بنقطة السعر وحدها.

افكار اخيرة

هذه مجرد نقطة بداية لما يمكنك فعله بخادمك التجريبي الجديد. على سبيل المثال ، يمكن أن يحتوي موقع الويب التسويقي الخاص بك على رابط "جرب ميزة XYZ". إذا كنت لا تطلب اسمًا أو بريدًا إلكترونيًا ، فيمكنك ربط demos#create method برابط مثل /demos/?feature=xyz وسيؤدي الإجراء ببساطة إلى إعادة التوجيه إلى الميزة و / أو الصفحة المطلوبة ، بدلاً من لوحة القيادة في المثال أعلاه.

أيضًا ، إذا كنت تستخدم SQLite للتطوير وبيئات العرض التوضيحي ، فإن وجود قاعدة بيانات نموذجية في التحكم في الإصدار يمنح جميع مطوريك إمكانية الوصول إلى قاعدة بيانات نظيفة لاستخدامها في التطوير المحلي أو بيئات الاختبار أو اختبار ضمان الجودة. الاحتمالات لا حصر لها.

يمكنك تنزيل عرض توضيحي مكتمل من GitHub.