Cum se construiește un sistem de conectare discret în rails

Un sistem de logare discret este unul care iese din calea utilizatorului. Aceasta va face aplicația mai frumoasă și mai lustruită. Acest articol vă va ghida în procesul de configurare a conectărilor utilizatorilor, apoi ajaxificarea procesului mutând formularul într-o casetă modală care comunică cu serverul. În plus, acest articol vă va arăta cum să creați configurarea utilizând jQuery și Prototype pentru a vă putea alege biblioteca preferată. Acest articol presupune că aveți experiență cu Rails și jQuery sau Prototype.


Puteți folosi Adman65 / nettuts pentru o autentificare reușită. Asigurați-vă că utilizați acreditări proaste pentru a vedea cum funcționează totul.

Ce facem



Noțiuni de bază

Vom începe prin crearea unei aplicații falsificate care are o pagină publică și privată. Adresa URL a root este pagina publică. Există un link de autentificare pe pagina publică. Dacă utilizatorul se conectează cu succes, sunt redirecționați către pagina privată. Dacă nu, sunt redirecționați înapoi la formularul de autentificare. Pagina privată prezintă numele de utilizator. Vom folosi acest lucru ca punct de plecare pentru ajaxificarea site-ului.

Primul pas este să utilizați comanda șinelor pentru a genera o nouă aplicație, apoi să instalați și să configurați authlogic.

$ cd în-un-director $ șine necontrolabile-login

Adăugați authlogic.

# /config/environment.rb config.gem "authlogic"

Acum, instalați pietrele prețioase.

$ sudo gem instalare gemcutter $ sudo gem tambur $ sudo rake pietre: install

Apoi creați un model de utilizator și adăugați la migrare coloanele authlogic necesare.

$ ./script/generate model Există o aplicație / modele / există test / unitate / există test / fixtures / create app / models / user.rb creare test / unitate / user_test.rb creare test / fixtures / users.yml create db / migrați creați db / migrate / 20100102082657_create_users.rb

Acum, adăugați coloanele la noua migrare.

clasa CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.string :login, :null => t.string false: crypted_password,: null => t.string false: password_salt,: null => false t.string: persistence_token,: null => false t.timestamps end end def self.down drop_table:

Migrați baza de date.

$ rake db: migrează

Includeți authlogic în modelul de utilizator.

# /app/models/user.rb Utilizator de clasă < ActiveRecord::Base acts_as_authentic end

Acum putem crea un utilizator. Deoarece aceasta este o aplicație demo, nu este necesară funcționalitatea web pentru înscriere. Așa că deschideți consola și creați un utilizator:

$ ./script/console >> me = User.create (: login => 'Adman65',: password => 'nettuts',: password_confirmation => 'nettuts')

Acum avem un utilizator în sistem, dar nu avem nici o modalitate de conectare sau de logout. Trebuie să creăm modele, controale și vizualizări pentru acest lucru. Authlogic are propria clasă pentru urmărirea datelor de conectare. Putem folosi generatorul pentru asta:

# crea sesiunea de utilizator $ ./script/generate UserSession

Apoi trebuie să generăm controlerul care va conecta / deconecta utilizatorii. Puteți crea sesiuni la fel ca orice altă resursă din Rails.

# creați controlerul de sesiune $ ./script/generate controler UserSessions

Acum setați conținutul său la:

# /app/controllers/user_sessions_controller.rb clasa UserSessionsController < ApplicationController def new @user_session = UserSession.new end def create @user_session = UserSession.new(params[:user_session]) if @user_session.save flash[:notice] = "Login successful!" redirect_back_or_default user_path else render :action => : sfârșitul final sfârșitul nou

Seamănă exact cu un controler care a fost generat prin schele. Acum creați controlorul de utilizatori care are conținut public și privat. Generați un controler de utilizatori. În interiorul controlerului vom folosi un filtru înainte pentru a limita accesul la zonele private. Acțiunea index este publică și arată că este privată.

# crea controlerul utilizatorilor $ ./script/generate utilizatori ai controlorului

Actualizați conținutul acestuia:

# /app/controllers/users_controller.rb UtilizatorControl de clasă < ApplicationController before_filter :login_required, :only => : show def index end end show @user = actual_user sfârșitul privat def login_required excepția cazului în care current_user flash [: error] = 'Trebuie să fii autentificat pentru a vedea această pagină'. redirect_to new_user_session_path sfârșitul capătului final

Ar trebui să observați că current_user este o metodă nedefinită în acest moment. Definiți aceste metode în ApplicationController. Deschideți application_controller.rb și actualizați conținutul:

# aplicație controler de clasă ApplicationController < ActionController::Base helper :all # include all helpers, all the time protect_from_forgery # See ActionController::RequestForgeryProtection for details # From authlogic filter_parameter_logging :password, :password_confirmation helper_method :current_user_session, :current_user private def current_user_session @current_user_session ||= UserSession.find end def current_user @current_user ||= current_user_session && current_user_session.user end end

În acest moment, modelele și controlorii sunt complete, dar nu sunt vizibile. Trebuie să creați vederi pentru un formular de conectare și pentru conținutul public și privat. Vom folosi bijuteriile generatoarelor pentru a crea un aspect de bază.

$ sudo gem instala nifty-generatoare $ ./script/generate nifty_layout

Este timpul să creați formularul de autentificare. Vom folosi un parțial pentru acest lucru, deoarece în viitor vom folosi parțial pentru a face doar formularul de autentificare în caseta modală. Iată codul pentru a crea formularul de autentificare. Este exact același lucru ca și cum ați crea un post blog sau orice alt model.

# creați vizualizările de conectare # /app/views/user_sessions/_form.html.erb <% form_for(@user_session, :url => calea utilizatorului_session_path) face | form | %> <%= form.error_messages %> 

<%= form.label :login %> <%= form.text_field :login %>

<%= form.label :password %> <%= form.password_field :password %>

<%= form.submit 'Login' %> <% end %>

Redați parțial în noua vizualizare:

# /app/views/user_sessions/new.html.erb <% title 'Login Please' %> <%= render :partial => 'formează'% '

Creați câteva pagini de bază pentru conținutul public și privat. Acțiunea index indică conținutul public și afișează conținut privat.

# creați pagina publică falsă # /app/views/users/index.html.erb <% title 'Unobtrusive Login' %> 

Conținutul public cu care se confruntă

<%= link_to 'Login', new_user_session_path %>

Și pentru pagina privată:

# creați pagina privată falsă # /app/views/users/show.html.erb <% title 'Welcome' %> 

Salut <%=h @user.login %>

<%= link_to 'Logout', user_session_path, :method => : șterge%>

Ștergeți fișierul /public/index.html și porniți serverul. Acum vă puteți conecta și deconecta aplicația.

$ ./script/server

Iată câteva capturi de ecran ale aplicației demo. Prima este pagina publică.

Acum, formularul de autentificare

Și pagina privată

În sfârșit, accesul a fost interzis când încercați să vizitați http: // localhost: 3000 / user

Procesul de conectare AJAX

Înainte de a continua, trebuie să înțelegem cum serverul și browserul vor lucra împreună pentru a finaliza acest proces. Știm că va trebui să folosim JavaScript pentru caseta modală și serverul pentru a valida datele de conectare. Să clarificăm modul în care aceasta va funcționa. Utilizatorul dă clic pe linkul de conectare, apoi apare o casetă modală cu formularul de autentificare. Utilizatorul completează formularul și fie redirecționat către pagina privată, fie căsuța modală este reîncărcată cu un nou formular de autentificare. Următoarea întrebare este cum actualizați caseta modală sau spuneți browserului ce trebuie să facă după ce utilizatorul trimite formularul? Rails a răspuns la blocuri. Cu răspuns_to, puteți spune controlorului să difuzeze conținut diferit dacă utilizatorul a solicitat XML, HTML, JavaScript, YAML etc. Deci, atunci când utilizatorul trimite formularul, serverul poate returna JavaScript în execuție în browser. Vom folosi acest lucru pentru a face un nou formular sau o redirecționare. Înainte de scufundări mai adânci, să trecem peste proces în ordine.

  1. Utilizatorul merge la pagina publică
  2. Utilizatorul face clic pe link-ul de autentificare
  3. Se afișează caseta Modal
  4. Utilizatorul completează formularul
  5. Formularul este trimis la server
  6. Serverul returnează JavaScript pentru execuție
  7. Browser execută JavaScript care redirecționează sau actualizează caseta modală.

Acesta este nivelul ridicat. Iată implementarea la nivel scăzut.

  1. Utilizatorul vizitează pagina publică
  2. Pagina publică are un JavaScript care rulează atunci când DOM este gata care atașează JavaScript la link-ul de autentificare. Acest javscript face un XMLHTTPRequest (XHR de acum încolo) către server pentru unele JavaScript. Javascriptul stabilește conținutul casetei modale în formularul HTML. JavaScript, de asemenea, face ceva foarte important. Ea leagă acțiunea de transmitere a formularului către un XHR cu date POST la acțiunea formularului. Aceasta permite utilizatorului să păstreze completarea formularului de autentificare în interiorul casetei modale.
  3. Modal box are acum formularul și JavaScript necesar
  4. User clicks 'Login'
  5. Funcția submit () este numită care face un POST XHR la acțiunea formularului cu datele sale.
  6. Serverul generează JavaScript pentru formular sau pentru redirecționare
  7. Browser-ul primește JavaScript și îl execută. Browserul va actualiza caseta modală sau va redirecționa utilizatorul prin window.location.

Luând un vârf la controlerul AJAX Ready

Să aruncăm o privire la noua structură pentru controlerul UserSessions.

clasa UserSessionsController < ApplicationController layout :choose_layout def new @user_session = UserSession.new end def create @user_session = UserSession.new(params[:user_session]) if @user_session.save respond_to do |wants| wants.html  redirect_to user_path(@user_session.user)  wants.js  render :action => : redirect # JavaScript pentru a face finalul de redirecționare altceva răspuns_de a face | vrea | wants.html render: new wants.js # implicit să creeze.js.erb sfârșitul final sfârșitul privat def alege_layout (request.xhr?)? nil: sfârșitul final al aplicației

După cum puteți vedea structura este diferită. În cazul if save, else conditional, răspuns_to este folosit pentru a reda conținutul corect. want.xx unde xx este un tip de conținut. Implicit Prototype și jQuery solicită text / JavaScript. Acest lucru corespunde cu wants.js. Suntem gata să începem pe partea AJAX. Nu vom folosi niciun plugin, cu excepția celor pentru cutii modale. Vom folosi Facebox pentru jQuery și ModalBox pentru Prototype.

Prototip

Rails a creat suportul pentru Prototype. Ajutoarele JavaScript de la Rail sunt funcții Ruby care generează JavaScript care utilizează Prototype. Această tehnică este cunoscută sub numele de RJS (Ruby JavaScript). Un exemplu este remote_form_for care funcționează ca standardul for_for adaugă unele JS obligate să supună faptul că transmite formularului acțiunii sale utilizând metoda sa cu datele sale. Nu voi folosi RJS în acest articol, deoarece vreau să demonstrez vanilla JS. Cred că prin utilizarea JS pur și eliminarea ajutoarelor JS articolul va fi mai accesibil de către dezvoltatorii mai puțin experimentați. Acestea fiind spuse, puteți realiza cu ușurință acești pași folosind ajutorul RJS / Prototype dacă alegeți.

Adăugarea prototipului la aplicație este foarte ușoară. Când utilizați comanda șine, creează fișierele Prototype și scriptaculous din / public / JavaScripts. Includerea lor este ușoară. Deschideți /app/views/layouts/application.erb și adăugați această linie în interiorul etichetei de cap:

<%= JavaScript_include_tag :defaults %>

JavaScript_include_tag creează etichete de script pentru fișierele implicite în / public / JavaScript, cel mai important fiind prototype.js, effects.js și application.js. effects.js este scriptacul. application.js este un fișier pe care îl puteți utiliza pentru a păstra JS specifice aplicației. Acum avem nevoie de un plugin modular. Vom folosi asta. Este un plugin foarte frumos cutie modală inspirată de OSX. Sursa este găzduită pe GitHub, deci va trebui să clonați și să mutați fișierele în directorul de proiect. De exemplu:

$ cd code $ git clone git: //github.com/okonet/modalbox.git $ cd modalbox # mutați fișierele în directoarele corecte. # mutare modalbox.css în / public / stylesheets # mutare modalbox.js în / public / JavaScripts # mutare spinner.gif în / public / images

Acum includeți foile de stil și JavaScript în aplicația dvs..

 <%= stylesheet_link_tag 'application' %> <%= stylesheet_link_tag 'modalbox' %> <%= JavaScript_include_tag :defaults %> <%= JavaScript_include_tag 'modalbox'%>

Acum, să luăm legătura noastră de conectare pentru a deschide un modbox. Pentru a face acest lucru, trebuie să adăugăm un JavaScript care rulează atunci când DOM este gata care atașează căsuța modală la linkul nostru. Când utilizatorul face clic pe link-ul de conectare, browser-ul va face un GET to / user_sessions / new care conține formularul de autentificare. Linkul de conectare utilizează selectorul # login-link. Actualizați linkul de conectare pentru a utiliza noul id în /app/views/users/index.html.erb. Modificați funcția link_to astfel:

<%= link_to 'Login', new_user_session_path, :id => 'login-link'%>

Asta ne dă un # login-link. Acum, pentru ca JavaScript să atașeze un modbox. Adăugați acest JS în /public/JavaScripts/application.js

document.observe ('dom: loaded', function () $ ('login-link'). : "Conectare", lățime: 500););)

Există câteva simple JS pentru că atunci când utilizatorul face clic pe link, o casetă modală se deschide cu href-ul liniei. Consultați documentația modbox dacă doriți mai multă personalizare. Iată o captură de ecran:

Observați că în caseta modală se arată foarte asemănătoare cu cea a paginii noastre standard. Rails utilizează aspectul aplicației noastre pentru toate răspunsurile HTML. Din moment ce XHR-ul nostru are nevoie de fragmente HTML, are sens să redea fără layout-uri. Reveniți la controlerul de exemplu. Am introdus o metodă pentru determinarea aspectului. Adăugați-le la UserSessionsController pentru a dezactiva aspectul pentru XHR.

clasa UserSessionsController < ApplicationController layout :choose_layout def new @user_session = UserSession.new end def create @user_session = UserSession.new(params[:user_session]) if @user_session.save flash[:notice] = "Login successful!" redirect_to user_path else render :action => : sfarsitul nou sfarsit def distruge current_user_session.destroy flash [: notice] = "Logout succes!" redirect_to root_path sfârșitul privat def alege_layout (request.xhr?)? nil: sfârșitul final al aplicației

Actualizați pagina și dați clic pe link-ul pe care ar trebui să-l primiți astfel:

Completați formularul și vedeți ce se întâmplă. Dacă completați informațiile cu informații nepotrivite, sunteți redirecționat în afara casetei modale. Dacă vă autentificați corect, sunteți redirecționat în mod normal. Conform cerințelor, utilizatorul ar trebui să poată completa formularul din nou și din nou în caseta modală până când se autentifică corect. Cum putem realiza acest lucru? După cum este descris mai înainte, trebuie să folosim AJAX pentru a trimite date către server, apoi utilizați JavaScript pentru a actualiza caseta modală cu formularul sau pentru a face o redirecționare. Știm că modulul de lucru face un GET pentru HTML. După afișarea casetei inițiale, trebuie să scrieți JS care face ca formularul să se supună stilului AJAX. Acest lucru permite ca formularul să se supună în interiorul casetei modale. Pur și simplu adăugarea acestui cod după ce se numește caseta modală nu va funcționa, deoarece este posibil ca XHR să nu fi terminat. Trebuie să folosim apelul după apelul AfterLoad al Modalbox. Iată noul cod:

document.observe ('dom: loaded', function () $ ('login-link'). : 'Login', latime: 500, afterLoad: function () $ ('new_user_session'). ;);)

Formularul # cerere este o metodă convenabilă pentru serializarea și trimiterea formularului printr-un Ajax.Request la adresa URL a atributului de acțiune al formularului - ceea ce este exact ceea ce vrem. Acum puteți completa formularul în interiorul modalului fără să îl închideți. Partea clientului este acum completă. Cum rămâne cu serverul? Clientul trimite un POST care vrea JS înapoi. Serverul trebuie să decidă fie să returneze JavaScript pentru a actualiza formularul, fie pentru a redirecționa. În UserSessionsController vom folosi answer_to pentru a face față cererii JS și o condiție pentru returnarea JS corectă. Să începem prin tratarea cazului de conectare eșuat. Serverul trebuie să returneze JS care actualizează formularul și îi spune noului formular să se prezinte peste ajax. Vom plasa acest șablon în /app/views/users_sessions/create.js.erb. Iată structura pentru noua acțiune de creare:

def create @user_session = UserSession.new (params [: user_session]) dacă @ user_session.save flash [: notice] = "Conectați-vă cu succes!" redirect_to calea utilizator altceva răspuns_de a face | vrea | wants.html render: new wants.js # create.js.erb Sfârșit sfârșit de sfârșit

Acum, să completăm create.js.erb:

$ ( 'MB_content'). Actualizare (“<%= escape_JavaScript(render :partial => '()'); Modalbox.resizeToContent (); $ ('new_user_session'); observați ('submit', function (event) event.stop ();

Mai întâi actualizăm conținutul pentru a include noul formular. Apoi redimensionăm caseta modală. Înainte vom ajaxifica formularul ca și înainte. Voilla, puteți completa formularul de câte ori doriți.

În continuare trebuie să rezolvăm cazul de redirecționare. Creați un fișier nou în /app/views/users_sessions/redirect.js.erb:

 window.location =“<%= user_path %>„;

Actualizați acțiunea de creare pentru a gestiona procesul de redirecționare:

def create @user_session = UserSession.new (params [: user_session]) dacă @ user_session.save răspunde_pentru a face | vrea | wants.html face flash [: notice] = "Conectați-vă cu succes!" redirect_to end user_path wants.js render: redirect termină altceva răspuns_to face | vrea | wants.html render: new wants.js # create.js.erb Sfârșit sfârșit de sfârșit

Si asta e! Acum încercați să vă autentificați cu acreditările corecte și sunteți redirecționat către pagina privată. Pentru învățarea ulterioară, încercați să adăugați un robinet și o notificare prin care utilizatorul îi transmite formularul sau se redirecționează. Aplicația funcționează în continuare dacă utilizatorul a dezactivat JavaScript.

jQuery

Din moment ce am acoperit deja procesul Prototype, așa că nu voi intra în aceleași detalii ca înainte. În schimb, mă voi deplasa rapid descriind JavaScript alternativ pentru a adăuga la aplicație. Vestul jQuery va avea exact aceeași structură ca versiunea Prototype. Tot ce trebuie să schimbăm este ceea ce este în aplicațiile.js, create.js.erb și JavaScript / css include.

Primul lucru pe care trebuie să îl facem este să descărcați jQuery și Facebox. Mutați jQuery în / public / JavaScripts ca jquery.js. Pentru facebox, mutați imaginile în / public / images /, foile de stil în / public / stylesheets și, în final, JS în / public / JavaScripts. Actualizați acum /app/views/layouts/application.html.erb pentru a reflecta modificările:

 <%= h(yield(:title) || "Untitled") %> <%= stylesheet_link_tag 'facebox' %> <%= stylesheet_link_tag 'application' %> <%= JavaScript_include_tag 'jquery' %> <%= JavaScript_include_tag 'facebox' %> <%= JavaScript_include_tag 'application' %> 

Facebox vine cu o foaie de stil implicită care presupune că aveți imaginile în / facebox. Va trebui să actualizați aceste selectori în facebox.css cum ar fi:

#facebox .b fundal: url (/images/b.png);  #facebox .tl fundal: url (/images/tl.png);  #facebox .tr fundal: url (/images/tr.png);  #facebox .bl fundal: url (/images/bl.png);  #facebox .br fundal: url (/images/br.png); 

Acum atașăm cutie de fete la link-ul de autentificare. Deschideți /public/JavaScripts/application.js și folosiți acest lucru:

$ (document) .ready (functie () $ ('# login-link') facebox (loadingImage: '/images/loading.gif', closeImage: '/images/closelabel.gif',); );

Suprascriu setările implicite pentru imagini pentru a reflecta noua cale a imaginii. Porniți severul și treceți la pagina index. Ar trebui să vedeți o cutie poștală frumoasă cu formularul de autentificare:

Următorul lucru pe care trebuie să-l facem este să setăm formularul să se supună prin AJAX. La fel ca înainte, va trebui să folosim callback-uri pentru a executa cod după ce caseta modală este gata. Vom folosi metoda postului jQuery pentru solicitarea XHR. Facebox are un cârlig după dezvăluire pe care îl putem folosi. application.js:

$ (document) .ready (functie () $ ('# login-link'). (document) .bind ('reveal.facebox', functie () $ ('# new_user_session') trimite (function () $ .post (this.action, $ (this) script "); return false;);););

Actualizarea create.js.erb ar trebui să fie suficient de ușoară. Trebuie să actualizăm conținutul casetei și să re-ajaxăm formularul. Iată codul:

$ ('# facebox .content'). html ("<%= escape_JavaScript(render :partial => (funcția () $ .post (this.action, $ (this) .serialize (), null, "script"); return false; );

Si asta e! Iată produsul final:

Descărcarea codului

Puteți obține codul aici. Există sucursale pentru fiecare bibliotecă, astfel încât să puteți verifica versiunile Prototype sau jQuery. Orice întrebări, comentarii, preocupări? Vă mulțumim din nou pentru citire!

  • Urmați-ne pe Twitter sau abonați la Nettuts + RSS Feed pentru cele mai bune tutoriale de dezvoltare web de pe web.
Cod