Il existe plusieurs façons d’ajouter une fonctionnalité Push à une application, notamment Pushr et Pub-Nub, des solutions simples et élégantes. Il existe également des options plus avancées. Dans cet article, je vais vous montrer comment utiliser Faye, un système de messagerie fonctionnant à la fois sur Ruby et Node.js..
Nous allons construire un simple service de chat. Maintenant, Ryan Bates a couvert cela dans Railscast # 260, cependant, nous allons adopter une approche légèrement différente dans ce tutoriel. Tout d'abord, nous allons créer un service de discussion où les utilisateurs entrent dans une salle publique et où tout le monde peut discuter en public. La deuxième fonctionnalité que nous allons ajouter est celle des messages privés. De plus, nous allons intégrer une certaine sécurité à notre implémentation en utilisant le gem private_pub de Ryan Bate.
Assurez-vous que vous avez une configuration de travail de Ruby et de Ruby on Rails 3.1. En dehors de cela, vous aurez besoin de minces. Thin est un serveur Web Ruby largement utilisé, et Faye nécessite son exécution (il ne fonctionne pas avec WEBrick, le serveur intégré de Rails). Vous pouvez installer Thin, comme suit:
bijou installer mince
Nous devrions être tous prêts, alors créons l'application:
rails nouveau faye-tutorial
Maintenant, ajoutez le faye
joyau à votre Gemfile
:
gem 'faye'
et courir installation groupée
pour l'installer. Faye doit s'exécuter sur un serveur Web distinct de l'application Web elle-même. Pour ce faire, vous devez créer un fichier de configuration Rackup. Ajouter un faye.ru
fichier à la racine du projet et assurez-vous qu'il ressemble à ce qui suit:
nécessite 'faye' bayeux = Faye :: RackAdapter.new (: mount => '/ faye',: timeout => 25) bayeux.listen (9292)
Ce fichier indique simplement à Rackup comment démarrer le serveur Faye. Essayez-le pour vous assurer qu'il fonctionne correctement. Exécutez ceci dans votre terminal:
rackup faye.ru -E production -s mince
Si vous ne recevez aucune erreur, alors vous êtes prêt à partir!
Pour créer une application de discussion, nous avons besoin de deux éléments de base: les utilisateurs et une salle de discussion. Nous n'allons pas authentifier nos utilisateurs, mais nous devons tout de même leur fournir un moyen de définir leur nom d'utilisateur. Créons cela. Exécutez la commande suivante pour créer une session manette
afin que nous puissions les connecter:
rails g sessions de contrôleur nouvelle créer
Cela va créer une session manette
et deux méthodes: Nouveau
et créer
. Ajoutez ces itinéraires à votre routes.rb
fichier:
get '/ login' => 'sessions # new',: as =>: login post '/ login' => 'sessions # create',: as =>: login
Ces deux itinéraires devraient vous être explicites. Allez-y et modifiez le app / views / sessions / new.html.erb
fichier:
<%= form_tag login_path do |f| %> <%= label_tag :username %> <%= text_field_tag :username %> <%= submit_tag "Enter" %> <% end %>
Et avoir le créer
méthode dans les sessions manette
ressembler à ce qui suit:
def create session [: nomutilisateur] = params [: nomutilisateur] render: text => "Bienvenue # session [: nomutilisateur]!" fin
Allez-y et essayez-le! Courir serveur de rails
dans le terminal et pointez votre navigateur sur localhost: 3000 / login et entrez un nom d'utilisateur. Vous devriez être accueilli par votre demande après avoir soumis le formulaire.
Si vous êtes prêt pour un défi, vous pouvez utiliser Omniauth pour ajouter une intégration Twitter ou Facebook à cette étape.!
Maintenant que nous avons une authentification de base, ajoutons une salle de discussion. Exécutez la commande suivante pour créer une discussion. manette
:
les rails génèrent une salle de discussion pour le contrôleur
Cela va générer nos discussions manette
et une pièce
méthode. Nous devons ajouter quelques itinéraires pour que notre chat fonctionne, alors ajoutez cette ligne à votre routes.rb
fichier:
get '/ chatroom' => 'chats # room',: as =>: chat
Cet itinéraire dirige notre utilisateur vers la salle de discussion et lui permet de poster des messages via un simple formulaire. Modifier le pièce
méthode sur les chats manette
et le faire ressembler ainsi:
def room redirect_to login_path sauf si session [: nom d'utilisateur] se termine
Cela garantira que les utilisateurs définissent un nom d'utilisateur s'ils souhaitent discuter. Maintenant, créons la pièce elle-même! Ajoutez ceci au app / views / chats / room.html.erb
:
Bienvenue sur le chat room <%= session[:username] %>!
Ceci est une structure simple pour la salle. Le formulaire à la fin sera géré par du code JavaScript qui publiera le message dans la salle de discussion..
Maintenant, pour poster des messages dans la salle, nous devons ajouter du JavaScript à notre vue. Premièrement, ajoutez la bibliothèque de Faye à app / views / layouts / application.html.erb
:
<%= javascript_include_tag "http://localhost:9292/faye.js" %>
Ensuite, ajoutez ce qui suit au début de la room.html.erb
vue:
Cette méthode prend le message sous la forme que nous avons ajoutée précédemment (lors de sa soumission) et envoie le nom d'utilisateur et le message de l'auteur au canal "/ messages / public" dans un objet JSON. Les canaux sont la manière dont Faye envoie les messages. Un utilisateur s'abonne à un canal et reçoit tous les messages qui lui sont envoyés. Dans notre cas, il n'y a qu'une seule chaîne, celle du public. Disséquons un peu plus le code:
retourne faux
, pour éviter que le formulaire soit effectivement soumis et rafraîchir la page.Désormais, les messages seront publiés sur la salle de discussion, mais nos utilisateurs connectés ne pourront pas les recevoir car leurs navigateurs ne sont pas abonnés au canal. Ceci est réalisé grâce à un peu plus de JavaScript. Faire le bloc JavaScript sur app / views / chats / room.html.erb
ressemblez ainsi:
Cela se connecte simplement au serveur de Faye et s'abonne au canal «/ messages / public». Le rappel que nous fournissons reçoit les messages envoyés. Les données
sera l'objet JSON que nous avons publié auparavant, nous utilisons donc simplement cela pour créer un
marquez le message à l'intérieur et ajoutez-le au conteneur de la salle de discussion.
Vous devriez maintenant avoir un simple chat! Exécutez Faye et le serveur Rails et ouvrez deux navigateurs (ou une fenêtre de navigation privée sur Chrome, par exemple). Vous pouvez entrer deux noms d'utilisateur différents et tester votre conversation. Les messages devraient apparaître presque instantanément sur le salon de discussion une fois que vous les avez envoyés..
Pour le moment, les utilisateurs peuvent discuter entre eux, mais tous les messages sont publics. Ajoutons quelques fonctionnalités simples permettant à des personnes d'envoyer des messages privés à quelqu'un en mentionnant le nom d'utilisateur du destinataire, un peu comme sur Twitter. Pour que cela fonctionne, nous allons abonner nos utilisateurs à leurs propres canaux, de sorte qu'ils sont les seuls à pouvoir recevoir des messages de ce dernier. Faire votre app / views / chats / room.html.erb
JavaScript ressemble à ceci:
Comme vous pouvez le constater, nous nous abonnons à deux canaux Faye: l’un est le canal public et l’autre est un canal appelé «/ messages / private / USERNAME» (notez que nous utilisons le nom d’utilisateur de la session Rails). Ainsi, lorsque quelqu'un mentionne cet utilisateur, au lieu d'envoyer le message via le canal public, nous l'envoyons via le canal privé du destinataire, de sorte que seule cette personne puisse le lire. Nous y ajoutons également quelques styles simples, de sorte qu'il s'affiche en gras.
Une autre chose qui a changé est le code qui publie des messages. Nous vérifions d’abord si le message est privé, en appliquant une simple expression régulière cherchant une mention. Si c'est le cas, nous publions un message sur le canal spécifique du destinataire. Si ce n'est pas le cas, nous faisons exactement comme avant - publions le tout sur le canal public..
Maintenant, essayez-le! Envoyez des messages à d'autres utilisateurs en les mentionnant, vous ne devriez les voir que dans la fenêtre de discussion du destinataire..
Cette implémentation a ses défauts. Premièrement, nous ne vérifions pas si le nom d'utilisateur choisi par une personne est déjà utilisé. Cela signifierait que n'importe qui pourrait entrer le même nom d'utilisateur que quelqu'un d'autre et envoyer des messages se faisant passer pour eux, et même recevoir leurs messages privés! Ceci est facilement résolu en ajoutant une sorte de système d'authentification ou en stockant les noms d'utilisateur actuellement utilisés dans une base de données. Je ne vais pas couvrir cela dans le tutoriel d'aujourd'hui, mais cela devrait être assez facile à mettre en œuvre. Si vous avez besoin d'aide, laissez un commentaire et nous vous aiderons!
La deuxième mise en garde n'est pas aussi évidente. Le problème de notre implémentation est que tout le monde peut manipuler le code JavaScript à la volée (à l’aide de Firebug, par exemple) pour s’abonner à n’importe quel canal (même privé) et leur envoyer des messages se faisant passer pour quelqu'un d'autre. Ce n'est pas aussi facile à résoudre que le premier défaut que j'ai signalé (si nous devions le résoudre manuellement), mais Ryan Bates a créé un joyau qui rend cette tâche très facile, et notre application très sécurisée..
La gemme s'appelle private_pub; il interdit essentiellement à tout utilisateur de publier sur des chaînes avec JavaScript, ce qui signifie que seule l'application Rails est en mesure de publier sur ces chaînes. Cela ajoute une certaine sécurité car un utilisateur malveillant ne pourrait pas publier sur des canaux privés. Une autre chose que ce petit bijou résout est les abonnements. Avec private_pub, un utilisateur ne peut recevoir que les messages des canaux auxquels il est abonné, il ne peut donc pas ajouter un abonnement manuellement, ce qui résout le problème dans son intégralité..
Alors ajoutons-le à notre Gemfile
:
gem 'private_pub',: git => 'git: //github.com/ryanb/private_pub.git'
courir installation groupée
pour installer le gem et exécuter le générateur pour créer les fichiers de configuration:
rails g private_pub: installer
Vous recevrez un avertissement de conflit lors de l'exécution de cette commande (private_pub essaie de remplacer le faye.ru
fichier). Il suffit de taper "Y" et appuyez sur Entrée, car il est nécessaire d'écraser ce fichier. Vous aurez également besoin de déplacer le public / private_pub.js
déposer au app / assets / javascripts
dossier. Et la dernière chose: supprimer la ligne qui comprend faye.js
sur application.html.erb
, depuis Private Pub l'inclut automatiquement. Assurez-vous de redémarrer les deux serveurs (rails et faye) à ce stade..
Maintenant, nous devons faire quelques changements. Tout d'abord, abonner un utilisateur à un canal se fait différemment avec private_pub. modifier app / views / chats / room.html.erb
et ajoutez ce qui suit avant le bloc JavaScript:
<%= subscribe_to "/messages/public" %> <%= subscribe_to "/messages/private/#session[:username]" %>
C'est private_pub
Manière de s'abonner à des canaux. Ceci autorise l'utilisateur à recevoir des messages via le canal que vous spécifiez. Maintenant, nous devons changer le code JavaScript comme suit:
PrivatePub.subscribe ("/ messages / public", fonction (données)
$ (''). html (data.username + ":" + data.msg) .appendTo ('# chat_room');
);
PrivatePub.subscribe ("/ messages / private /<%= session[:username] %>", fonction (données)
$ (''). addClass ('private'). html (data.username + ":" + data.msg) .appendTo ('# chat_room');
);
La seule différence est que nous utilisons PrivatePub pour nous abonner à des canaux plutôt qu'à la bibliothèque Faye directement..
Nous allons également avoir besoin de changer la façon dont nous publions des messages. Avec Private Pub, seule l’application Rails est capable de publier des messages. La bibliothèque Javascript ne peut pas publier de messages seule. C’est une bonne chose, car nous contrôlons totalement qui publie les messages et sur quel canal. Pour ce faire, nous devrons modifier le formulaire utilisé pour envoyer des messages comme suit:
<%= form_tag new_message_path, :remote => vrai faire%> <%= text_field_tag :message %> <%= submit_tag "Send" %> <% end %>
Ceci est un formulaire AJAX, il ne sera donc pas actualisé lors de la soumission. Il va aussi être à la recherche de new_message_path
, alors assurez-vous d'ajouter ceci à routes.rb
:
post '/ new_message' => 'chats # new_message',: as =>: new_message
Vous allez également avoir besoin de créer une nouvelle méthode sur le contrôleur de chats:
def new_message # Vérifie si le message est privé si le destinataire = params [: message] .match (/@(.+) (. +) /) # Il est privé, envoyez-le au canal privé du destinataire @channel = "/ messages /private/#recipient.captures.first "@message = : nomutilisateur => session [: nomutilisateur],: msg => destinataire.captures.second else # C'est public, envoyez-le au canal public @channel = "/ messages / public" @message = : nomutilisateur => session [: nomutilisateur],: msg => params [: message] end end answer_to do | f | f.js end end
Cela fonctionne très bien comme son homologue JavaScript. Il détermine si le message contient une mention et, le cas échéant, envoie le message au canal privé du destinataire. Sinon, il envoie le message via le canal public. En fait, cela n’envoie pas réellement le message, cela crée simplement deux variables que nous devons utiliser à partir de la vue pour pouvoir en envoyer une. Le pub privé ne vous autorise pas à envoyer des messages via le manette
(du moins pas avec la version que j'ai utilisée pour ce tutoriel), continuez et créez le fichier app / views / chats / new_message.js.erb
et ajoutez ce qui suit:
// Effacer le message saisi $ ('# message'). Val ("); // envoie le message <% publish_to @channel, @message %>
Ceci exécutera la première ligne de code, en effaçant la zone de message et en appelant publier_à
, Un pub privé enverra @message
(qui sera converti en objet JSON quand il arrivera) en @canal
. Simple, hein?
Allez-y et essayez-le. Cela devrait fonctionner comme avant, mais avec une nouvelle sécurité supplémentaire!
J'espère que cet article vous a montré comment utiliser Faye pour vos projets. Je vous conseillerais de toujours utiliser Private Pub, car cela ajoute un niveau de sécurité important, à moins que vous n'en ayez vraiment besoin.
Si vous avez des questions, n'hésitez pas à les poser dans les commentaires ou à m'envoyer un tweet!