Caracteristici Rails 6: Ce este nou și de ce contează

Publicat: 2022-03-11

După cum majoritatea fanilor Ruby on Rails știu, Rails 6 va veni în curând și va aduce o serie de funcții și modificări așteptate cu nerăbdare. Scopul acestui articol este de a vă familiariza cu caracteristicile cheie care au fost adăugate la Rails 6 și de a sublinia modul în care acestea vă pot ajuta să vă îmbunătățiți aplicațiile, economisind astfel timp valoros de dezvoltare.

Pentru început, rețineți că Rails 6 necesită Ruby 2.5+ și baze de date actualizate. Așadar, asigurați-vă că aveți un plan pentru a vă actualiza sistemele în consecință, în cazul în care nu ați făcut-o deja.

Deci, care sunt aceste caracteristici noi? Iată o scurtă recapitulare a caracteristicilor cheie ale Rails 6 pe care probabil le veți folosi în viitor:

Testarea pe șine 6

În calitate de dezvoltatori profesioniști Ruby on Rails, ne propunem să asigurăm o acoperire maximă pentru codul nostru. Cu toate acestea, testarea devine o activitate obositoare atunci când cazurile noastre de testare devin „grele” și trebuie să așteptăm câteva minute, sau chiar ore, doar pentru a executa cazurile de testare.

Testare paralelă

Ei bine, Rails 6 are un răspuns aici. A adăugat o metodă de parallelize la ActiveSupport::TestCase care vă permite să paralelizați suita de teste cu procese bifurcate.

Deci, ceea ce trebuie să faceți pentru a paraleliza procesele pentru testele dvs. este să adăugați acest lucru la test_helper.rb :

 parallelize(workers: 2)

Alternativ, putem înlocui comenzile noastre utilizate anterior pentru rularea testelor. De exemplu, bin/rails test OR bin/rspec spec poate fi acum înlocuit cu PARALLEL_WORKERS=15 rails test OR PARALLEL_WORKERS=15 rspec spec .

În consecință, puteți modifica comenzile pentru rularea suitelor de testare pe diferite platforme CI, cum ar fi Travis, Gitlab, CircleCI și altele.

Există, de asemenea, cârlige atunci când fiecare proces este creat/distrus, care pot fi folosite după cum urmează:

 class ActiveSupport::TestCase parallelize_setup do |worker| # setup databases end parallelize_teardown do |worker| # cleanup databases end parallelize(workers: :number_of_processors) end

Notă: dacă doriți să aflați mai multe, puteți consulta Ghiduri șine pentru detalii suplimentare.

Testarea cablului de acțiune

Deoarece vorbeam despre testare eficientă, să înțelegem și cum s-a îmbunătățit Action Cable, una dintre cele mai importante caracteristici ale Rails 5. Acum este posibil să testați Action Cable la orice nivel: conexiuni , canale și transmisii .

Testele de conexiune urmăresc să verifice dacă identificatorii unei conexiuni sunt alocați corect sau dacă orice solicitare de conexiune necorespunzătoare este respinsă:

 class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase test "connects with params" do connect params: { user_id: 42 } OR cookies.signed[:user_id] = "42" connect assert_equal connection.user_id, "42" end test "rejects connection without params" do assert_reject_connection { connect } end end

Testele de canal pot fi scrise pentru a verifica dacă utilizatorii se pot abona la canale și dacă canalul are un flux:

 class ChatChannelTest < ActionCable::Channel::TestCase test "subscribes and stream for room" do # Simulate a subscription creation by calling `subscribe` subscribe room: "15" # You can access the Channel object via `subscription` in tests assert subscription.confirmed? assert_has_stream "chat_15" end end

Difuzarea către canale poate fi testată astfel:

 # app/jobs/chat_relay_job.rb class ChatRelayJob < ApplicationJob def perform_later(room, message) ChatChannel.broadcast_to room, text: message end end # test/jobs/chat_relay_job_test.rb require 'test_helper' class ChatRelayJobTest < ActiveJob::TestCase include ActionCable::TestHelper test "broadcast message to room" do room = rooms(:all) assert_broadcast_on(ChatChannel.broadcasting_for(room), text: "Hi!") do ChatRelayJob.perform_now(room, "Hi!") end end end

Notă: Mai multe sfaturi despre cum să testați pot fi găsite aici.

Inserare în vrac și Upsert

La un moment dat, cu toții trebuie să inserăm mai multe înregistrări dintr-o singură mișcare și am găsit multe soluții atunci când facem acest lucru. Ei bine, Rails 6 vine cu o nouă metodă din cutie insert_all , similar cu update_all .

Nu va declanșa niciun apel invers și va executa o singură interogare SQL. Există o metodă suplimentară upsert_all care vă permite să utilizați operația de upsert care este expusă de multe baze de date moderne precum Postgres. Deci, acum puteți reduce interogările de inserare și puteți optimiza codul. De asemenea, spuneți la revedere pietrelor prețioase folosite anterior, cum ar fi activerecord-import .

O singură interogare INSERT SQL este pregătită prin aceste metode și o singură instrucțiune SQL este trimisă în baza de date, fără a instanția modelul sau a invoca apeluri și validări Active Record. Este, de asemenea, posibil să se definească criterii atunci când o cheie primară - indecșii unici sau constrângerile unice sunt încălcate cu o opțiune de a omite sau de a rula interogări de tip upsert.

Câteva exemple sunt mai jos:

 result = Article.insert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, #...snip... ], returning: %w[ id title ], unique_by: :index_articles_on_title_and_author ) result = Article.upsert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, { id: 1, .... }, # duplicate 'id' here { id: 2, .... }, { id: 3, .... }, # duplicate 'title' and 'author' here { id: 4, .... }, { id: 5, .... }, # duplicate 'slug' here { id: 6, .... } ] )

Metodele insert , insert! și upsert sunt învelișuri în jurul insert_all , insert_all! și, respectiv, upsert_all .

Notă: Există un articol foarte bun care discută interogări în bloc cu privire la diferite baze de date. Dacă aveți nevoie de informații suplimentare, asigurați-vă că le verificați.

Comutarea între mai multe baze de date

Una dintre caracteristicile principale pe care multe aplicații mari le vor aprecia este aceasta: Rails 6 a adăugat în cele din urmă suport pentru mai multe baze de date pentru aplicația dvs., încorporate și gata de funcționare, din cutie!

Diagrama de comutare între baze de date

Desigur, alegerea de proiectare este încă a dvs., indiferent dacă doriți să împărțiți aplicația dvs. în mai multe microservicii, fiecare având o bază de date separată, sau să luați o rută monolitică sau să adăugați mai multe replici de citire pentru aplicația dvs.

Cu toate acestea, capacitatea de a face acest lucru într-un mod atât de ușor are potențialul de a economisi mult timp pe frontul dezvoltării.

Deci, așa va arăta noul fișier database.yml :

 development: primary: database: my_primary_db user: root primary_replica: database: my_primary_db user: ro_user replica: true animals: database: my_animals_db user: root animals_replica database: my_animals_db user: ro_user replica: true

Iată modalități interesante de a specifica cum să comutați la diferite baze de date:

 class AnimalsModel < ApplicationRecord self.abstract_class = true connects_to database: { writing: :animals_primary, reading: :animals_replica } end class Dog < AnimalsModel # connected to both the animals_primary db for writing and the animals_replica for reading end

Iată pagina oficială GitHub, care este, de asemenea, bine documentată. Personal, aștept cu nerăbdare să am capabilități de fragmentare a bazei de date și în viitoarele actualizări Rails (ceva de genul acesta).

Căsuța poștală de acțiune

O altă caracteristică interesantă Rails 6 este adăugarea Action Mailbox, care adaugă capacitatea de a direcționa e-mailurile primite către controler, cum ar fi cutiile poștale pentru procesare în Rails.

Action Mailbox include intrări pentru Mailgun, Mandrill, Postmark și SendGrid. De asemenea, puteți gestiona e-mailurile primite direct prin intrările încorporate Exim, Postfix și Qmail. Acum, probabil vă puteți imagina potențialele beneficii fără a intra în mai multe detalii. Poate fi procesarea directă a e-mailurilor de la un birou de asistență până la automatizarea biletelor de asistență — Rails 6 permite clienților să răspundă direct prin e-mail și multe, multe altele. Pardoseala este deschisă pentru a explora această caracteristică și a veni cu o abordare care este ideală pentru aplicația dvs.

Iată un mic exemplu pentru a înțelege cum să utilizați Action Mailbox:

 COMMENTS_REGEX = /^comment\+(.+)@example\.com/i # app/mailboxes/application_mailbox.rb class ApplicationMailbox < ActionMailbox::Base routing COMMENTS_REGEX => :comments end # app/mailboxes/comments_mailbox.rb class CommentsMailbox < ApplicationMailbox def process user = User.find_by(email: mail.from) post_uuid = COMMENTS_REGEX.match(mail.to)[1] post = Post.find_by(uuid: post_uuid) post.comments.create(user: user, content: mail.body) end end

De asemenea, noul mod de configurare a e-mailurilor este după cum urmează (luând exemplul Sendgrid):

 # config/environments/production.rb config.action_mailbox.ingress = :sendgrid

Utilizați rails credentials:edit pentru a adăuga parola la datele de conectare criptate ale aplicației dvs. sub action_mailbox.ingress_password , unde Action Mailbox o va găsi automat:

 action_mailbox: ingress_password: …

Configurați SendGrid Inbound Parse pentru a redirecționa e-mailurile primite către /rails/action_mailbox/sendgrid/inbound_emails cu numele de utilizator actionmailbox și parola pe care ați generat-o anterior. Dacă aplicația dvs. se află la https://example.com , ați configura SendGrid cu următoarea adresă URL:

 https://actionmailbox:[email protected]/rails/action_mailbox/sendgrid/i

În cazul în care doriți să explorați acest lucru în continuare, Rails are deja un ghid despre asta aici.

Zeitwerk

Zeitwerk este noul încărcător de cod pentru Ruby. Având în vedere o structură de fișiere convențională, Zeitwerk încarcă clasele și modulele proiectului dvs. la cerere, ceea ce înseamnă că nu trebuie să scrieți apeluri necesare pentru propriile fișiere. Pentru a-l activa în Rails 6, puteți face următoarele:

 config.autoloader = :zeitwerk

Puteți citi mai multe despre Zeitwerk aici.

Sfaturi pentru optimizare

Sunteți îngrijorat de faptul că unele dintre interogările dvs. durează prea mult să fie executate? Ei bine, acum aveți o modalitate de a defini time-out-uri și pentru interogările dvs.

Următoarea instrucțiune va ridica o excepție StatementTimeout dacă executarea interogării durează mai mult decât în ​​mod normal:

 User.optimizer_hints("MAX_EXECUTION_TIME(5000)").all

Este acceptat de MySQL și va trebui să explorați dacă baza de date îl acceptă.

Trunchiază baza de date

Dar semănarea datelor? Următoarea declarație va trunchia toate tabelele bazei de date și apoi puteți continua la însămânțarea datelor:

 rails db:truncate_all

Nu mai ștergeți bazele de date pentru a începe. Probabil veți fi de acord că aceasta este o soluție elegantă și rapidă.

Text de acțiune

Poate că o altă caracteristică notabilă pentru multe aplicații care joacă cu editorii WYSIWYG este adăugarea suportului pentru editorul Trix nativ în aplicațiile Rails 6. Aceasta va fi cu siguranță o actualizare/adăugare bună pentru multe proiecte.

Majoritatea editoarelor HTML WYSIWYG au o amploare enormă - implementarea fiecărui browser are propriul set de erori și ciudatenii, iar dezvoltatorii JavaScript sunt lăsați să rezolve inconsecvențele. Trix ocolește aceste inconsecvențe tratând contenteditable ca pe un dispozitiv I/O: când intrarea se îndreaptă către editor, Trix convertește acea intrare într-o operațiune de editare pe modelul său intern de document, apoi redă din nou acel document înapoi în editor. Acest lucru îi oferă Trix control complet asupra a ceea ce se întâmplă după fiecare apăsare a tastei.

Instalare:

 rails action_text:install # app/models/message.rb class Message < ApplicationRecord has_rich_text :content end

Puteți explora Action Text în mai multe detalii în documentația oficială, aici.

Securitate

Nicio actualizare serioasă nu este completă fără câteva îmbunătățiri de securitate. Nici Rails 6 nu dezamăgește din punct de vedere al securității. Prima actualizare notabilă de securitate este adăugarea de suport pentru Autorizarea gazdei .

Host Authorization este un nou middleware care protejează împotriva atacurilor de relegare a DNS, permițând în mod explicit gazdelor cărora li se poate trimite o solicitare. Acest lucru înseamnă că puteți defini gazdele care vă pot accesa aplicațiile.

O altă actualizare de securitate este menită să împiedice atacurile care încearcă să copieze valoarea semnată/criptată a unui cookie și să o utilizeze ca valoare a altui cookie. O face prin păstrarea numelui cookie-ului în câmpul scop, care este apoi semnat/criptat împreună cu valoarea cookie-ului. Apoi, pe partea de server, verificăm numele cookie-urilor și renunțăm la orice cookie atacat. Activați action_dispatch.use_cookies_with_metadata pentru a utiliza această funcție, care scrie cookie-uri cu noul scop și metadate de expirare încorporate.

Webpack ca Bundler implicit

Așa cum este standardul de facto cu multe cadre JavaScript moderne pentru dezvoltarea front-end, Rails 6 a adăugat Webpack ca bundler JavaScript implicit prin webpacker gem, înlocuind pipeline-ul Rails Asset. Aceasta este o completare relativ simplă și nu vom intra în multe detalii. Este suficient să spunem că Webpack va aduce o oarecare ușurare dezvoltatorilor front-end suprasolicitați.

Prevenirea condițiilor de cursă

Rails 6 are o nouă metodă care este folosită pentru a preveni SELECT/INSERT condițiile de cursă în codul nostru (sunt sigur că mulți cititori au avut ghinionul de a întâlni condiții de cursă în timp ce își scalau proiectul). Aici este firul GitHub în cazul în care aveți nevoie de informații suplimentare.

Tabelul de bază trebuie să aibă coloanele relevante definite cu constrângeri unice. În timp ce evităm condiția de cursă între SELECT → INSERT din #find_or_create_by , avem de fapt o altă condiție de concurență între INSERT → SELECT, care poate fi declanșată dacă un DELETE între aceste două instrucțiuni este rulat de un alt client. Dar, pentru majoritatea aplicațiilor, aceasta este o condiție pe care este mult mai puțin probabil să o atingem.

Acreditări în șine 6

Încă din zilele Rails 5.2, acreditările au fost denumite un nou „mod Rails” de a trata informațiile sensibile, cu promisiunea de a scăpa de fișierele infame .env odată pentru totdeauna. Cu acreditările, cheile criptate pentru servicii terțe pot fi verificate direct în controlul sursei.

Până acum, totuși, Rails folosea același fișier criptat pentru toate mediile, ceea ce a făcut ca tratarea diferitelor chei în dezvoltare și producție să fie puțin dificilă, mai ales atunci când ai de-a face cu proiecte mari și cod moștenit.

În Rails 6, acest lucru este în sfârșit rezolvat cu suport pentru acreditările pe mediu. Din nou, detalii suplimentare pot fi explorate pe firul oficial GitHub.

Este Rails 6 o actualizare bună?

Da, și de fapt Rails 6 ar putea fi descris ca o actualizare majoră, deși puțini l-ar numi un schimbător de joc. Deoarece Ruby on Rails există de ani de zile, puțini oameni se așteaptă la schimbări revoluționare, dar a șasea sa încarnare aduce multe la masă.

Unele funcții lansate în Rails 6 par îmbunătățiri minore, în timp ce altele au potențialul de a economisi mult timp de dezvoltare, de a îmbunătăți securitatea, robustețea și așa mai departe. Concluzie: Rails este matur, mulți dezvoltatori rămân entuziasmați de viitorul său și, odată cu lansarea Rails 6, a devenit și mai bun.

Desigur, această listă de caracteristici Rails 6 este incompletă și pentru a vedea setul complet de modificări, trebuie să verificați jurnalul de modificări. În plus, există o mulțime de deprecieri pe care ar trebui să le luați în considerare. În cele din urmă, dacă insistați să treceți peste fiecare modificare și să vă actualizați, vă rugăm să citiți notele complete de lansare.