Cum să utilizați Faye ca un server Push în timp real în rails

Există mai multe modalități de a adăuga funcționalitate push la o aplicație, inclusiv Pushr și Pub-Nub, care sunt soluții destul de elegante și simple. Există, de asemenea, câteva opțiuni mai avansate. În acest articol, vă voi arăta cum să utilizați Faye, un sistem de mesagerie care rulează atât pe Ruby, cât și pe Node.js.


Pasul 1 - Obțineți totul

Vom construi un serviciu de chat simplu. Acum, Ryan Bates a acoperit acest lucru pe Railscast # 260, cu toate acestea, vom avea o abordare puțin diferită în acest tutorial. În primul rând, vom crea un serviciu de chat în care utilizatorii intră într-o sală publică și toată lumea se poate conversa între ei în mod public. A doua funcționalitate pe care o vom adăuga este mesajul privat. În plus, vom integra o anumită securitate în implementarea noastră, folosind gemul personal_pub al lui Ryan Bate.

Asigurați-vă că aveți un set de lucru Ruby și Ruby on Rails 3.1. În afară de asta, veți avea nevoie de subțire. Thin este un server web Ruby utilizat pe scară largă, iar Faye îl cere să ruleze (nu funcționează cu WEBrick, serverul încorporat al lui Rails). Puteți instala Thin, așa cum este cazul:

gem instalați subțire

Ar trebui să fim totul setați, deci să creăm aplicația:

rails new faye-tutorial

Acum, adăugați faye bijuterie pentru dvs. Gemfile:

 gem "faye"

și fugi instalare pachet pentru ao instala. Faye trebuie să ruleze pe un server web separat din aplicația web în sine; pentru a realiza acest lucru, trebuie să creați un fișier de configurare Rackup. Adauga o faye.ru fișier la rădăcina proiectului și asigurați-vă că arată astfel:

 trebuie să fayeux bayeux = Faye :: RackAdapter.new (: mount => '/ faye',: timeout => 25) bayeux.listen (9292)

Acest fișier îi spune pur și simplu lui Rackup cum să pornească serverul Faye. Încercați-l pentru a vă asigura că funcționează corect. Rulați acest lucru în terminalul dvs.:

rackup faye.ru-producția e subțire

Dacă nu primiți nici o eroare, atunci sunteți bine să mergeți!


Pasul 2 - Unele autentificări de bază

Pentru a crea o aplicație de chat, avem nevoie de două lucruri de bază: utilizatori și o cameră de chat. Nu vom autentifica utilizatorii, dar trebuie să le oferim o modalitate de a-și seta numele de utilizator. Să creăm asta. Rulați următoarea comandă pentru a crea o sesiune controlor astfel încât să le putem înregistra:

rails g controler sesiuni noi crea

Aceasta va crea o sesiune controlor și două metode: nou și crea. Adăugați aceste rute la dvs. routes.rb fişier:

 primiți '/ login' => 'sesiuni # noi',: as =>: login login '/ login' => 'sesiuni # crea',: as =

Aceste două căi ar trebui să fie explicative pentru dumneavoastră. Continuați și modificați app / opinii / sesiuni / new.html.erb fişier:

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

Și trebuie să crea în cadrul sesiunilor controlor arata ca:

 Defineți sesiunea [: username] = params [: username] render: text => "Welcome # session [: username] Sfârșit

Încearcă o încercare! Alerga rails server în Terminal și îndreptați browserul spre localhost: 3000 / login și introduceți un nume de utilizator. Ar trebui să fiți salutat de cererea dvs. după ce ați trimis formularul.

Dacă sunteți pregătit pentru o provocare, ați putea folosi Omniauth pentru a adăuga o integrare Twitter sau Facebook pentru acest pas!


Pasul 3 - Camera de chat

Acum că avem o autentificare de bază, să adăugăm o cameră de chat. Rulați următoarea comandă pentru a crea un chat controlor:

șinele generează cameră de chat controler

Acest lucru va genera chat-urile noastre controlor și unul cameră metodă. Trebuie să adăugăm câteva rute pentru a ne face să lucreze în chat, așa că adăugați această linie la dvs. routes.rb fişier:

 get '/ chatroom' => 'chats # room',: as =>: chat

Acest traseu va direcționează utilizatorul nostru către camera de chat și îi va lăsa să trimită mesaje printr-un simplu formular. Modificați cameră pe chat controlor și fă-o să arate așa:

 def spațiul redirect_to calea de conectare, dacă nu se termină sesiunea [: username]

Acest lucru va asigura că utilizatorii stabilesc un nume de utilizator dacă doresc să vorbească. Acum, să creăm camera în sine! Adăugați această funcție la app / opinii / chat-uri / room.html.erb:

 

Bine ați venit în camera de chat <%= session[:username] %>!

Aceasta este o structură simplă pentru cameră. Formularul de la final va fi gestionat de un cod JavaScript care va publica mesajul în camera de chat.

Acum, pentru a posta mesaje în cameră, trebuie să adăugăm un JavaScript în vizualizarea noastră. Mai întâi, adăugați biblioteca lui Faye la app / opinii / machete / application.html.erb:

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

Apoi, adăugați următoarele la începutul room.html.erb vedere:

 

Această metodă preia mesajul în forma pe care am adăugat-o anterior (când este trimisă) și trimite numele de utilizator și mesajul autorului către canalul "/ messages / public" într-un obiect JSON. Canalele sunt modul în care Faye trimite mesaje. Un utilizator subscrie la un canal și primește toate mesajele care îi sunt trimise. În cazul nostru, există doar un canal, care este unul public. Să discutăm codul un pic mai mult:

  1. Mai întâi instanțiăm un nou client Faye și îl conectăm la serverul nostru Faye.
  2. Apoi, vom rezolva depunerea formularului. Când utilizatorul atinge tasta Enter sau dă clic pe "Trimite", vom publica obiectul JSON menționat mai sus, care conține expeditorul mesajului și mesajul în sine în canalul public.
  3. După aceasta, ștergem caseta de mesaj și return false, pentru a evita prezentarea și actualizarea paginii.

Acum, aceasta va publica mesaje în camera de chat, dar utilizatorii conectați nu vor putea să le primească, deoarece browserele lor nu sunt abonate la canal. Acest lucru este realizat printr-un JavaScript mai puțin. Efectuați blocarea JavaScript app / opinii / chat-uri / room.html.erb arata asa:

 

Aceasta se conectează pur și simplu la serverul Faye și se abonează la canalul "/ messages / public". Callback-ul pe care îl furnizăm primește mesajele trimise. date va fi obiectul JSON pe care l-am publicat înainte, deci pur și simplu îl folosim pentru a crea un etichetați cu mesajul din interior și adăugați-l în containerul camerei de chat.

Ar trebui să aveți acum un simplu chat! Rulați atât serverul Faye, cât și serverul Rails și deschideți două browsere (sau, de exemplu, un fereastră Incognito în Chrome). Puteți introduce două nume de utilizatori diferite și puteți testa chatul. Mesajele ar trebui să apară aproape instantaneu în camera de chat odată ce le trimiteți.


Pasul 4 - Adăugarea de mesaje private

În acest moment, utilizatorii pot discuta unul cu celălalt, dar toate mesajele sunt publice. Să adăugăm câteva funcționalități simple în care oamenii pot trimite mesaje private, menționând numele de utilizator al destinatarului - ca și în Twitter. Pentru ca acest lucru să funcționeze, ne vom abona pe utilizatorii noștri pe propriile canale, astfel încât aceștia sunt singurii care pot primi mesaje de la acesta. Fă-ți app / opinii / chat-uri / room.html.erb JavaScript arata astfel:

 

După cum puteți vedea, suntem abonați la două canale Faye: unul este canalul public, iar al doilea este un canal, numit "/ messages / private / USERNAME" (observați că utilizăm numele de utilizator în sesiunea Rails). În acest fel, când cineva menționează acest utilizator, în loc să trimită mesajul prin canalul public, îl trimitem prin canalul privat al destinatarului, astfel încât numai acea persoană să o poată citi. Adăugăm de asemenea câteva stiluri simple, așa că este afișat cu caractere aldine.

Un alt lucru care sa schimbat este codul care publică mesaje. Mai întâi verificăm dacă mesajul este unul privat, aplicând o expresie regulată simplă, care caută o mențiune. Dacă este, publicăm un mesaj către canalul specific destinatarului. Dacă nu, facem exact așa cum am făcut înainte - publicăm-o pe canalul public.

Acum încercați! Trimiteți mesaje către alți utilizatori, menționând-le, trebuie să le vedeți numai în fereastra de chat a destinatarului.


Pasul 5 - Câteva avertismente

Această implementare are defectele sale. În primul rând, nu verificăm dacă numele de utilizator pe care o persoană o alege este deja utilizat. Acest lucru ar însemna că oricine ar putea să intre în același nume de utilizator ca și altcineva și să trimită mesaje care pretind a fi ei, și chiar să primească mesajele lor private! Acest lucru este ușor de rezolvat prin adăugarea unui fel de sistem de autentificare sau prin stocarea numelor de utilizator care se află în prezent în uz într-o bază de date. Nu voi acoperi acest lucru în tutorialul de astăzi, dar ar trebui să fie destul de ușor pentru tine de a pune în aplicare. Dacă aveți nevoie de asistență, lăsați un comentariu și vă vom ajuta!

Cea de-a doua avertizare nu este la fel de evidentă. Problema cu implementarea noastră este că oricine ar putea manipula JavaScript în zbor (folosind Firebug de exemplu) pentru a se abona la orice canal pe care îl doresc (chiar și pentru canale private), și ar putea să le publice mesaje care să pretindă că sunt altcineva. Acest lucru nu este atât de ușor de rezolvat ca primul defect pe care l-am subliniat (dacă am fi rezolvat acest lucru manual), dar Ryan Bates a creat o bijuterie care face ca această sarcină să fie cinch, iar aplicația noastră foarte sigură.

Bijutectura se numește private_pub; în mod esențial, interzice oricărui utilizator să publice în canale cu JavaScript, ceea ce înseamnă că numai aplicația Rails poate să le publice. Aceasta adaugă o anumită securitate, deoarece un utilizator rău intenționat nu ar putea să publice pe canale private. Un alt lucru pe care această bijuterie o rezolvă este abonamentele. Cu privat_pub, un utilizator poate primi doar mesaje de la canalele la care le-am abonat, deci nu pot adăuga manual un abonament, rezolvând întreaga problemă.

Deci, să o adăugăm la noi Gemfile:

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

alerga instalare pachet pentru a instala bijuteria și a rula generatorul pentru a crea fișierele de configurare:

rails g private_pub: instalați

Veți primi un avertisment de conflict atunci când executați această comandă (private_pub încearcă să suprascrie faye.ru fişier). Doar tastați "Y" și apăsați Enter, deoarece este necesar să suprascrieți acel fișier. De asemenea, va trebui să mutați publice / private_pub.js fișier la app / active / javascripts pliant. Și ultimul lucru: eliminați linia care include faye.js pe application.html.erb, deoarece Pubul privat îl include în mod automat. Asigurați-vă că reporniți ambele servere (șine și faye) în acest moment.

Acum, trebuie să facem niște schimbări. În primul rând, abonarea unui utilizator la un canal se face diferit cu privat_pub. Editați | × app / opinii / chat-uri / room.html.erb și adăugați următoarele înaintea blocului JavaScript:

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

Aceasta este private_pubmodul de abonare la canale. Aceasta permite utilizatorului să primească mesaje prin canalul pe care îl specificați. Acum, trebuie să schimbăm codul JavaScript la următoarele:

PrivatePub.subscribe ("/ messages / public", funcție (date)
$ (''). html (date.username + ":" + data.msg) .appendTo ('# chat_room');
);

PrivatePub.subscribe ( "/ mesaje / private /<%= session[:username] %>", funcția (date)
$ (''). addClass ('privat'). html (data.username + ":" + data.msg) .appendTo ('# chat_room');
);

Singura diferență aici este că folosim direct PrivatePub pentru a vă abona la canale în locul bibliotecii Faye.

De asemenea, va trebui să schimbăm modul în care publicăm mesajele. Cu Private Pub, numai aplicația Rails poate să publice mesaje. Biblioteca Javascript nu poate publica mesaje pe cont propriu. Acesta este un lucru bun, deoarece avem controlul deplin asupra cine publică mesaje și la ce canal. Pentru a face acest lucru, va trebui să modificăm formularul utilizat pentru a trimite mesaje la următoarele:

 <%= form_tag new_message_path, :remote => adevărat face%> <%= text_field_tag :message %> <%= submit_tag "Send" %> <% end %>

Acesta este un formular AJAX, deci nu va reîmprospăta pagina când este trimisă. De asemenea, va căuta new_message_path, deci asigurați-vă că adăugați acest lucru routes.rb:

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

Va trebui, de asemenea, să creați o nouă metodă în controlerul de chaturi:

 def new_message # Verificați dacă mesajul este privat dacă recipientul = params [: message] .match (/@(.+) (. +) /) # Este privat, trimiteți-l la canalul privat al destinatarului @channel = "/ messages /private/#recipient.captures.first "@message = : username => session [: username],: msg => recipient.captures.second altceva # Este public, asa ca trimite-l la canalul public @canal = "/ messages / public" @message = : username => session [: nume utilizator],: msg => params [: message] end reply_to | Sfârșitul capătului f.js

Acest lucru funcționează foarte mult ca omologul său JavaScript. Aceasta determină dacă mesajul conține o mențiune și, dacă este cazul, trimite mesajul către canalul privat al destinatarului. Dacă nu, trimite mesajul prin canalul public. Acum, acest lucru nu trimite de fapt mesajul, ci creează doar două variabile pe care trebuie să le folosim din vedere pentru a le trimite. Pubul privat nu vă permite să trimiteți mesaje prin controlor (cel puțin nu cu versiunea pe care am folosit-o pentru acest tutorial), deci mergeți mai departe și creați fișierul app / opinii / chat-uri / new_message.js.erb și adăugați următoarele:

 // Eliminați mesajul de intrare $ ('# message') val ("); // Trimiteți mesajul <% publish_to @channel, @message %>

Aceasta va executa prima linie de cod, debifând caseta de mesaje și sunând publish_to, Private Pub va trimite @mesaj (care va fi convertit la un obiect JSON atunci când acesta va sosi) @canal. Simplu, huh?

Mergeți la o încercare. Ar trebui să funcționeze la fel ca înainte, numai cu o securitate adăugată nouă!


Concluzie

Sper că acest articol ți-a oferit câteva informații despre cum să folosești Faye pentru proiectele tale. V-aș sfătui să utilizați întotdeauna Private Pub, deoarece adaugă un nivel important de securitate, dacă nu aveți nevoie de ea.

Dacă aveți întrebări, nu ezitați să le întrebați în comentarii sau trimiteți-mi un tweet!

Cod