نظرة جديدة على تطوير Fullstack مع إطار Ruby on Rails

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

صورة


Ruby on Rails عبارة عن إطار عمل MVC يركز على التطور السريع ، ويولي الكثير من الاهتمام للحفاظ على الاتساق داخل المشروع (حتى لا يتحول إلى "بسرعة" على أي حال). يوفر العديد من الأدوات لتطوير الواجهة الأمامية والخلفية. في اتجاه Fullstack الكلاسيكي ، كان هناك إغفال مؤقت بسبب الجهل بتطورها ومفهومها الخاطئ حول تأخر الأموال المستخدمة. الهدف من هذه المقالة هو تسليط الضوء على كيفية تطور نهج Fullstack وعدد الاحتمالات المثيرة للاهتمام المختلفة التي ظهرت فيه.

باكر الويب


Webpacker هو جوهرة تأتي مع روبي أون ريلز.

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

يحدد Webpacker التكوينات العامة اللازمة للبدء وهيكل التطبيق ، مما يزيد من اليقين ويبسط فهم المشروع من قبل المطورين المختلفين. بالنسبة لرمز جافا سكريبت ، يتم تخصيص المجلد الذي app/javascript/يحتوي على الملف الأساسي app/javascript/packs/application.js.

تمت إضافة الملفات والمجلدات بواسطة Webpacker
config/webpacker.yml
config/webpack/
config/webpack/development.js
config/webpack/environment.js
config/webpack/production.js
config/webpack/test.js
package.json
postcss.config.js
babel.config.js
.browserslistrc
node_modules/
bin/webpack
bin/webpack-dev-server
app/javascript/
app/javascript/packs/
app/javascript/packs/application.js


يبدأ Webpacker بشكل افتراضي أثناء عملية إنشاء تطبيق جديد ويقوم بتنفيذ إعداداته. يمكنك إنشاء التطبيق على الفور مع تكوينات إضافية لـ Stimulus أو Vue أو Typescript أو أخرى من القائمة المقدمة :

rails new myapp --webpack=stimulus

أو قم بتثبيت تكوينات إضافية بعد إنشاء التطبيق:

bundle exec rails webpacker:install:stimulus

تطوير الواجهة الأمامية مع إطار Ruby on Rails = استخدم أحدث مناهج تطوير JavaScript. تم دمج جميع وسائل الراحة لاستخدام معايير JavaScript الحديثة بشكل جيد مع Ruby on Rails. يتم توفير التكوينات اللازمة للعمل مع Webpack ، مما يسمح لك بأن تكون أقل تشتيتًا من خلال التنظيم الصحيح للمشروع والتركيز على حل المهام الشائعة باستخدام البيئة المألوفة.

الارتباطات


Turbolinks هي مكتبة JavaScript التي تأتي مع Ruby on Rails.

تتمثل المهمة ذات الأولوية لـ Turbolinks في تخفيف الحمل على الخادم وتقليل "طبقات" عند الانتقال إلى عناوين URL للتطبيق. غالبًا ما تتم مقارنة هذه الميزة مع SPA ، لأنها تعطي انطباعًا عن إعادة عرض المحتوى في المتصفح بدلاً من الانتقالات البسيطة بين الصفحات.

مبدأ تشغيل Turbolinks: للتنقل بين الصفحات ليس عن طريق الانتقال القياسي إلى عنوان جديد ، ولكن من خلال تلبية طلب لهذا العنوان "في الخلفية" عبر ajax ، وتحميل الاستجابة في JavaScript ، واستبدال محتويات الصفحة بأخرى جديدة. هذه العملية مصحوبة بأحداث خاصة تسمح لك بإضافة وظائف للانتقال بين الصفحات والعودة إلى الصفحات السابقة. على سبيل المثال،
  • لبدء الانتقال إلى عنوان مختلف: turbolinks:click, turbolinks:before-visit, turbolinks:visit؛
  • أو معالجة طلب لصفحة جديدة: turbolinks:request-start, turbolinks:request-end؛
  • أو في عملية عرض صفحة جديدة turbolinks:before-render, turbolinks:render, turbolinks:load.

بالإضافة إلى ذلك ، يحتوي Turbolinks على شريط تقدم ، ويخزن محفوظات الصفحات المحملة في ذاكرة التخزين المؤقت ويسمح لك بتحديد عناصر الصفحة غير المحدثة.

قابل للتنفيذ


ActionCable هو جزء من إطار عمل Ruby on Rails. يجعل ActionCable العمل مع مآخذ الويب. إلى قائمة القنوات على الخادم، مجلد app/channels/مع الملفات الأساسية channel.rbو المقدمة connection.rb. لتنفيذ الاتصال بهذه القنوات - مجلد app/javascript/channels/يحتوي على ملفات index.jsو consumer.js.

من الأفضل التعرف على إمكانيات ActionCable على الفور بالقدوة. يمكن تنفيذ أبسط اتصال بمقابس الويب بمساعدته في بضع خطوات.

  1. إنشاء ملف القناة

    التطبيق / القنوات / hello_channel.rb
    # app/channels/hello_channel.rb
    class HelloChannel < ApplicationCable::Channel
      def subscribed
        stream_from "hello_1"
      end
    end
    

  2. إنشاء اشتراك لهذه القناة
    التطبيق / جافا سكريبت / القنوات / hello_channel.js
    // app/javascript/channels/hello_channel.js
    import consumer from "./consumer"
    
    consumer.subscriptions.create({ channel: "HelloChannel" }, {
      received(data) {
        console.log("Data received", data);
        document.body.innerText += `\nHello, ${data.name}!`
      }
    })
    


والاتصال بمقابس الويب جاهز.

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

التطبيق / وحدات التحكم / hello_controller.rb
# app/controllers/hello_controller.rb
class HelloController < ApplicationController
  def index
    render :html => "Hello page...", :layout => true
  end

  def new
    ActionCable.server.broadcast("hello_1", name: params[:name])
    head 200
  end
end


config / flights.rb
# config/routes.rb
get "/hello" => "hello#index"
get "/hello/new" => "hello#new"


نبدأ التطبيق ، نذهب إلى العنوان 127.0.0.1haps000 / hello ونفتح وحدة تحكم المتصفح ، حيث يمكنك رؤية تسجيل الرسائل الواردة من الخادم عبر مآخذ الويب.

بعد ذلك ، نرسل طلبًا للعمل بالبريد:

curl http://127.0.0.1:3000/hello/new?name=World

وإلقاء نظرة على صفحة / hello والإخراج في وحدة التحكم الخاصة به.

مساعدو النموذج و Rails-ujs


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

app / views / articles / new.html.erb
<%# app/views/articles/new.html.erb %>
<%#      %>
<%= form_with(model: Article.new) do |f| %>
  <div>
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>
  <div>
    <%= f.label :text %>
    <%= f.text_area :text %>
  </div>
  <%= f.submit %>
<% end %>


config / locales / ru.yml
# config/locales/ru.yml
#       
ru:
  activerecord:
    attributes:
      article:
        title:  
        text:  


config / application.rb
# config/application.rb
#        config/application.rb
config.i18n.default_locale = :ru


التطبيق / وحدات التحكم / articles_controller.rb
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController

  def new
    #  new   
    # rails -     
  end

  def create
    #        
    @article = Article.create(article_params)

    #    -    ,
    #    url  
    #   ,   
    redirect_to @article
  end

  private

  def article_params
    #      
    params.require(:article).permit(:title, :text)
  end
end


يمكنك معرفة المزيد عن هذا المثال هنا و هنا .

ريلز-أوجس


Rails-ujs هو الجزء الأساسي من إطار Ruby on Rails الخاص بـ JavaScript غير المزعج.
يوفر Rails-ujs العديد من الخيارات الإضافية لعناصر الصفحة التي تغير أو توسع طريقة عملها.

خيار بعيد - مصمم للعناصر التي تصل إلى الخادم (الروابط والنماذج) لجعل الطلبات غير متزامنة. مثال الارتباط:

<%= link_to " ", new_article_path, remote: true %>

لعرض نتائج هذا الاستعلام يتطلب معالجة إضافية، على سبيل المثال، إضافة معالج إلى بعيد الأحداث: ajax:success, ajax:error, ajax:complete.

خيار التأكيد - يسمح لك بطلب تأكيد الإجراء قبل تنفيذه.

<%= link_to "", article_path(article), method: :delete,
  data: { confirm: ' ,     ?' } %>


الخيار Disable_with - يسمح لك بإلغاء تنشيط عنصر بعد إجراء
<%= form.submit data: { disable_with: "..." } %>

بالإضافة إلى ذلك ، يحتوي Rails-ujs على العديد من الميزات المفيدة. فيما يلي بعض منها:

Rails.fire(obj, name, data)- وظيفة استدعاء الحدث
Rails.ajax(options)- مجمّع عبر XMLHttpRequest
Rails.isCrossDomain(url)- التحقق من عنوان url الخاص بمجال آخر
Rails.$(selector)- غلاف عبر document.querySelectorAll يمكنك

ربطها بكودك باستخدام الأمر

import Rails from "@rails/ujs"

التحفيز


التحفيز - إطار JavaScript من مطوري Ruby on Rails.

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

المهمة الأساسية للتحفيز هي ربط المعالجات بالأحداث. وفقًا لـ Stimulus ، يجب وضع شفرة المصدر على فئات وحدة التحكم ، ويجب استخدام طرقها كمعالجات. بشكل افتراضي ، يتم تخصيص المجلد الذي app/javascript/controllers/يحتوي على الملف الأساسي لوحدات التحكم في التحفيز في المشروع index.js. هنا يمكننا إضافة وحدات التحكم الخاصة بنا ، لهذا نحتاج إلى إنشاء ملف مع لاحقة _controller.js، على سبيل المثال ،articles_controller.js. بعد ذلك ، يستورد محمل Stimulus مثل هذه الملفات ويربط وحدات التحكم بالكتل المقابلة في صفحاتنا.

تحتوي وحدات التحكم في Stimulus على معدات إضافية: تهيئة كائن وحدة التحكم ( initialize) ، والمساعدين للوصول إلى العناصر داخل الكتلة ( targetsوالأهداف) ، وإرفاق كائن وحدة التحكم بالكتلة ( connect) وفصلها ( disconnect) ، والوصول إلى سمات البيانات الخاصة بالكتلة ( this.data.get). فيما يلي مثال على كتلة دولة نشطة / غير نشطة مكتوبة في التحفيز.

app / views / home / show.html.erb
<%# app/views/home/show.html.erb %>

<%#   home   %>
<%#      (  ) %>
<div data-controller="home"
    data-home-active-text="Activated" data-home-deactive-text="Deactivated">

  <%#    text  home  %>
  <p data-target="home.text"></p>

  <%#   action click  home %>
  <button data-action="home#click"></button>

</div>



app / javascript / controlers / home_controller.js
// app/javascript/controllers/home_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  //  
  static targets = [ "text" ]

  initialize() {
    //      
    this.activeText = this.data.get("active-text");
    this.deactiveText = this.data.get("deactive-text");
  }

  connect() {
    //   /
    this.active = this.data.get("active") == "true";
    //  
    this.refresh();
  }

  disconnect() {
    //     
    this.element.setAttribute("data-home-active", !!this.active);
  }

  click() {
    //  
    this.active = !this.active;
    //  
    this.refresh();
  }

  //    
  refresh(){
    //     
    this.element.style.background =   this.active ? "none" : "#EEE";
    //  
    this.textTarget.innerHTML =   this.active ? this.activeText : this.deactiveText;
    //   
    this.textTarget.style.color = this.active ? "black" : "#777";
  }
}


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

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

التحفيز و Webpacker


يوفر Webpacker أوامر لإنشاء تطبيق باستخدام التحفيز المتصل:

rails new myapp --webpack=stimulus

أو لربطه بمشروع تم إنشاؤه بالفعل:

bundle exec rails webpacker:install:stimulus

التحفيز وجافا سكريبت


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

التحفيز وروبي على القضبان


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

التحفيز و ActionCable


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

التحفيز والتربينات


يتم تنشيط التحفيز بمجرد أن يقوم Turbolinks بتحميل الصفحة ؛ لا حاجة إلى معالجات إضافية لربط التحفيز بكتل الصفحة.

لا تعمل روابط Turbol على تسهيل تحميل الصفحات فحسب ، بل تخزن أيضًا محتوياتها مؤقتًا عند الانتقال. عند العودة إلى الصفحة المخبأة من السجل ، يتم تنشيط التحفيز تلقائيًا ، كما هو الحال عند تحميل صفحة جديدة. إذا كنت تريد حفظ بعض القيم قبل فصل وحدة التحكم عن الوحدة ، فيمكنك استخدام الطريقة disconnect- وبعد ذلك ، عند إرجاع وحدة التحكم وتوصيلها ، ستتمكن من استعادة حالتها الأخيرة. في كود المثال الأول للعمل مع التحفيز ، يمكنك أن ترى كيف ، عند قطع الاتصال ( disconnect) ، يتم إصلاح القيمة في سمة البيانات في كتلة وحدة التحكم this.active، وعند الاتصال ( connect) ، يتم استخراجه مرة أخرى.

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

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

وبالتالي ، يمكن استخدام العودة إلى سجل الصفحة كطريقة ملائمة للعمل مع تطبيق الويب الخاص بك.

نماذج التحفيز والمساعدين


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

app / views / articles / show.html.erb
<%#       app/views/articles/show.html.erb %>

<%#      %>
<% article_data = article.attributes
      .slice("id", "created_at", "updated_at", "author", "title").to_json %>

<%#   div    content_tag %>
<%= content_tag :div,
    :data => { controller: :articles },
    "data-articles-attributes" => article_data do %>
  <%# ... %>
<% end %>


app / javascript / controllers / articles_controller.js (مقتطف)
//   
//   initialize  app/javascript/controllers/articles_controller.js
initialize() {
  this.attributes = JSON.parse(this.data.get("attributes"));
  //   
  // ...
}


التحفيز والقضبان


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

الارتباط مع الخيار البعيد ومعالج التحفيز
<%= link_to " ",
  article_path(article, format: :html),
  data: { remote: true, action: "ajax:success->articles#showArticle" } %>


عند النقر على هذا الرابط ، سيحدث طلب Ajax غير متزامن إلى وحدة تحكم القضبان articles_controller.rbلإجراء العرض. عند تلقي استجابة إيجابية ، سيتم إطلاق حدث وسيتم ajax:successاستدعاء الطريقة showArticleمن وحدة التحكمapp/javascript/controllers/articles_controller.js

وحدة تحكم showArticle طريقة التطبيق / جافا سكريبت / وحدات تحكم / articles_controller.js
showArticle(e) {

  //      
  const xhr = e.detail[2];

  //    
  this.showFormTarget.innerHTML = xhr.responseText;

  //  
  this.showFormTarget.style.display = "block";
}


ماذا بعد؟


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

قم ببناء تطبيقات الويب باستخدام أدوات تطوير Fullstack الحديثة والسريعة مع إطار Ruby on Rails واستمتع بها!

All Articles