Rails 6-Funktionen: Was ist neu und warum es wichtig ist
Veröffentlicht: 2022-03-11Wie die meisten Ruby on Rails-Fans vielleicht wissen, kommt Rails 6 bald und bringt eine Reihe von mit Spannung erwarteten Funktionen und Änderungen mit sich. Das Ziel dieses Artikels ist es, Sie mit den wichtigsten Funktionen vertraut zu machen, die Rails 6 hinzugefügt wurden, und zu skizzieren, wie sie dazu beitragen können, Ihre Anwendungen zu verbessern und so wertvolle Entwicklungszeit zu sparen.
Denken Sie zunächst daran, dass Rails 6 Ruby 2.5+ und aktualisierte Datenbanken erfordert. Stellen Sie also sicher, dass Sie einen Plan haben, um Ihre Systeme entsprechend zu aktualisieren, falls Sie dies noch nicht getan haben.
Was sind diese neuen Funktionen? Hier ist eine kurze Zusammenfassung der wichtigsten Funktionen von Rails 6, die Sie wahrscheinlich in Zukunft verwenden werden:
Testen in Rails 6
Als professionelle Ruby on Rails-Entwickler möchten wir eine maximale Abdeckung für unseren Code sicherstellen. Das Testen wird jedoch zu einer mühsamen Aktivität, wenn unsere Testfälle „schwer“ werden und wir mehrere Minuten oder sogar Stunden warten müssen, nur um die Testfälle auszuführen.
Paralleles Testen
Nun, Rails 6 hat hier eine Antwort. Es hat dem ActiveSupport::TestCase
eine parallelize
hinzugefügt, die es Ihnen ermöglicht, die Testsuite mit gegabelten Prozessen zu parallelisieren.
Was Sie also tun müssen, um die Prozesse für Ihre Tests zu parallelisieren, ist Folgendes zu Ihrer test_helper.rb
:
parallelize(workers: 2)
Alternativ können wir unsere bisher verwendeten Befehle zum Ausführen von Tests ersetzen. Beispielsweise kann bin/rails test OR bin/rspec spec
jetzt durch PARALLEL_WORKERS=15 rails test OR PARALLEL_WORKERS=15 rspec spec
ersetzt werden.
Dementsprechend können Sie die Befehle zum Ausführen der Testsuiten auf verschiedenen CI-Plattformen wie Travis, Gitlab, CircleCI und anderen ändern.
Es gibt auch Hooks, wenn jeder Prozess erstellt/zerstört wird, die wie folgt verwendet werden können:
class ActiveSupport::TestCase parallelize_setup do |worker| # setup databases end parallelize_teardown do |worker| # cleanup databases end parallelize(workers: :number_of_processors) end
Hinweis: Wenn Sie mehr erfahren möchten, können Sie sich die Rails Guides für weitere Details ansehen.
Aktion Kabeltest
Da wir über effizientes Testen gesprochen haben, lassen Sie uns auch verstehen, wie sich Action Cable, eine der hervorstechendsten Funktionen von Rails 5, verbessert hat. Jetzt ist es möglich, Action Cable auf jeder Ebene zu testen: Verbindungen , Kanäle und Sendungen .
Verbindungstests zielen darauf ab, zu überprüfen, ob die Kennungen einer Verbindung richtig zugewiesen werden oder dass alle unzulässigen Verbindungsanforderungen abgelehnt werden:
class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase test "connects with params" do connect params: { user_id: 42 } OR cookies.signed[:user_id] = "42" connect assert_equal connection.user_id, "42" end test "rejects connection without params" do assert_reject_connection { connect } end end
Kanaltests können geschrieben werden, um zu überprüfen, ob Benutzer Kanäle abonnieren können und der Kanal einen Stream hat:
class ChatChannelTest < ActionCable::Channel::TestCase test "subscribes and stream for room" do # Simulate a subscription creation by calling `subscribe` subscribe room: "15" # You can access the Channel object via `subscription` in tests assert subscription.confirmed? assert_has_stream "chat_15" end end
Das Senden an Kanäle kann wie folgt getestet werden:
# app/jobs/chat_relay_job.rb class ChatRelayJob < ApplicationJob def perform_later(room, message) ChatChannel.broadcast_to room, text: message end end # test/jobs/chat_relay_job_test.rb require 'test_helper' class ChatRelayJobTest < ActiveJob::TestCase include ActionCable::TestHelper test "broadcast message to room" do room = rooms(:all) assert_broadcast_on(ChatChannel.broadcasting_for(room), text: "Hi!") do ChatRelayJob.perform_now(room, "Hi!") end end end
Hinweis: Weitere Tipps zum Testen finden Sie hier.
Bulk Insert und Upsert
Irgendwann müssen wir alle mehrere Datensätze auf einmal einfügen und haben dabei viele Problemumgehungen gefunden. Nun, Rails 6 kommt mit einer neuen Methode aus der Box – insert_all
, ähnlich wie update_all
.
Es löst keine Rückrufe aus und führt eine einzelne SQL-Abfrage aus. Es gibt eine zusätzliche Methode upsert_all
, mit der Sie die Upsert-Operation verwenden können, die von vielen modernen Datenbanken wie Postgres bereitgestellt wird. Jetzt können Sie Ihre Einfügeabfragen reduzieren und Ihren Code optimieren. Verabschieden Sie sich auch von zuvor verwendeten Juwelen wie activerecord-import
.
Eine einzelne INSERT
SQL-Abfrage wird durch diese Methoden vorbereitet, und eine einzelne SQL-Anweisung wird an die Datenbank gesendet, ohne das Modell zu instanziieren oder Active Record-Callbacks und -Validierungen aufzurufen. Es ist auch möglich, Kriterien zu definieren, wenn ein Primärschlüssel – eindeutige Indizes oder eindeutige Einschränkungen – verletzt werden, mit einer Option zum Überspringen oder Ausführen von Upsert-Abfragen.
Einige Beispiele sind unten:
result = Article.insert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, #...snip... ], returning: %w[ id title ], unique_by: :index_articles_on_title_and_author ) result = Article.upsert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, { id: 1, .... }, # duplicate 'id' here { id: 2, .... }, { id: 3, .... }, # duplicate 'title' and 'author' here { id: 4, .... }, { id: 5, .... }, # duplicate 'slug' here { id: 6, .... } ] )
Die Methoden insert
, insert!
und upsert
sind Wrapper um insert_all
, insert_all!
bzw. upsert_all
.
Hinweis: Es gibt einen sehr guten Artikel, der Massenabfragen in Bezug auf verschiedene Datenbanken behandelt. Wenn Sie zusätzliche Informationen benötigen, schauen Sie sich diese unbedingt an.
Wechseln zwischen mehreren Datenbanken
Eines der Hauptfeatures, das viele große Anwendungen zu schätzen wissen, ist dieses: Rails 6 hat endlich Unterstützung für mehrere Datenbanken für Ihre Anwendung hinzugefügt, eingebaut und sofort einsatzbereit!
Natürlich haben Sie weiterhin die Wahl beim Design, ob Sie Ihre Anwendung in mehrere Microservices aufteilen möchten, von denen jeder eine separate Datenbank hat, oder einen monolithischen Weg einschlagen oder mehrere Read Replicas für Ihre Anwendung hinzufügen möchten.
Die Möglichkeit, dies auf so einfache Weise zu tun, hat jedoch das Potenzial, viel Zeit an der Entwicklungsfront zu sparen.
So sieht also Ihre neue database.yml
-Datei aus:
development: primary: database: my_primary_db user: root primary_replica: database: my_primary_db user: ro_user replica: true animals: database: my_animals_db user: root animals_replica database: my_animals_db user: ro_user replica: true
Hier sind interessante Möglichkeiten, um festzulegen, wie auf verschiedene Datenbanken umgeschaltet werden soll:
class AnimalsModel < ApplicationRecord self.abstract_class = true connects_to database: { writing: :animals_primary, reading: :animals_replica } end class Dog < AnimalsModel # connected to both the animals_primary db for writing and the animals_replica for reading end
Hier ist die offizielle GitHub-Seite, die ebenfalls gut dokumentiert ist. Persönlich freue ich mich darauf, in zukünftigen Rails-Updates auch Datenbank-Sharding-Funktionen zu haben (etwas in der Art).
Aktionspostfach
Ein weiteres interessantes Feature von Rails 6 ist das Hinzufügen von Action Mailbox, das die Möglichkeit hinzufügt, eingehende E-Mails wie Postfächer zur Verarbeitung in Rails an den Controller weiterzuleiten.
Action Mailbox bietet Eingänge für Mailgun, Mandrill, Postmark und SendGrid. Sie können eingehende E-Mails auch direkt über integrierte Exim-, Postfix- und Qmail-Eingänge verarbeiten. Jetzt können Sie sich wahrscheinlich die potenziellen Vorteile vorstellen, ohne näher darauf eingehen zu müssen. Es kann E-Mails von einem Helpdesk direkt verarbeiten, um Support-Tickets zu automatisieren – Rails 6 ermöglicht es Kunden, direkt per E-Mail zu antworten, und vieles mehr. Es steht Ihnen offen, diese Funktion zu erkunden und einen Ansatz zu finden, der für Ihre Anwendung ideal ist.

Hier ist ein kleines Beispiel, um zu verstehen, wie man Action Mailbox verwendet:
COMMENTS_REGEX = /^comment\+(.+)@example\.com/i # app/mailboxes/application_mailbox.rb class ApplicationMailbox < ActionMailbox::Base routing COMMENTS_REGEX => :comments end # app/mailboxes/comments_mailbox.rb class CommentsMailbox < ApplicationMailbox def process user = User.find_by(email: mail.from) post_uuid = COMMENTS_REGEX.match(mail.to)[1] post = Post.find_by(uuid: post_uuid) post.comments.create(user: user, content: mail.body) end end
Außerdem sieht die neue Art der E-Mail-Konfiguration wie folgt aus (am Beispiel von Sendgrid):
# config/environments/production.rb config.action_mailbox.ingress = :sendgrid
Verwenden Sie rails credentials:edit
, um das Passwort zu den verschlüsselten Anmeldeinformationen Ihrer Anwendung unter action_mailbox.ingress_password
, wo Action Mailbox es automatisch findet:
action_mailbox: ingress_password: …
Konfigurieren Sie SendGrid Inbound Parse, um eingehende E-Mails mit dem Benutzernamen actionmailbox
und dem zuvor generierten Passwort an /rails/action_mailbox/sendgrid/inbound_emails
weiterzuleiten. Wenn sich Ihre Anwendung unter https://example.com
befindet, würden Sie SendGrid mit der folgenden URL konfigurieren:
https://actionmailbox:[email protected]/rails/action_mailbox/sendgrid/i
Falls Sie dies weiter untersuchen möchten, hat Rails hier bereits eine Anleitung dazu.
Zeitwerk
Zeitwerk ist der neue Code-Loader für Ruby. Bei einer herkömmlichen Dateistruktur lädt Zeitwerk die Klassen und Module Ihres Projekts nach Bedarf, sodass Sie keine require-Aufrufe für Ihre eigenen Dateien schreiben müssen. Um es in Rails 6 zu aktivieren, können Sie Folgendes tun:
config.autoloader = :zeitwerk
Mehr über Zeitwerk erfahren Sie hier.
Optimierer-Tipps
Sie befürchten, dass die Ausführung einiger Ihrer Abfragen zu lange dauert? Nun, jetzt haben Sie auch die Möglichkeit, Zeitüberschreitungen für Ihre Abfragen zu definieren.
Die folgende Anweisung löst eine StatementTimeout
-Ausnahme aus, wenn die Ausführung der Abfrage länger als normal dauert:
User.optimizer_hints("MAX_EXECUTION_TIME(5000)").all
Es wird von MySQL unterstützt und Sie müssen herausfinden, ob Ihre Datenbank es unterstützt.
Datenbank abschneiden
Was ist mit Seeding-Daten? Die folgende Anweisung kürzt alle Ihre Datenbanktabellen und Sie können dann mit dem Seeding Ihrer Daten fortfahren:
rails db:truncate_all
Sie brauchen Ihre Datenbanken nicht mehr zu Seed zu löschen. Sie werden wahrscheinlich zustimmen, dass dies eine elegante und schnelle Lösung ist.
Aktionstext
Vielleicht ist ein weiteres bemerkenswertes Feature für viele Anwendungen, die mit WYSIWYG-Editoren spielen, die Unterstützung für den Trix-Editor, der nativ in Rails 6-Anwendungen integriert ist. Dies wird sicherlich eine gute Aufrüstung/Ergänzung für viele Projekte sein.
Die meisten WYSIWYG-HTML-Editoren haben einen enormen Umfang – die Implementierung jedes Browsers hat seine eigenen Bugs und Macken, und JavaScript-Entwickler müssen die Inkonsistenzen beseitigen. Trix umgeht diese Inkonsistenzen, indem es contenteditable
als E/A-Gerät behandelt: Wenn Eingaben ihren Weg zum Editor finden, wandelt Trix diese Eingaben in einen Bearbeitungsvorgang in seinem internen Dokumentmodell um und rendert das Dokument dann erneut in den Editor. Dies gibt Trix die vollständige Kontrolle darüber, was nach jedem Tastendruck passiert.
Installation:
rails action_text:install # app/models/message.rb class Message < ApplicationRecord has_rich_text :content end
Sie können Action Text in der offiziellen Dokumentation hier ausführlicher untersuchen.
Sicherheit
Kein ernsthaftes Upgrade ist ohne einige Sicherheitsverbesserungen vollständig. Rails 6 enttäuscht auch nicht an der Sicherheitsfront. Das erste nennenswerte Sicherheits-Upgrade ist die Unterstützung für die Host-Autorisierung .
Die Host-Autorisierung ist eine neue Middleware, die vor DNS-Rebinding-Angriffen schützt, indem sie explizit zulässt, dass eine Anfrage an die Hosts gesendet werden kann. Das bedeutet, dass Sie die Hosts definieren können, die auf Ihre Anwendungen zugreifen können.
Ein weiteres Sicherheits-Upgrade soll Angriffe vereiteln, die versuchen, den signierten/verschlüsselten Wert eines Cookies zu kopieren und ihn als Wert eines anderen Cookies zu verwenden. Dazu wird der Cookie-Name im Zweckfeld gespeichert, das dann zusammen mit dem Cookie-Wert signiert/verschlüsselt wird. Dann überprüfen wir beim serverseitigen Lesen die Cookie-Namen und verwerfen alle angegriffenen Cookies. action_dispatch.use_cookies_with_metadata
, um diese Funktion zu verwenden, die Cookies mit eingebetteten neuen Zweck- und Ablauf-Metadaten schreibt.
Webpack als Standard-Bundler
Wie es bei vielen modernen JavaScript-Frameworks für die Frontend-Entwicklung der De-facto-Standard ist, hat Rails 6 Webpack als Standard-JavaScript-Bundler über das Webpacker-Gem hinzugefügt und die Rails-Asset-Pipeline ersetzt. Dies ist eine relativ einfache Ergänzung, und wir werden nicht sehr ins Detail gehen. Es genügt zu sagen, dass Webpack überarbeiteten Front-End-Entwicklern etwas Erleichterung bringen wird.
Race Conditions verhindern
Rails 6 hat eine neue Methode, die verwendet wird, um SELECT/INSERT-Rennbedingungen in unserem Code zu verhindern (ich bin sicher, dass viele Leser das Pech hatten, auf Rennbedingungen zu stoßen, während sie ihr Projekt skalieren). Hier ist der GitHub-Thread, falls Sie zusätzliche Informationen benötigen.
In der zugrunde liegenden Tabelle müssen die relevanten Spalten mit eindeutigen Einschränkungen definiert sein. Während wir die Race-Bedingung zwischen SELECT → INSERT von #find_or_create_by
, haben wir tatsächlich eine andere Race-Bedingung zwischen INSERT → SELECT, die ausgelöst werden kann, wenn ein DELETE zwischen diesen beiden Anweisungen von einem anderen Client ausgeführt wird. Aber für die meisten Anwendungen ist dies eine Bedingung, die wir mit erheblich geringerer Wahrscheinlichkeit treffen werden.
Anmeldeinformationen in Rails 6
Seit den Tagen von Rails 5.2 wurden Credentials als neuer „Rails-Weg“ bezeichnet, um mit sensiblen Informationen umzugehen, mit dem Versprechen, berüchtigte .env- Dateien ein für alle Mal loszuwerden. Mit Credentials können verschlüsselte Schlüssel für Drittanbieterdienste direkt in die Quellcodeverwaltung eingecheckt werden.
Bisher verwendete Rails jedoch für alle Umgebungen dieselbe verschlüsselte Datei, was den Umgang mit unterschiedlichen Schlüsseln in Entwicklung und Produktion etwas schwierig machte, insbesondere bei großen Projekten und Legacy-Code.
In Rails 6 wird dies endlich durch die Unterstützung von umgebungsspezifischen Anmeldeinformationen gelöst. Auch hier können weitere Details im offiziellen GitHub-Thread nachgelesen werden.
Ist Rails 6 ein gutes Update?
Ja, und tatsächlich könnte Rails 6 als großes Update bezeichnet werden, obwohl nur wenige es als Game-Changer bezeichnen würden. Da es Ruby on Rails schon seit Jahren gibt, erwarten nur wenige Leute revolutionäre Veränderungen, aber seine sechste Inkarnation bringt viel auf den Tisch.
Einige Funktionen, die in Rails 6 eingeführt wurden, scheinen kleine Verbesserungen zu sein, während andere das Potenzial haben, viel Entwicklungszeit zu sparen, die Sicherheit, Robustheit und so weiter zu verbessern. Fazit: Rails ist ausgereift, viele Entwickler sind von seiner Zukunft begeistert, und mit der Veröffentlichung von Rails 6 wurde es noch besser.
Natürlich ist diese Liste der Rails 6-Funktionen unvollständig, und um den vollständigen Satz von Änderungen anzuzeigen, müssen Sie sich das Änderungsprotokoll ansehen. Darüber hinaus gibt es eine Menge Abschreibungen, die Sie beachten sollten. Wenn Sie schließlich darauf bestehen, jede einzelne Änderung durchzugehen und sich selbst zu aktualisieren, lesen Sie bitte die vollständigen Versionshinweise.