Ein neuer Blick auf die Fullstack-Entwicklung mit dem Ruby on Rails-Framework

Ist es möglich, die Fullstack-Entwicklung ernsthaft zu diskutieren? Wenn Sie auf große Frameworks für das Frontend und das Backend schauen, ist es zweifelhaft, über Fullstack zu sprechen. Ich schlage vor, den Begriff fullstackaus der Sicht von Ruby on Rails und den früheren einfacheren Prinzipien der Implementierung von Interaktivität auf klassischen Webseiten zu betrachten. Ich präsentiere Ihnen einen Überblick über die Frontend-Funktionen, die im Ruby on Rails-Framework bereitgestellt werden oder damit zusammenhängen.

Bild


Ruby on Rails ist ein MVC-Framework, das sich auf eine schnelle Entwicklung konzentriert und viel Wert darauf legt, die Konsistenz innerhalb eines Projekts aufrechtzuerhalten (damit es nicht „sowieso“ „schnell“ wird). Es bietet viele Tools für die Backend- und Frontend-Entwicklung. In der klassischen Fullstack-Richtung gab es eine vorübergehende Auslassung aufgrund der Unkenntnis der Entwicklung und des Missverständnisses über die Verzögerung der verwendeten Mittel. Das Ziel dieses Artikels ist es hervorzuheben, wie sich der Fullstack-Ansatz entwickelt und wie viele verschiedene interessante Möglichkeiten darin erschienen sind.

Webpacker


Webpacker ist ein Juwel, das mit Ruby on Rails geliefert wird.

Webpacker bietet einen Wrapper über Webpack: Befehle zum Verbinden und Starten von Konfigurationen für die Arbeit. Webpacker setzt de facto den Standard für die Arbeit mit Frontend in Ruby on Rails, fördert die Verwendung der neuesten JavaScript-Funktionen und moderner Prinzipien für die Arbeit mit Code (Struktur, Modularität, Assembly und vieles mehr).

Webpacker definiert die allgemeinen Konfigurationen, die für den Einstieg erforderlich sind, und die Struktur der Anwendung, wodurch die Sicherheit erhöht und das Verständnis des Projekts für verschiedene Entwickler vereinfacht wird. Für den JavaScript-Code wird der Ordner app/javascript/mit der Primärdatei zugewiesen app/javascript/packs/application.js.

Von Webpacker hinzugefügte Dateien und Ordner
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 startet standardmäßig beim Erstellen einer neuen Anwendung und führt die Einstellungen durch. Sie können die Anwendung sofort mit zusätzlichen Konfigurationen für Stimulus, Vue, Typescript oder eine andere aus der bereitgestellten Liste erstellen :

rails new myapp --webpack=stimulus

Oder installieren Sie nach dem Erstellen der Anwendung weitere Konfigurationen:

bundle exec rails webpacker:install:stimulus

Entwickeln Sie das Frontend mit dem Ruby on Rails-Framework = Verwenden Sie die aktuellsten JavaScript-Entwicklungsansätze. Der Komfort moderner JavaScript-Standards ist in Ruby on Rails gut integriert. Für die Arbeit mit Webpack werden die erforderlichen Konfigurationen bereitgestellt, sodass Sie weniger von der richtigen Organisation des Projekts abgelenkt werden und sich auf die Lösung beliebter Aufgaben in der vertrauten Umgebung konzentrieren können.

Turbolinks


Turbolinks ist die JavaScript-Bibliothek, die mit Ruby on Rails geliefert wird.

Die vorrangige Aufgabe von Turbolinks besteht darin, die Belastung des Servers zu verringern und die „Nähte“ beim Navigieren zu Anwendungs-URLs zu reduzieren. Diese Funktion wird häufig mit SPA verglichen, da sie den Eindruck einer erneuten Darstellung von Inhalten im Browser erweckt, anstatt nur einfache Übergänge zwischen Seiten.

Funktionsprinzip von Turbolinks: Navigieren zwischen Seiten, nicht durch standardmäßiges Umschalten auf eine neue Adresse, sondern durch Erfüllen einer Anforderung an diese Adresse „im Hintergrund“ über Ajax, Laden der Antwort in JavaScript und Ersetzen des Seiteninhalts durch eine neue. Dieser Prozess wird von speziellen Ereignissen begleitet, mit denen Sie dem Übergang zwischen Seiten Funktionen hinzufügen und zu vorherigen Seiten zurückkehren können. Zum Beispiel,
  • um den Übergang zu einer anderen Adresse zu starten : turbolinks:click, turbolinks:before-visit, turbolinks:visit;
  • oder die Bearbeitung einer Anfrage für eine neue Seite : turbolinks:request-start, turbolinks:request-end;
  • oder beim Anzeigen einer neuen Seite turbolinks:before-render, turbolinks:render, turbolinks:load.

Darüber hinaus verfügt Turbolinks über einen Fortschrittsbalken, speichert den Verlauf geladener Seiten im Cache und ermöglicht es Ihnen, nicht aktualisierte Seitenelemente anzugeben.

Aktionskabel


ActionCable ist Teil des Ruby on Rails-Frameworks. ActionCable ermöglicht das Arbeiten mit Web-Sockets. Zur Liste Kanäle auf dem Server einen Ordner app/channels/mit primären Dateien channel.rbund wird zur Verfügung gestellt connection.rb. Um die Verbindung zu diesen Kanälen zu implementieren - ein Ordner app/javascript/channels/mit Dateien index.jsund consumer.js.

Es ist besser, sich sofort anhand eines Beispiels mit den Möglichkeiten von ActionCable vertraut zu machen. Die einfachste Verbindung zu Web-Sockets mit ihrer Hilfe kann in nur wenigen Schritten implementiert werden.

  1. Kanaldatei erstellen

    app / canal / hello_channel.rb
    # app/channels/hello_channel.rb
    class HelloChannel < ApplicationCable::Channel
      def subscribed
        stream_from "hello_1"
      end
    end
    

  2. Erstellen Sie ein Abonnement für diesen Kanal
    app / javascript / channel / 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}!`
      }
    })
    


Und die Verbindung zu den Web-Sockets ist bereit.

Um dies zu überprüfen, benötigen wir eine einfache Seite und eine Aktion zum Versenden. Erstellen Sie dazu einen Controller und fügen Sie dessen Adressen zu den Routen hinzu

app / controller / 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 / route.rb
# config/routes.rb
get "/hello" => "hello#index"
get "/hello/new" => "hello#new"


Wir starten die Anwendung, gehen zur Adresse 127.0.0.1haps000 / hallo und öffnen die Browserkonsole. Darin können Sie die Protokollierung von Nachrichten sehen, die vom Server über Web-Sockets kommen.

Als nächstes senden wir eine Anfrage für Action Mailing:

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

Schauen Sie sich die Seite / hello und die Ausgabe in der Konsole an.

Form Helfer und Rails-ujs


Bemerkenswert sind einige nicht neue, aber gut etablierte Funktionen des Ruby on Rails-Frameworks. Unter ihnen sind Helfer für Darstellungen und Formen. Der anfängliche Vorteil von Helfern besteht darin, dass sie die Integration von Markups in Modelle, Konfigurationen und andere Backend-Komponenten erleichtern. Der Vorteil von Formularhelfern gegenüber herkömmlichen Markups besteht in der Möglichkeit, Formularfelder schnell aufzulisten, ohne auf die Details ihrer Bindung an Modellattribute einzugehen. Mithilfe von Helfern wird die Beziehung zwischen ihnen automatisch hergestellt. Ein Fragment, das ein Beispiel für das Binden von Formularfeldern mit Controller-Parametern und Modellattributen zeigt:

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


app / controller / 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


Mehr über dieses Beispiel erfahren Sie hier und hier .

Rails-ujs


Rails-ujs ist der Kern des Ruby on Rails-Frameworks für unauffälliges JavaScript.
Rails-ujs bietet verschiedene zusätzliche Optionen für Seitenelemente, die ihre Funktionsweise ändern oder erweitern.

Remote-Option - Entwickelt für Elemente, die auf den Server zugreifen (Links, Formulare), um Anforderungen asynchron zu machen. Linkbeispiel:

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

Um die Ergebnisse dieser Abfrage anzuzeigen, sind zusätzliche Manipulationen erforderlich, z. B. das Hinzufügen eines Handlers zu Remote-Ereignissen : ajax:success, ajax:error, ajax:complete.

Mit der Bestätigungsoption können Sie eine Bestätigung der Aktion anfordern, bevor sie ausgeführt wird.

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


Option Deaktivieren_mit - Ermöglicht das Deaktivieren eines Elements nach einer Aktion
<%= form.submit data: { disable_with: "..." } %>

Darüber hinaus verfügt Rails-ujs über mehrere praktische Funktionen. Hier einige davon:

Rails.fire(obj, name, data)- Ereignisaufruffunktion
Rails.ajax(options)- Wrapper über XMLHttpRequest
Rails.isCrossDomain(url)- Überprüfung der URL einer anderen Domäne
Rails.$(selector)- Wrapper über document.querySelectorAll Sie können

sie mit dem Befehl mit Ihrem Code verbinden

import Rails from "@rails/ujs"

Stimulus


Stimulus - JavaScript-Framework von Ruby on Rails-Entwicklern.

Stimulus ist eines der seltenen Frameworks und auf seine Weise einzigartig, da es die Frontend-Entwicklung mithilfe neuer JavaScript-Ansätze implementiert, während es nicht versucht, alle Ihre Aktionen zu steuern, und Sie nicht zwingt, das Frontend vom Backend zu trennen.

Die grundlegende Aufgabe von Stimulus besteht darin, Handler an Ereignisse zu binden. Laut Stimulus muss der Quellcode in Controller-Klassen platziert werden, und ihre Methoden sollten als Handler verwendet werden. Standardmäßig wird der Ordner app/javascript/controllers/mit der Primärdatei für Stimulus-Controller im Projekt zugewiesen index.js. Hier können wir unsere Controller hinzufügen, dafür müssen wir eine Datei mit einem Suffix erstellen _controller.js, zum Beispielarticles_controller.js. Als nächstes importiert der Stimulus Loader solche Dateien und verbindet die Controller mit den entsprechenden Blöcken auf unseren Seiten.

Die Controller in Stimulus verfügen über zusätzliche Ausrüstung: Initialisierung des Controller-Objekts ( initialize), Helfer für den Zugriff auf Elemente innerhalb des Blocks ( targets, Ziele), Anhängen des Controller-Objekts an den Block ( connect) und Trennen von ihm ( disconnect), Zugriff auf die Datenattribute des Blocks ( this.data.get). Das Folgende ist ein Beispiel für einen aktiven / inaktiven Stateful-Block, der in Stimulus geschrieben wurde.

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 / controller / 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";
  }
}


Trotz der Beibehaltung der alten Prinzipien für die Implementierung interaktiver Funktionen auf klassischen Seiten wurde der Entwicklungsansatz mit Stimulus erheblich verbessert: Die Struktur des Quellcodes wird neu strukturiert, die Bindung von Handlern an Ereignisse wird geändert und zusätzliche Ausrüstung wird bereitgestellt. Dank dieser Annehmlichkeiten und seiner Einfachheit können Sie mit dem Stimulus-Framework auch ein großes Frontend schnell und kompetent strukturieren.

Darüber hinaus ist hervorzuheben, dass sich Stimulus gut mit anderen Ruby on Rails-Funktionen kombinieren lässt - nützliche Funktionen sind in fast jedem Bundle enthalten.

Stimulus und Webpacker


Webpacker bietet Befehle zum Erstellen einer Anwendung mit einem verbundenen Stimulus:

rails new myapp --webpack=stimulus

Oder um es mit einem bereits erstellten Projekt zu verbinden:

bundle exec rails webpacker:install:stimulus

Stimulus und JavaScript


Stimulus fördert die Verwendung moderner JavaScript-Entwicklungsprinzipien, um Interaktivität auf Ihren Seiten zu implementieren. Mit Stimulus wird die Frontend-Lösung modular aufgebaut, OOP wird für Ereignishandler verwendet und der Code ist sorgfältig strukturiert. Mit dem Targeting-Tool und Stimulus-Controllern können Sie bequem die Verbindung zu den Blockelementen komplexer Grafikkomponenten steuern, die aus Bibliotheken von Drittanbietern stammen oder unabhängig voneinander geschrieben wurden (Kalender, Auto-Compiler, Listen, Bäume und andere). Dank dessen ist Stimulus eine der einfachsten Möglichkeiten, von veralteten Frontend-Tools zu wechseln und durch die Verwendung von modernem reinem JavaScript die erforderliche Produktivität zu erzielen.

Stimulus und Ruby on Rails


Mit der von Stimulus empfohlenen Codestruktur schreiben Sie weiterhin in JavaScript wie in Ruby on Rails. Sie deklarieren auch Controller und binden Aktionen an Methoden. Mit Stimulus ähnelt die Frontend-Entwicklung dem Backend, was es einfacher macht, sowohl dort als auch dort zu arbeiten.

Stimulus und ActionCable


Mit den Initialisierungs- und Verbindungsmethoden in Stimulus-Controllern ist es praktisch, Web-Sockets nicht an die gesamte Seite, sondern an die einzelnen Blöcke zu binden und präzise mit eingehenden Nachrichten zu arbeiten. Es wird immer einfacher, mehrere parallele Streams auf einer Seite mit unabhängiger Kanalumschaltung zu organisieren.

Reiz und Turbolinks


Der Stimulus wird aktiviert, sobald Turbolinks die Seite lädt. Es sind keine zusätzlichen Manipulationen erforderlich, um den Stimulus mit den Blöcken der Seite zu verbinden.

Turbolinks erleichtern nicht nur das Laden von Seiten, sondern speichern deren Inhalt auch beim Übergang zwischen. Wenn Sie aus dem Verlauf zur zwischengespeicherten Seite zurückkehren, wird Stimulus automatisch aktiviert, wie beim Laden einer neuen Seite. Wenn Sie einige Werte speichern möchten, bevor Sie den Controller vom Gerät trennen, können Sie die Methode verwenden. Wenn Sie den Controller zurückgeben disconnectund anschließen, kann er seinen letzten Status wiederherstellen. Im Code des ersten Beispiels für die Arbeit mit Stimulus können Sie sehen, wie beim Trennen ( disconnect) der Wert im Datenattribut des Controller-Blocks festgelegt this.activeund beim Verbinden ( connect) zurück extrahiert wird.

Das Zurückblättern durch Seiten kann eine nützliche Möglichkeit sein, mit der Anwendung zu arbeiten. Wenn Sie beispielsweise mit einem Formular arbeiten, müssen Sie möglicherweise den Wert im Verzeichnis auf einer anderen Seite eingeben / bearbeiten, dann zurückkehren und neue Daten auswählen.

Ein weiteres Beispiel: Angenommen, wir müssen die Werte auf der Seite mit den Webchat-Einstellungen bearbeiten oder anzeigen. Wenn wir den Controller während des Gesprächs vom Gerät trennen, ist es hilfreich, sich die Kennung der letzten Nachricht zu merken. Wenn Sie zurückkehren, fordern Sie zuerst die fehlenden neuen Nachrichten an und öffnen Sie dann die Verbindung über Web-Sockets.

Daher kann eine Rückkehr zum Seitenverlauf als bequeme Möglichkeit zur Arbeit mit Ihrer Webanwendung verwendet werden.

Reiz- und Helferformen


Stimulus arbeitet eng mit dem Markup zusammen und mithilfe von Helfern können Daten leicht in HTML-Blöcke eingebettet werden. Dank dieser Funktion kann ein Teil der Daten in das Datenattribut des Blocks geladen und an den Controller übermittelt werden.

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 / controller / articles_controller.js (Snippet)
//   
//   initialize  app/javascript/controllers/articles_controller.js
initialize() {
  this.attributes = JSON.parse(this.data.get("attributes"));
  //   
  // ...
}


Stimulus und Rails-Ujs


Mit Stimulus und Remote-Optionen können Sie Controller direkt mit Ajax-Ereignissen verbinden und Abfrageergebnisse verarbeiten. Deklarieren Sie den Link mit Rails-ujs und fügen Sie einen Stimulus-Handler hinzu.

Verbindung mit Remote-Option und Stimulus-Handler
<%= link_to " ",
  article_path(article, format: :html),
  data: { remote: true, action: "ajax:success->articles#showArticle" } %>


Wenn Sie auf diesen Link klicken, wird eine asynchrone Ajax-Anforderung an den Rails-Controller articles_controller.rbfür die Show-Aktion gesendet . Nach Erhalt einer positiven Antwort wird ein Ereignis ausgelöst ajax:successund die Methode showArticlevom Controller aufgerufenapp/javascript/controllers/articles_controller.js

controller showArticle Methode app / javascript / controller / articles_controller.js
showArticle(e) {

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

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

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


Was weiter?


Diese Tools eröffnen zusammen mit dem Ruby on Rails-Framework neue Horizonte für die Fullstack-Entwicklung. Darüber hinaus sind die beschriebenen Werkzeuge relativ einfach und erfordern keine langen Tauchgänge - alles, was für ein erfolgreiches Projekt notwendig ist, ist an der Oberfläche.

Erstellen Sie Webanwendungen mit modernen und schnellen Fullstack-Entwicklungstools mit dem Ruby on Rails-Framework und genießen Sie es!

All Articles