Verwendung von Faye als Echtzeit-Push-Server in Rails

Es gibt mehrere Möglichkeiten, einer Anwendung eine Push-Funktionalität hinzuzufügen, einschließlich Pushr und Pub-Nub, die recht elegante und einfache Lösungen darstellen. Es gibt auch einige erweiterte Optionen. In diesem Artikel werde ich Ihnen zeigen, wie Sie Faye verwenden, ein Messagingsystem, das sowohl auf Ruby als auch auf Node.js ausgeführt wird.


Schritt 1 - Bereite alles vor

Wir bauen einen einfachen Chat-Service. Jetzt hat Ryan Bates auf Railscast # 260 darüber berichtet. In diesem Tutorial werden wir jedoch etwas anders vorgehen. Zunächst erstellen wir einen Chat-Service, bei dem Benutzer einen öffentlichen Raum betreten und jeder öffentlich miteinander chatten kann. Die zweite Funktionalität, die wir hinzufügen werden, sind private Nachrichten. Darüber hinaus integrieren wir einige Sicherheitsaspekte in unsere Implementierung, indem wir das private_pub gem von Ryan Bate verwenden.

Stellen Sie sicher, dass Sie über ein funktionierendes Setup von Ruby und Ruby on Rails 3.1 verfügen. Abgesehen davon brauchen Sie dünn. Thin ist ein weit verbreiteter Ruby-Webserver, der von Faye ausgeführt werden muss (er funktioniert nicht mit dem eingebauten WEBrick-Server von Rails). Sie können Thin wie folgt installieren:

gem installieren dünn

Wir sollten fertig sein, also erstellen wir die Anwendung:

Schienen neues Faye-Tutorial

Nun füge das hinzu Faye Juwel zu Ihrem Gemfile:

 Juwel 'Faye'

und Renn Bundle installieren um es zu installieren. Faye muss auf einem separaten Webserver von der Webanwendung selbst ausgeführt werden. Um dies zu erreichen, müssen Sie eine Rackup-Konfigurationsdatei erstellen. Füge hinzu ein faye.ru Datei im Stammverzeichnis des Projekts und vergewissern Sie sich, dass es so aussieht:

 erfordern 'faye' bayeux = Faye :: RackAdapter.new (: mount => '/ faye',: timeout => 25) bayeux.listen (9292)

Diese Datei teilt Rackup lediglich mit, wie der Faye-Server gestartet wird. Probieren Sie es aus, um sicherzustellen, dass es richtig funktioniert. Führen Sie dies in Ihrem Terminal aus:

Rackup faye.ru -E Produktion -s dünn

Wenn Sie keine Fehler erhalten, können Sie loslegen!


Schritt 2 - Einige grundlegende Authentifizierung

Um eine Chat-Anwendung zu erstellen, benötigen wir zwei grundlegende Dinge: Benutzer und einen Chatroom. Wir werden unsere Benutzer nicht authentifizieren, aber wir müssen ihnen trotzdem die Möglichkeit geben, ihren Benutzernamen festzulegen. Lass uns das schaffen. Führen Sie den folgenden Befehl aus, um Sitzungen zu erstellen Regler so können wir sie einloggen:

Schienen g Controller-Sitzungen neu erstellen

Dadurch werden Sitzungen erstellt Regler und zwei Methoden: Neu und erstellen. Fügen Sie diese Routen zu Ihrem hinzu routen.rb Datei:

 get '/ login' => 'sessions # neu',: as =>: login post '/ login' => 'sessions # create',: as =>: login

Diese beiden Routen sollten für Sie selbsterklärend sein. Gehen Sie weiter und ändern Sie die app / views / sessions / new.html.erb Datei:

 <%= form_tag login_path do |f| %> <%= label_tag :username %> <%= text_field_tag :username %> <%= submit_tag "Enter" %> <% end %>

Und haben die erstellen Methode innerhalb der Sitzungen Regler sieh wie folgt aus:

 def create session [: username] = params [: username] render: text => "Welcome # session [: username]!" Ende

Probieren Sie es aus! Lauf Schienen-Server im Terminal und verweisen Sie mit Ihrem Browser auf localhost: 3000 / login und geben Sie einen Benutzernamen ein. Sie sollten von Ihrer Bewerbung begrüßt werden, nachdem Sie das Formular abgeschickt haben.

Wenn Sie sich einer Herausforderung stellen möchten, können Sie mit Omniauth die Integration von Twitter oder Facebook für diesen Schritt hinzufügen!


Schritt 3 - Der Chatraum

Nun, da wir einige grundlegende Authentifizierung haben, fügen wir einen Chatroom hinzu. Führen Sie den folgenden Befehl aus, um einen Chat zu erstellen Regler:

Schienen erzeugen Controller-Chat-Raum

Dadurch werden unsere Chats generiert Regler und ein Zimmer Methode. Wir müssen einige Routen hinzufügen, damit unser Chat funktioniert. Fügen Sie diese Zeile also zu Ihrem hinzu routen.rb Datei:

 Holen Sie sich '/ chatroom' => 'chats # room',: as =>: chat

Diese Route leitet unseren Benutzer in den Chatroom und lässt ihn über ein einfaches Formular Nachrichten veröffentlichen. Modifiziere den Zimmer Methode in den Chats Regler und es so aussehen lassen:

 def room redirect_to login_path, sofern nicht Session [: Benutzername] beendet ist

Dadurch wird sichergestellt, dass Benutzer einen Benutzernamen festlegen, wenn sie chatten möchten. Lassen Sie uns jetzt den Raum selbst erstellen! Fügen Sie dies dem hinzu app / views / chats / room.html.erb:

 

Willkommen im Chatroom <%= session[:username] %>!

Dies ist eine einfache Struktur für den Raum. Das Formular am Ende wird von einem JavaScript-Code verwaltet, der die Nachricht im Chatroom veröffentlicht.

Um Nachrichten in den Raum zu senden, müssen wir unserer Ansicht JavaScript hinzufügen. Fügen Sie zunächst Fayes Bibliothek hinzu app / views / layouts / application.html.erb:

 <%= javascript_include_tag "http://localhost:9292/faye.js" %>

Fügen Sie dann Folgendes am Anfang von hinzu room.html.erb Aussicht:

 

Diese Methode übernimmt die Nachricht in der Form, die wir zuvor hinzugefügt haben (wenn sie übermittelt wurde) und sendet den Benutzernamen und die Nachricht des Autors an den Kanal "/ messages / public" in einem JSON-Objekt. Kanäle sind Fayes Art, Nachrichten zu senden. Ein Benutzer abonniert einen Kanal und empfängt alle Nachrichten, die an ihn gesendet werden. In unserem Fall gibt es nur einen Kanal, den öffentlichen. Lassen Sie uns den Code etwas genauer analysieren:

  1. Zuerst instanziieren wir einen neuen Faye-Client und lassen ihn mit unserem Faye-Server verbinden.
  2. Als Nächstes erledigen wir die Übermittlung des Formulars. Wenn der Benutzer die Eingabetaste drückt oder auf "Senden" klickt, veröffentlichen wir das oben genannte JSON-Objekt, das den Absender der Nachricht und die Nachricht selbst enthält, im öffentlichen Kanal.
  3. Anschließend löschen wir das Meldungsfeld und falsch zurückgeben, um zu vermeiden, dass das Formular tatsächlich gesendet wird und die Seite aktualisiert wird.

Nun werden Nachrichten im Chatroom veröffentlicht, aber die verbundenen Benutzer können sie nicht empfangen, da ihre Browser den Kanal nicht abonniert haben. Dies wird durch etwas mehr JavaScript erreicht. Aktivieren Sie den JavaScript-Block app / views / chats / room.html.erb so aussehen:

 

Dies stellt einfach eine Verbindung zum Server von Faye her und abonniert den Kanal "/ messages / public". Der von uns bereitgestellte Rückruf empfängt die gesendeten Nachrichten. Daten wird das JSON-Objekt sein, das wir zuvor veröffentlicht haben Markieren Sie die darin enthaltene Nachricht und hängen Sie sie an den Chatroom-Container an.

Du solltest jetzt einen einfachen Chat haben! Führen Sie sowohl Faye als auch den Rails-Server aus und öffnen Sie zwei Browser (oder beispielsweise ein Inkognito-Fenster in Chrome). Sie können zwei verschiedene Benutzernamen eingeben und Ihren Chat testen. Nachrichten sollten im Chat-Raum sofort angezeigt werden, sobald Sie sie senden.


Schritt 4 - Private Nachrichten hinzufügen

Momentan können Benutzer miteinander chatten, aber alle Nachrichten sind öffentlich. Fügen Sie einige einfache Funktionen hinzu, mit denen Personen private Nachrichten senden können, indem Sie den Benutzernamen des Empfängers erwähnen - so wie in Twitter. Damit dies funktioniert, abonnieren wir unsere Benutzer in ihren eigenen Kanälen, sodass sie die einzigen sind, die Nachrichten davon erhalten können. Mach dein app / views / chats / room.html.erb JavaScript sieht so aus:

 

Wie Sie sehen, abonnieren wir zwei Faye-Kanäle: Einer ist der öffentliche Kanal und der zweite ist ein Kanal mit dem Namen "/ messages / private / USERNAME" (beachten Sie, dass wir den Benutzernamen in der Rails-Sitzung verwenden). Auf diese Weise senden wir, wenn jemand diesen Benutzer erwähnt, die Nachricht nicht über den öffentlichen Kanal, sondern über den privaten Kanal des Empfängers, sodass nur diese Person sie lesen kann. Wir fügen auch einige einfache Stile hinzu, sodass sie fett dargestellt werden.

Eine andere Sache, die geändert wurde, ist der Code, der Nachrichten veröffentlicht. Wir prüfen zunächst, ob es sich um eine private Nachricht handelt, indem Sie einen einfachen regulären Ausdruck anwenden, der nach einer Erwähnung sucht. Wenn dies der Fall ist, veröffentlichen wir eine Nachricht an den spezifischen Kanal des Empfängers. Wenn nicht, machen wir genau so wie zuvor - veröffentlichen es im öffentlichen Kanal.

Jetzt probieren Sie es aus! Senden Sie Nachrichten an andere Benutzer, indem Sie sie erwähnen. Sie sollten sie nur im Chatfenster des Empfängers sehen.


Schritt 5 - Einige Vorsichtsmaßnahmen

Diese Implementierung hat ihre Mängel. Erstens prüfen wir nicht, ob der von einer Person ausgewählte Benutzername bereits verwendet wird. Dies würde bedeuten, dass jeder denselben Benutzernamen wie jemand anderes eingeben und Nachrichten senden kann, die sich als sie selbst ausgeben, und sogar seine privaten Nachrichten erhalten! Dies kann leicht durch Hinzufügen eines Authentifizierungssystems oder durch Speichern der aktuell verwendeten Benutzernamen in einer Datenbank gelöst werden. Ich werde das im heutigen Tutorial nicht behandeln, aber es sollte ziemlich einfach für Sie sein, es zu implementieren. Wenn Sie Hilfe benötigen, hinterlassen Sie einen Kommentar, und wir helfen Ihnen dabei!

Der zweite Vorbehalt ist nicht so offensichtlich. Das Problem bei unserer Implementierung ist, dass jeder das JavaScript im Handumdrehen manipulieren kann (z. B. mit Firebug), um sich selbst für jeden gewünschten Kanal (auch für private Kanäle) zu abonnieren und ihm Nachrichten zu veröffentlichen, die sich als jemand anderes ausgeben. Dies ist nicht so leicht zu lösen wie der erste Fehler, auf den ich hingewiesen habe (wenn wir das Problem manuell lösen würden), aber Ryan Bates hat ein Juwel geschaffen, das diese Aufgabe zum Kinderspiel macht und unsere App sehr sicher macht.

Der Edelstein heißt privat_pub. Es verbietet im Wesentlichen jedem Benutzer, auf Kanälen mit JavaScript zu veröffentlichen, was bedeutet, dass nur die Rails-App für ihn veröffentlichen kann. Dies erhöht die Sicherheit, da ein böswilliger Benutzer nicht in privaten Kanälen veröffentlichen kann. Eine weitere Sache, die dieser Edelstein löst, sind Abonnements. Mit private_pub kann ein Benutzer nur Nachrichten von Kanälen empfangen, in denen wir sie abonnieren, sodass er kein Abonnement manuell hinzufügen kann, um das gesamte Problem zu lösen.

Fügen wir es also unserem hinzu Gemfile:

 gem 'private_pub',: git => 'git: //github.com/ryanb/private_pub.git'

Lauf Bundle installieren um den gem zu installieren und den Generator auszuführen, um die Konfigurationsdateien zu erstellen:

Schienen g private_pub: installieren

Wenn Sie diesen Befehl ausführen, erhalten Sie eine Konfliktwarnung (private_pub versucht, den Befehl zu überschreiben.) faye.ru Datei). Geben Sie einfach "J" ein und drücken Sie die Eingabetaste, da diese Datei überschrieben werden muss. Sie müssen auch das verschieben public / private_pub.js Datei an die app / assets / javascripts Mappe. Und das Letzte: Entfernen Sie die Zeile mit faye.js auf application.html.erb, da Private Pub es automatisch enthält. Stellen Sie sicher, dass Sie an diesem Punkt beide Server (Rails und Faye) neu starten.

Nun müssen wir einige Änderungen vornehmen. Erstens: Das Abonnieren eines Benutzers für einen Kanal erfolgt mit private_pub anders. Bearbeiten app / views / chats / room.html.erb und fügen Sie vor dem JavaScript-Block Folgendes hinzu:

 <%= subscribe_to "/messages/public" %> <%= subscribe_to "/messages/private/#session[:username]" %>

Das ist private_pubDie Art und Weise, wie Sie Kanäle abonnieren. Dadurch kann der Benutzer Nachrichten über den von Ihnen angegebenen Kanal empfangen. Nun müssen wir den JavaScript-Code wie folgt ändern:

PrivatePub.subscribe ("/ messages / public", Funktion (Daten)
$ (''). html (data.username + ":" + data.msg) .appendTo ('# chat_room');
);

PrivatePub.subscribe ("/ messages / private /<%= session[:username] %>", Funktion (Daten)
$ (''). addClass ('private'). html (data.username + ":" + data.msg) .appendTo ('# chat_room');
);

Der einzige Unterschied besteht darin, dass wir PrivatePub verwenden, um Kanäle direkt von der Faye-Bibliothek zu abonnieren.

Wir müssen auch die Art und Weise ändern, in der wir Nachrichten veröffentlichen. Mit Private Pub kann nur die Rails-Anwendung Nachrichten veröffentlichen. Die Javascript-Bibliothek kann keine eigenen Nachrichten veröffentlichen. Dies ist eine gute Sache, da wir die volle Kontrolle darüber haben, wer Nachrichten auf welchem ​​Kanal veröffentlicht. Dazu müssen wir das Formular zum Senden von Nachrichten folgendermaßen ändern:

 <%= form_tag new_message_path, :remote => true do%> <%= text_field_tag :message %> <%= submit_tag "Send" %> <% end %>

Dies ist ein AJAX-Formular, sodass die Seite beim Senden nicht aktualisiert wird. Es wird auch gesucht werden new_message_path, Stellen Sie sicher, dass Sie dies zu hinzufügen routen.rb:

 post '/ new_message' => 'chats # new_message',: as =>: new_message

Sie müssen auch eine neue Methode auf dem Chats-Controller erstellen:

 def new_message # Prüfen Sie, ob die Nachricht privat ist, wenn der Empfänger = params [: message] .match (/@(.+) (. +) /) ist. # Es ist privat. Senden Sie es an den privaten Kanal des Empfängers @channel = "/ messages /private/#recipient.captures.first "@message = : username => session [: username],: msg => receiver.captures.second else # Es ist öffentlich, also sende es an den öffentlichen Kanal @channel = "/ messages / public" @message = : username => session [: username],: msg => params [: message] beende antwort_, um | f | zu tun f.js end end

Dies funktioniert sehr ähnlich wie das JavaScript-Pendant. Es ermittelt, ob die Nachricht eine Erwähnung enthält, und sendet die Nachricht an den privaten Kanal des Empfängers. Wenn nicht, wird die Nachricht über den öffentlichen Kanal gesendet. Jetzt wird die Nachricht nicht wirklich gesendet, sondern es werden lediglich zwei Variablen erstellt, die wir in der Ansicht verwenden müssen, um eine zu senden. Private Pub erlaubt es Ihnen nicht, Nachrichten über die Regler (zumindest nicht mit der Version, die ich für dieses Tutorial verwendet habe), machen Sie also weiter und erstellen Sie die Datei app / views / chats / new_message.js.erb und füge folgendes hinzu:

 // Lösche die Nachrichteneingabe $ ('# message'). Val ("); // Sende die Nachricht <% publish_to @channel, @message %>

Dadurch wird die erste Codezeile ausgeführt, das Meldungsfeld gelöscht und durch Aufruf aufgerufen publish_to, Private Pub wird senden @Botschaft (das bei Ankunft in ein JSON-Objekt konvertiert wird) an @Kanal. Einfach, huh?

Probieren Sie es aus. Es sollte wie zuvor funktionieren, nur mit neuer zusätzlicher Sicherheit!


Fazit

Ich hoffe, dieser Artikel gab Ihnen einen Einblick in die Verwendung von Faye für Ihre Projekte. Ich würde empfehlen, dass Sie immer Private Pub verwenden, da dies eine wichtige Sicherheitsstufe darstellt, es sei denn, Sie benötigen es nicht wirklich.

Wenn Sie Fragen haben, können Sie diese gerne in den Kommentaren stellen oder mir einen Tweet senden!