‫Ruby on Rails على WebAssembly، رحلة التطوير الشاملة داخل المتصفّح

Vladimir Dementyev
Vladimir Dementyev

تاريخ النشر: 31 كانون الثاني (يناير) 2025

تخيل تشغيل مدوّنة تعمل بكامل وظائفها في المتصفّح، وليس فقط الواجهة الأمامية، بل الخلفية أيضًا. لا تتضمّن هذه التجربة أيّ خوادم أو خدمات سحابة إلكترونية، بل تتضمّن فقطك أنت ومتصفّحك وWebAssembly. من خلال السماح بتشغيل منصّات تطوير الويب الكلاسيكية على الويب على الجهاز، تمكّن WebAssembly من محو الحدود بين تطوير الويب الكلاسيكي وفتح آفاق جديدة مثيرة. في هذه المشاركة، يشارك فلاديمير ديمنتيف (رئيس قسم الخلفية في Evil Martians) مستوى التقدّم في جعل Ruby on Rails جاهزة لاستخدام WebAssembly والمتصفّحات:

  • كيفية استخدام Rails في المتصفّح في 15 دقيقة
  • جولة خلف الكواليس في عملية تحويل الرموز البرمجية إلى وحدات wasm في Rails
  • مستقبل Rails وWasm

يمكنك الآن تنفيذ الخطوات المشهورة في Ruby on Rails "إنشاء مدوّنة في 15 دقيقة" مباشرةً في المتصفّح.

‫Ruby on Rails هو إطار عمل ويب يركز على إنتاجية المطوّرين وسرعة إرسال التطبيقات. وهي التكنولوجيا التي تستخدمها الشركات الرائدة في المجال، مثل GitHub و Shopify. بدأت شعبية إطار العمل منذ عدة سنوات مع إصدار "كيفية إنشاء مدوّنة في 15 دقيقة"، وهو فيديو مشهور أعدّه "ديفيد هاينيميير هانزسون" (أو DHH). في عام 2005، كان من الصعوبة بمكان إنشاء تطبيق ويب يعمل بشكل كامل في وقت قصير جدًا. لقد كان تجربتي ساحرة.

اليوم، أودّ استعادة هذا الشعور السحري من خلال إنشاء تطبيق Rails يعمل بالكامل في المتصفّح. تبدأ رحلتك بإنشاء تطبيق Rails أساسي بالطريقة المعتادة، ثم حزمه لنظام التشغيل Wasm.

الخلفية: إنشاء "مدوّنة في 15 دقيقة" على سطر الأوامر

بافتراض أنّه تم تثبيت Ruby وRuby on Rails على جهازك، يمكنك البدء بإنشاء تطبيق Ruby on Rails جديد وإنشاء إطار عمل لبعض الوظائف (تمامًا كما هو موضّح في الفيديو الأصلي "إنشاء مدوّنة في 15 دقيقة"):


$ rails new --css=tailwind web_dev_blog

  create  .ruby-version
  ...

$ cd web_dev_blog

$ bin/rails generate scaffold Post title:string date:date body:text

  create    db/migrate/20241217183624_create_posts.rb
  create    app/models/post.rb
  ...

$ bin/rails db:migrate

== 20241217183624 CreatePosts: migrating ====================
-- create_table(:posts)
   -> 0.0017s
== 20241217183624 CreatePosts: migrated (0.0018s) ===========

بدون الحاجة إلى تعديل قاعدة البيانات، يمكنك الآن تشغيل التطبيق ومشاهدته في العمل:

$ bin/dev

=> Booting Puma
=> Rails 8.0.1 application starting in development
...
* Listening on http://127.0.0.1:3000

يمكنك الآن فتح مدونتك على الرابط http://localhost:3000/posts والبدء في كتابة محتوى المدونة.

مدوّنة Ruby on Rails تم إطلاقها من سطر الأوامر الذي يعمل في المتصفّح

لديك تطبيق مدوّنة أساسي جدًا ولكنه فعّال تم إنشاؤه في دقائق. وهو تطبيق متكامل يُدار من الخادم: لديك قاعدة بيانات (SQLite) للحفاظ على بياناتك وخادم ويب لمعالجة طلبات HTTP (Puma) وبرنامج Ruby للحفاظ على منطق نشاطك التجاري وتوفير واجهة المستخدم ومعالجة تفاعلات المستخدمين. أخيرًا، هناك طبقة رقيقة من JavaScript (Turbo) لتبسيط تجربة التصفّح.

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

المستوى التالي: إنشاء "مدوّنة في 15 دقيقة" باستخدام WebAssembly

منذ إضافة WebAssembly، أصبحت المتصفّحات قادرة على تشغيل رمز JavaScript، بالإضافة إلى أي رمز قابل للتحويل إلى Wasm. ولا تشكّل "روبي" استثناءً. من المؤكد أنّ Rails أكثر من مجرد Ruby، ولكن قبل التوغّل في اختلافاتها، لنواصل العرض الترويجي وتحويله إلى ملف ‎wasm (وهو فعل صاغته مكتبة wasmify-rails) لتطبيق Rails.

ما عليك سوى تنفيذ بعض الأوامر لتجميع تطبيق المدوّنة في ملف ‎VMWasm وتشغيله في المتصفّح.

أولاً، عليك تثبيت مكتبة wasmify-rails باستخدام Bundler (npm لـ Ruby) وتشغيل أداة إنشاء الرموز البرمجية باستخدام واجهة سطر أوامر Rails:

$ bundle add wasmify-rails

$ bin/rails wasmify:install

  create  config/wasmify.yml
  create  config/environments/wasm.rb
  ...
  info   The application is prepared for Wasm-ificaiton!

يضبط الأمر wasmify:rails بيئة تنفيذ "wasm" مخصّصة (بالإضافة إلى البيئات التلقائية "development" و"test" و "production" ) ويثبّت التبعيات المطلوبة. بالنسبة إلى تطبيق Rails جديد، هذا كافٍ لجعله متوافقًا مع WebAssembly.

بعد ذلك، أنشئ وحدة Wasm الأساسية التي تحتوي على وقت تشغيل Ruby والمكتبة المعيار وجميع ملفات تطبيقك التابعة:

$ bin/rails wasmify:build

==> RubyWasm::BuildSource(3.3) -- Building
...
==> RubyWasm::CrossRubyProduct(ruby-3.3-wasm32-unknown-wasip1-full-4aaed4fbda7afe0bdf4e22167afd101e) -- done in 47.37s
INFO: Packaging gem: rake-13.2.1
...
INFO: Packaging gem: wasmify-rails-0.2.0
INFO: Packaging setup.rb: bundle/setup.rb
INFO: Size: 73.77 MB

يمكن أن تستغرق هذه الخطوة بعض الوقت: عليك إنشاء Ruby من المصدر لربط الإضافات الأصلية (المكتوبة بلغة C) بشكل صحيح من المكتبات التابعة لجهات خارجية. وسيتم تناول هذا النقص (المؤقت) لاحقًا في هذه المشاركة.

وحدة Wasm المجمّعة هي مجرد أساس لتطبيقك. يجب أيضًا تجميع رمز التطبيق نفسه وجميع مواد العرض (مثل الصور وCSS وJavaScript). قبل إجراء عملية الحزمة، أنشئ مشغّل أساسيًا تطبيقًا يمكن استخدامه لتشغيل Rails المحوَّلة إلى رمز برمجي قابل للتنفيذ في لغة الويب في المتصفّح. للقيام بذلك، هناك أيضًا أمر إنشاء:

$ bin/rails wasmify:pwa

  create  pwa
  create  pwa/boot.html
  create  pwa/boot.js
  ...
  prepend  config/wasmify.yml

ينشئ الأمر السابق تطبيقًا بسيطًا لتطبيق الويب التقدمي (PWA) تم إنشاؤه باستخدام Vite ويمكن استخدامه محليًا لاختبار وحدة Wasm المجمّعة من Rails أو نشرها بشكل ثابت لتوزيع التطبيق.

الآن، باستخدام المشغِّل، ما عليك سوى تجميع التطبيق بالكامل في ملف ثنائي واحد من Wasm:

$ bin/rails wasmify:pack
...
Packed the application to pwa/app.wasm
Size: 76.2 MB

هذا كل شيء! شغِّل تطبيق المشغّل وشاهد تطبيق التدوين باستخدام Rails وهو يعمل بشكل كامل داخل المتصفّح:

$ cd pwa/

$ yarn dev

  VITE v4.5.5  ready in 290 ms

    Local:   http://localhost:5173/

انتقِل إلى http://localhost:5173، وانتظِر قليلاً إلى أن يصبح زر "التشغيل" نشطًا، ثم انقر عليه. استمتع بالعمل مع تطبيق Rails الذي يتم تشغيله محليًا في المتصفّح.

مدوّنة Ruby on Rails تم إطلاقها من علامة تبويب متصفّح تعمل في علامة تبويب متصفّح أخرى

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

عرض توضيحي

يمكنك تجربة العرض الترويجي المضمّن في المقالة أو تشغيل العرض الترويجي في نافذة مستقلة. يمكنك الاطّلاع على رمز المصدر على GitHub.

جولة خلف الكواليس في Rails على Wasm

لفهم التحديات (والحلول) التي تواجهك عند تجميع تطبيق على جانب الخادم في وحدة Wasm، توضّح بقية هذه المشاركة المكوّنات التي تشكّل جزءًا من هذه البنية.

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

المكونات التي تشكّل تطبيق Ruby on Rails: خادم ويب وقاعدة بيانات وقائمة انتظار ومساحة تخزين بالإضافة إلى مكوّنات Ruby الأساسية: الأحجار الكريمة والإضافات الأصلية وأدوات النظام والجهاز الافتراضي Ruby

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

الأساس: ruby.wasm

أصبحت Ruby رسميًا متوافقة مع Wasm في عام 2022 (بدءًا من الإصدار 3.2.0)، ما يعني أنّه يمكن تجميع رمز C المصدر إلى Wasm واستخدام آلة افتراضية Ruby في أي مكان تريده. يُرسِل مشروع ruby.wasm وحدات مُجمَّعة مسبقًا وعمليات ربط JavaScript لتشغيل Ruby في المتصفّح (أو أي وقت تشغيل آخر لـ JavaScript). يتضمّن مشروع ruby:wasm أيضًا أدوات الإنشاء التي تتيح لك إنشاء إصدار مخصّص من Ruby يتضمّن تبعيات إضافية، وهذا مهم جدًا للمشاريع التي تعتمد على مكتبات تتضمّن إضافات C. نعم، يمكنك تجميع الإضافات الأصلية إلى Wasm أيضًا. (حسنًا، ليس أي إضافة حتى الآن، ولكن معظم التطبيقات).

تتوافق Ruby حاليًا بالكامل مع واجهة نظام WebAssembly، WASI 0.1. إنّ الإصدار 0.2 من WASI الذي يتضمّن نموذج المكوّنات متوفّر حاليًا في مرحلة الإصدار التمهيدي ويفصله عن اكتماله بضع خطوات.وبعد توفّر الإصدار 0.2 من WASI، سيتم التخلص من الحاجة الحالية إلى إعادة تجميع اللغة بأكملها في كل مرة تحتاج فيها إلى إضافة تبعيات أصلية جديدة: يمكن تقسيمها إلى مكوّنات.

كأثر جانبي، من المفترض أن يساعد نموذج المكوّنات أيضًا في تقليل حجم الحِزمة. يمكنك الاطّلاع على مزيد من المعلومات حول تطوير ruby.wasm ومستوى تقدّمه من خلال الاطّلاع على المحادثة بعنوان ما يمكنك فعله باستخدام Ruby على WebAssembly.

وبالتالي، تم حلّ جزء Ruby من معادلة Wasm. ولكنّ Rails بصفتها إطار عمل ويب تحتاج إلى كل المكوّنات الموضّحة في الرسم البياني السابق. تابِع القراءة لمعرفة كيفية وضع مكوّنات أخرى في المتصفّح وربطها معًا في Rails.

الاتصال بقاعدة بيانات قيد التشغيل في المتصفّح

تأتي SQLite3 مع توزيع Wasm رسمي وحزمة JavaScript مقابلة، وبالتالي فهي جاهزة للتضمين في المتصفّح. يتوفّر PostgreSQL لـ Wasm من خلال مشروع PGlite. لذلك، ما عليك سوى معرفة كيفية الربط بقاعدة البيانات داخل المتصفّح من تطبيق Rails on Wasm.

يُطلق على المكوّن أو الإطار الفرعي في Rails المسؤول عن نمذجة البيانات والتفاعلات مع قاعدة البيانات اسم Active Record (نعم، تم تسميته على اسم نمط تصاميم ORM). يزيل Active Record تنفيذ قاعدة البيانات الفعلية التي تستخدم لغة الاستعلامات البنيوية (SQL) من код التطبيق من خلال محولات قاعدة البيانات. يوفّر لك Rails تلقائيًا محوِّلات SQLite3 وPostgreSQL وMySQL. ومع ذلك، تفترض جميعها الاتصال بقواعد بيانات حقيقية متاحة على الشبكة. لحلّ هذه المشكلة، يمكنك كتابة محوِّلات خاصة بك للاتصال بقواعد بيانات محلية داخل المتصفّح.

في ما يلي كيفية إنشاء محولات SQLite3 Wasm وPGlite التي تم تنفيذها كجزء من مشروع Wasmify Rails:

  • تكتسِب فئة المُحوِّل الخصائص من المُحوِّل المضمّن المقابل (مثل class PGliteAdapter < PostgreSQLAdapter)، ما يتيح لك إعادة استخدام منطق إعداد الطلب الفعلي وتحليل النتائج.
  • بدلاً من الاتصال بقاعدة البيانات على مستوى منخفض، يمكنك استخدام كائن واجهة خارجية مضمّن في وقت تشغيل JavaScript، وهو عبارة عن جسر بين وحدة Rails Wasm وقاعدة بيانات.

على سبيل المثال، في ما يلي تنفيذ الجسر لـ SQLite3 Wasm:

export function registerSQLiteWasmInterface(worker, db, opts = {}) {
  const name = opts.name || "sqliteForRails";

  worker[name] = {
    exec: function (sql) {
      let cols = [];
      let rows = db.exec(sql, { columnNames: cols, returnValue: "resultRows" });

      return {
        cols,
        rows,
      };
    },

    changes: function () {
      return db.changes();
    },
  };
}

من وجهة نظر التطبيق، فإنّ عملية الانتقال من قاعدة بيانات حقيقية إلى قاعدة بيانات داخل المتصفّح هي مجرد مسألة ضبط:

# config/database.yml
development:
  adapter: sqlite3

production:
  adapter: sqlite3

wasm:
  adapter: sqlite3_wasm
  js_interface: "sqliteForRails"

لا يتطلّب العمل مع قاعدة بيانات محلية الكثير من الجهد. ومع ذلك، إذا كانت هناك حاجة إلى مزامنة البيانات مع بعض المصادر الموثوقة، قد تواجه تحدّيًا من مستوى أعلى. لا يدخل هذا السؤال في نطاق هذا المنشور (ملاحظة: يمكنك الاطّلاع على العرض التقديمي لـ Rails on PGlite وElectricSQL).

الخدمة العاملة بصفتها خادم ويب

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

مشغّل الخدمة هو نوع خاص من مشغّل الويب يعمل كوكيل بين تطبيق JavaScript والشبكة. ويمكنه اعتراض الطلبات و التلاعب بها، على سبيل المثال: عرض البيانات المخزّنة مؤقتًا أو إعادة التوجيه إلى عناوين URL أخرى أو… إلى وحدات Wasm. في ما يلي مخطّط للخدمة التي تعمل على تقديم الطلبات باستخدام تطبيق Rails الذي يعمل في Wasm:

// The vm variable holds a reference to the Wasm module with a
// Ruby VM initialized
let vm;
// The db variable holds a reference to the in-browser
// database interface
let db;

const initVM = async (progress, opts = {}) => {
  if (vm) return vm;
  if (!db) {
    await initDB(progress);
  }
  vm = await initRailsVM("/app.wasm");
  return vm;
};

const rackHandler = new RackHandler(initVM});

self.addEventListener("fetch", (event) => {
  // ...
  return event.respondWith(
    rackHandler.handle(event.request)
  );
});

يتم تشغيل "الاسترداد" في كل مرة يقدّم فيها المتصفّح طلبًا. يمكنك الحصول على معلومات الطلب (عنوان URL ورؤوس HTTP والنص) وإنشاء عنصر الطلب الخاص بك.

تعتمد Rails، مثل معظم تطبيقات الويب المستندة إلى Ruby، على واجهة Rack للعمل مع طلبات HTTP. تصف واجهة Rack تنسيق عناصر الطلب والاستجابة بالإضافة إلى واجهة معالِج HTTP الأساسي (التطبيق). يمكنك التعبير عن هذه السمات على النحو التالي:

request = {
   "REQUEST_METHOD" => "GET",
   "SCRIPT_NAME"    => "",
   "SERVER_NAME"  => "localhost",
   "SERVER_PORT" => "3000",
   "PATH_INFO"      => "/posts"
}

handler = proc do |env|
  [
    200,
    {"Content-Type" => "text/html"},
    ["<!doctype html><html><body>Hello Web!</body></html>"]
  ]
end

handler.call(request) #=> [200, {...}, [...]]

إذا وجدت تنسيق الطلب مألوفًا، من المحتمل أنّك عملت مع CGI في السابق.

يتحمّل كائن JavaScript‏ RackHandler مسؤولية تحويل الطلبات والنتائج بين نطاقَي JavaScript وRuby. بما أنّ معظم تطبيقات الويب التي تستخدم Ruby تستخدم Rack، يصبح التنفيذ شاملاً وليس خاصًا بـ Rails. ومع ذلك، فإنّ عملية التنفيذ الفعلي طويلة جدًا ولا يمكن نشرها هنا.

عامل الخدمة هو أحد النقاط الأساسية المتكاملة لتطبيق ويب داخل المتصفّح. وهو ليس خادمًا وكيلاً لبروتوكول HTTP فحسب، بل هو أيضًا طبقة تخزين مؤقت ومبدِّل شبكة (أي يمكنك إنشاء تطبيق يستخدم الموارد على الجهاز أولاً أو يمكن استخدامه بلا اتصال بالإنترنت). وهذا المكوّن أيضًا يمكن أن يساعدك في عرض ملفات uploaded المستخدم.

إبقاء عمليات تحميل الملفات في المتصفّح

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

في Rails، يُطلق على الجزء من إطار العمل المسؤول عن التعامل مع عمليات تحميل الملفات اسم Active Storage. يوفّر Active Storage للمطوّرين واجهات وعمليات تجريدية للعمل مع الملفات بدون التفكير في آلية التخزين على مستوى منخفض. بغض النظر عن مكان تخزين ملفاتك، سواء على محرك أقراص ثابت أو في السحابة الإلكترونية، لا يدرك رمز التطبيق ذلك.

على غرار Active Record، لتفعيل آلية تخزين مخصّصة، كلّ ما تحتاجه هو تنفيذ محوِّل خدمة تخزين ملائم. أين يمكن تخزين الملفات في المتصفّح؟

الخيار التقليدي هو استخدام قاعدة بيانات. نعم، يمكنك تخزين الملفات كوحدات بيانات ملف سحابي في قاعدة البيانات، ولا يلزم توفُّر عناصر إضافية للبنية الأساسية. وهناك Active Storage Database، وهو مكوّن إضافي جاهز لذلك في Rails. ومع ذلك، فإنّ عرض الملفات المخزّنة في قاعدة بيانات من خلال تطبيق Rails الذي يعمل ضمن WebAssembly ليس مثاليًا لأنّه يتضمن جولات من (ترميز/ترميز عكسي) غير مجانية.

إنّ الحلّ الأفضل والمُحسَّن للمتصفّح هو استخدام واجهات برمجة تطبيقات نظام الملفات ومعالجة عمليات تحميل الملفات والملفات التي حمّلها الخادم مباشرةً من "عامل الخدمة" . ومن بين واجهات برمجة التطبيقات المناسبة لهذه البنية الأساسية، هناك واجهة برمجة التطبيقات OPFS (نظام الملفات الخاص بالمصدر)، وهي واجهة برمجة تطبيقات حديثة جدًا للمتصفّح ستؤدي بدورٍ مهمٍ في التطبيقات المستقبلية المُشغّلة داخل المتصفّح.

ما يمكن أن يحقّقه إطار عمل Rails وWebAssembly معًا

أعتقد أنّك طرحت هذا السؤال على نفسك عندما بدأت قراءة المقالة: لماذا يتم تشغيل إطار عمل من جهة الخادم في المتصفّح؟ إنّ فكرة أنّ إطار عمل أو مكتبة من جهة الخادم (أو من جهة العميل) هي مجرّد تصنيف. تعمل الرموز البرمجية الجيدة، وعلى وجه الخصوص، الرمز البرمجي المجرد بشكل جيد في كل مكان. لا يجب أن تمنعك التصنيفات من استكشاف إمكانيات جديدة وتجاوز حدود الإطار (مثل Ruby on Rails) بالإضافة إلى حدود وقت التشغيل (WebAssembly). ويمكن أن يستفيد كلاهما من حالات الاستخدام غير التقليدية هذه.

هناك أيضًا الكثير من حالات الاستخدام التقليدية أو العملية.

أولاً، يؤدي نقل إطار العمل إلى المتصفّح إلى توفير فرص هائلة للتعرّف على الإطار و إنشاء النماذج الأولية. تخيل أنّه بإمكانك استخدام المكتبات والمكونات الإضافية والنماذج مباشرةً في المتصفّح ومع أشخاص آخرين. أتاحت منصة Stackblitz ذلك لإطارات عمل JavaScript. ومن الأمثلة الأخرى WordPress Playground الذي أتاح اللعب بمظاهر WordPress بدون مغادرة صفحة الويب. يمكن أن تتيح تقنية Wasm إجراءً مشابهًا لـ Ruby ومنظومة Ruby المتكاملة.

هناك حالة خاصة من الترميز داخل المتصفّح مفيدة بشكل خاص لمطوّري المحتوى المفتوح المصدر، وهي تحديد أولويات المشاكل وتصحيح الأخطاء فيها. مرة أخرى، سهّلت StackBlitz تنفيذ ذلك في مشاريع JavaScript: يمكنك إنشاء نص برمجي بسيط لإعادة الإنتاج، والإشارة إلى الرابط في إحدى المشاكل على GitHub، وتوفير الوقت على القائمين بالصيانة لإعادة تنفيذ السيناريو. وقد بدأ هذا الإجراء بالفعل في Ruby بفضل مشروع RunRuby.dev (في ما يلي مثال على مشكلة تم حلّها من خلال إعادة الإنشاء في المتصفّح).

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

أخيرًا، من المنطقي أيضًا إنشاء تطبيقات محلية (أو مخصّصة لأجهزة الكمبيوتر المكتبي) باستخدام Rails، لأنّ الإنتاجية التي يوفّرها لك إطار العمل لا تعتمد على وقت التشغيل. تُعدّ الأطر المزوّدة بميزات كاملة مناسبة بشكلٍ جيد لإنشاء التطبيقات المكثّفة من حيث البيانات الشخصية والمنطق. ويُعدّ استخدام WebAssembly كتنسيق توزيع محمول خيارًا متاحًا أيضًا.

هذه ليست سوى بداية رحلة استخدام Rails على WebAssembly. يمكنك الاطّلاع على مزيد من المعلومات حول التحديات والحلول في الدليل الإلكتروني Ruby on Rails on WebAssembly (الذي يُعدّ تطبيق Rails نفسه متوافقًا مع وضع عدم الاتّصال بالإنترنت).