Nicht-ActiveRecord-Modelle in Schienen 4

ActiveRecord enthält einen leistungsstarken Satz Validatoren und andere Funktionen für Attribute eines persistenten Datenmodells. Andererseits sind Formulare einer der ältesten und wichtigsten Bausteine ​​heutiger Webanwendungen - eine wichtige Schnittstelle für die Benutzereingabe. Von den zwei Formular-Helfern, die Rails zur Verfügung stellt, geht "form_for" auch davon aus, dass Sie mit einem permanenten Objekt arbeiten. So können alle aktiven Datensatzmerkmale, d. H. Validierungen, voll genutzt werden.

Dies ist ideal für persistente Objekte mit datenbankgestützten Darstellungen. Was passiert jedoch, wenn Sie ein komplexes Formular benötigen, das keinen permanenten Datensatz darstellt??

In diesem Tutorial werde ich über die möglichen Lösungen für dieses Problem und die Implementierung einer Lösung in Rails 4 (Active Models) sprechen..

In diesem Lernprogramm erstellen wir eine Anwendung mit einem Formular, in dem ein Benutzer Feedback hinzufügen kann, das dann in einer Datenbank gespeichert wird. Diese Anwendung verfügt auch über Überprüfungen und Ansichten, genau wie sie sie für ein datenbankgestütztes Modell erstellt haben, aber dann werden wir einige der Änderungen im Modell durchgehen, um es tableless zu machen. Und alle Funktionen müssen so funktionieren, wie sie sind, ohne weitere Änderungen vorzunehmen. Es gibt keine Aktualisierungs-, Lösch- oder Suchaktionen für Feedback.

Das wichtigste zuerst

Für dieses Tutorial gehe ich davon aus, dass Sie ein grundlegendes Verständnis für das Rails-Framework haben und einfache Controller, Modelle und Ansichten erstellen oder generieren können. Ich gehe davon aus, dass Sie auch ein bisschen wissen, wie Routen und Validierungen funktionieren. Zum Zeitpunkt der Erstellung dieses Tutorials habe ich verwendet Schienen 4.2.5 und SQLite 3.8.10.2.

Einführung

Es kann viele Situationen geben, in denen Sie eine Klasse haben möchten, die wie ein typisches ActiveRecord-Modell funktionieren soll, die Daten jedoch nicht in der Datenbank beibehalten möchten. Beispielsweise haben Sie möglicherweise ein Kontaktformular oder etwas komplexeres wie eine Beschwerde- oder Rückmeldungsform. 

Um dieses Problem zu lösen, würde man in diesen Situationen die form_tag Helper-Methode, mit der Sie benutzerdefinierte Formularfelder erhalten, die das tun, was Sie benötigen, ohne sie mit einem beliebigen Modell binden zu müssen.

Das funktioniert gut, aber form_tag Wenn Sie mit mehr als ein paar Feldern arbeiten, kann es schnell langweilig werden, zu schreiben und zu warten, da Sie die zahlreichen Attribute und deren Validierungen selbst benennen müssen. In Kürze wird sich Ihr Controller mit einer Menge Logik und Tonnen von Formularparametern beschäftigen, was wahrscheinlich keine ideale Lösung ist.

Ein sauberer, flexiblerer Ansatz wäre, wenn wir dasselbe irgendwie anwenden könnten form_for mit einem Modell und allen Validierungen und anderen Vorteilen, die sie mitbringen, ohne jedoch datenbankgestützte Repräsentationen ihrer Attribute zu benötigen.

Rails bietet genau diese Lösung: die Aktives Modell-Das ist wie ein normales Modell, aber ohne die Tabellen. Es bietet dieselbe einfache Validierungsmethode und fast alle anderen mit ActiveRecord gelieferten Goodies. Es hilft Ihnen dabei, die Anwendungsstruktur konsistent zu halten, da Sie ohnehin Modelle verwenden, um Objekte in Ihrer App darzustellen, Routen kostenlos zur Verfügung stehen und das Erstellen von Formularen genauso einfach ist wie zuvor form_for.

Erstellen wir zuerst eine neue Anwendung

In diesem Schritt erstellen wir eine Dummy-Anwendung, mit der Sie in diesem Lernprogramm herumspielen können.

Schritt 1: Gebäude

Starten Sie Ihr Terminal und geben Sie diese Befehle ein, um eine neue Anwendung zu erstellen:

# Erstellen Sie eine einfache Rails-App. Neue Tableless-CD. Tableless. # Erstellen Sie einen Controller nur mit neuen Funktionen, Create & Success. Aktionsschienen generieren Controller-Rückmeldungen. Neuer Erfolg. --Skip-routen : Zeichenfolge Nachricht: Textvorschlag: Text 

So ist dein Verzeichnisaufbau aussehen wird.

Schritt 2: Bearbeiten

Hier werde ich die Codefragmente für alle Dateien bereitstellen, die Sie füllen müssen. Der Code ist ziemlich selbsterklärend. Sie können diese App entweder aus dem mit diesem Beitrag verknüpften GitHub-Repository herunterladen oder meinen eigenen Schritten folgen, um eine selbst zu erstellen.

→ / config /routen.rb

Ressourcen: Rückmeldungen,: nur => [: Neu,: Erstellen] Get 'Rückmeldungen / Erfolg' => 'Rückmeldungen # Erfolg', als:: Erfolg

→ /app/views/feedbacks/success.html.erb

<%= notice %>


<%= link_to 'Submit New Feedback', new_feedback_path %>

→ / app / ansichten / feedbacks /new.html.erb 

Neues Feedback

<%= form_for(@feedback) do |f| %> <% if @feedback.errors.any? %>

<%= pluralize(@feedback.errors.count, "error") %> das Speichern dieses Feedbacks ist verboten:

    <% @feedback.errors.full_messages.each do |message| %>
  • <%= message %>
  • <% end %>
<% end %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.label :message %>
<%= f.text_area :message %>
<%= f.label :suggestion %>
<%= f.text_area :suggestion %>
<%= f.submit %>
<% end %> <%= link_to 'Back', feedbacks_path %>

→ /app/controllers/feedbacks_controller.rb

Klasse FeedbacksController < ApplicationController def new @feedback = Feedback.new end def create @feedback = Feedback.new(feedback_params) respond_to do |format| if @feedback.save format.html  redirect_to success_path, notice: 'Feedback was successfully submitted.'  else format.html  render :new  end end end def success end private def feedback_params params.require(:feedback).permit(:name, :email, :address, :message, :suggestion) end end

→ / app /Modelle / feedbacks.rb

Klasse Feedback < ActiveRecord::Base # fields validation for the database. validates :name, presence: true validates :email, presence: true, length: in:5… 255 validates :address, presence: true validates :message, presence: true validates :suggestion, presence: true end

Schritt 3: Bereitstellen

Um es auf Ihrem lokalen Server bereitzustellen, müssen Sie zuerst die folgenden Befehle ausführen, um die Datenbank in Ihrem System zu erstellen.

cd tableless / rake db: migrieren 

Wenn Sie dem Lernprogramm bis hierher gefolgt sind, sollte der obige Befehl standardmäßig eine sqlite3-Datenbank erstellen. Um es zu ändern, können Sie zu springen Datenbank.yml-Für dieses Tutorial werde ich mit sqlite3 gehen.

Jetzt laufen Schienen s in Ihrem Terminal und Sie sollten etwas ähnliches sehen.

Und damit sollten Sie eine Dummy-Anwendung erfolgreich ausführen.

Schritt 4: Testen

Jetzt ist es Zeit zu testen, was wir gerade erstellt haben. Klicken Sie in Ihrem Browser auf diese Route, um zu überprüfen, ob alles gut funktioniert: http: // localhost: 3000 / feedbacks / neu

Sie sollten ein Formular wie oben sehen. Drücken Sie nun die Schaltfläche "Senden", ohne ein Feld auszufüllen, um zu prüfen, ob die Validierungen einwandfrei funktionieren.

Großartig. Sie sollten sechs Validierungsfehler wie oben sehen. Jetzt können wir die richtigen Werte ausfüllen und das Formular absenden.

Sie sollten etwas Ähnliches auf Ihrem Bildschirm sehen. Lassen Sie uns die Datenbank nach dem gerade eingegebenen Datensatz überprüfen. 

Öffne deine Terminal, Gehen Sie in Ihr Projektverzeichnis und geben Sie die folgenden Befehle ein.

  • Schienen db um den Datenbank-Client in Ihrer Konsole zu starten.
  • SQLite> .tables Alle Tabellen in Ihrer Datenbank auflisten (DB ist standardmäßig ausgewählt).
  • SQLite> .headers auf anzeigen Spaltennamen in Ihren Ergebnissen.
  • SQLite> * aus Feedbacks auswählen; um alle Rückmeldungen in der Datenbank zu sehen.

Und hier sehen wir, dass das Feedback erfolgreich in der Datenbank gespeichert wurde. Wenn Sie in die Protokolle schauen, finden Sie auch die EINFÜGEN Abfrage.

Und damit ist unser Test beendet. Nun, da alles gut zu funktionieren scheint, kommen wir zur Lösung.

Die Lösung

Schritt 1: Implementierung 

Implementieren Aktives Modell, Als erstes müssen Sie die Vererbung des Feedback-Modells entfernen < ActiveRecord::Base Wir möchten, dass dieses Modell nicht mehr über ein Datenbank-Back-End verfügt. 

Sobald wir dies tun, funktioniert unser Formular nicht mehr, da die Validatoren von ActiveRecord bereitgestellt werden. Aber hinzufügen schließen Sie ActiveModel :: Model ein in der nächsten Zeile sollte alles wiederherstellen.

Ihr Modell sollte jetzt so aussehen.

Die Klasse Feedback umfasst ActiveModel :: Model 

Die zweite Sache ist hinzuzufügen attr_accessor die Getter und Setter für alle Attribute wie diese zu generieren.

attr_accessor: name,: email,: adresse,: nachricht,: vorschlag

Nun sollte das Endergebnis des Modells so aussehen.

Klasse Rückmeldungen umfassen ActiveModel :: Model attr_accessor: Name,: E-Mail,: Adresse,: Nachricht,: Vorschlag # Felder für die Überprüfung der Datenbank. validates: Name, Präsenz: true validiert: E-Mail, Präsenz: true, Länge: in: 5… 255 validiert: Adresse, Präsenz: true validiert: Nachricht, Präsenz: true validiert: Vorschlag, Präsenz: true Ende

Das Fixieren des Modells reicht nicht aus, damit sich unsere App so verhält, wie wir es wollen. Der Controller erwartet weiterhin, das empfangene Datenobjekt in der Datenbank in der Datenbank zu speichern erstellen Methode. @ feedback.save funktioniert nicht, da wir kein Datenbank-Back-End haben, um das neue Feedback zu speichern.

Wir können dieses Problem durch Ändern beheben @ feedback.save in @ feedback.valid? Da wir jetzt nur die Validierungen in unseren Modellen durchführen, können Sie basierend auf diesem Erfolgsereignis jede bevorzugte Aufgabe innerhalb dieses Codeblocks ausführen, d. h. Benachrichtigungen senden, E-Mail senden oder Ereignisse protokollieren usw..

Klasse FeedbacksController < ApplicationController def create @feedback = Feedback.new(feedback_params) respond_to do |format| if @feedback.valid? # Something interesting can be done here # - send notifications # - send email # - log events format.html  redirect_to success_path, notice: 'Feedback was successfully submitted.'  else format.html  render :new  end end end

Schritt 2: Testen

Lassen Sie uns die Tests wiederholen, die wir zuvor durchgeführt haben.

Triff die Route http: // localhost: 3000 / feedbacks / neu und einreichendas Formular, ohne Felder auszufüllen. Alle Validierungen sollten wie zuvor funktionieren.

Großartig. Jetzt können wir es versuchen, indem wir das Formular mit gültigen Werten absenden.

Und hier geht die gleiche Erfolgsmeldung.

Das Letzte, was wir noch prüfen müssen, ist die Datenbank. 

Dafür öffnen Sie Ihre Terminal, Gehen Sie in Ihr Projektverzeichnis und geben Sie die folgenden Befehle ein.

  • Schienen db um den Datenbank-Client in Ihrer Konsole zu starten.
  • SQLite> .tables Alle Tabellen in Ihrer Datenbank auflisten (DB ist standardmäßig ausgewählt).
  • SQLite> .headers auf anzeigen Spaltennamen in Ihren Ergebnissen.
  • SQLite> * aus den Rückmeldungen auswählen um alle Rückmeldungen in der Datenbank zu sehen.

Da dieses Modell nicht mit einer Datenbanktabelle gesichert ist, finden Sie die neu übermittelten Werte nicht in der Tabelle.

Wenn Sie Ihre Konsolenprotokolle überprüfen, wird auch das nicht angezeigt EINFÜGEN mehr fragen.

Fazit

Damit sind wir mit dem fertig ActiveModel, und wir haben gesehen, wie einfach es ist, ein tischloses Modell zu erstellen. ActiveModel ist stark verbessert, so dass Sie in den kommenden Versionen von Rails einige Änderungen erwarten können. 

Wir haben nur die Validierungen und Attributzuweisungen in diesem Lernprogramm verwendet, um die Dinge einfach und übersichtlich zu halten. Schauen Sie sich aber das Verzeichnis an, das den Code für ActiveModel auf GitHub enthält.

Aus der Liste ist ersichtlich, dass ActiveModel unter anderem Klassen für Attributmethoden, Serialisierung, Rückrufe und Dirty-Tracking enthält. So behalten Sie die kommenden Funktionen im Auge und machen Sie sich auch mit anderen vertraut.