socialgekon.com
  • Põhiline
  • Ux Disain
  • Planeerimine Ja Prognoosimine
  • Innovatsioon
  • Veaotsing
Tagumine Ots

Ajatempli kärpimine: Ruby on Rails ActiveRecord Tale

Testid peaksid aitama vältida rakenduste ebakindlust. Kuid aeg-ajalt võivad testid ise muutuda ketendavaks - ka kõige otsesemad. Siit saate teada, kuidas a Rubiin rööbastel rakenduse, mida toetab PostgreSQL, ja mida me avastasime.

Tahtsime kontrollida, et teatud äriloogika (mida kutsutakse meetodiga perform) ei muuda a calendar mudel (Calendar eksemplar, Ruby on Rails ActiveRecordi mudeli klass), nii et kirjutasime:

let(:calendar) { create(:calendar) } specify do expect do perform # call the business action calendar.reload end .not_to change(calendar, :attributes) end

See möödus ühes arenduskeskkonnas (MacOS), kuid CI-s (Linux) oli see peaaegu alati ebaõnnestunud.



Õnneks õnnestus meil see reprodutseerida teises arenduskeskkonnas (Linux), kus see ebaõnnestus sõnumiga:

expected `Calendar#attributes` not to have changed, but did change from {'calendar_auth_id'=>8, 'created_at'=>2020-01-02 13:36:22.459149334 +0000, 'enabled'=>false, 'events_...t_sync_token'=>nil, 'title'=>nil, 'updated_at'=>2020-01-02 13:36:22.459149334 +0000, 'user_id'=>100} to { 'calendar_auth_id'=>8, 'created_at'=>2020-01-02 13:36:22.459149000 +0000, 'enabled'=>false, 'events_...t_sync_token'=>nil, 'title'=>nil, 'updated_at'=>2020-01-02 13:36:22.459149000 +0000, 'user_id'=>100}

Kas näete midagi kahtlast?

Uurimine

Lähemal uurimisel märkasime, et created_at ja updated_at ajatemplid muudeti expect sees veidi plokk:

{'created_at'=>2020-01-02 13:36:22.459149334 +0000, 'updated_at'=>2020-01-02 13:36:22.459149334 +0000} {'created_at'=>2020-01-02 13:36:22.459149000 +0000, 'updated_at'=>2020-01-02 13:36:22.459149000 +0000}

Sekundite osaosa kärbiti nii, et 13:36:22.459149334 sai 13:36:22.459149000.

Olime kindlad, et perform ei värskendanud calendar objekt, seega koostasime hüpoteesi, et ajatemplid kärbiti andmebaasi abil. Selle testimiseks kasutasime teadaolevalt kõige arenenumat silumisvõtet, s.t. paneb silumise :

let(:calendar) { create(:calendar) } specify do expect do puts 'before perform: #{calendar.created_at.to_f}' perform puts 'after perform: #{calendar.created_at.to_f}' calendar.reload puts 'after reload: #{calendar.created_at.to_f}' end .not_to change(calendar, :attributes) end

Kuid kärpimine ei olnud väljundis nähtav:

before perform: 1577983568.550754 after perform: 1577983568.550754 after reload: 1577983568.550754

See oli üsna üllatav - lisavarustus #created_at oleks pidanud olema sama väärtus kui atribuudi räsiväärtus attributes['created_at'] Et olla kindel, et printisime väites kasutatud sama väärtust, muutsime juurdepääsu meetodit created_at

Aksessori calendar.created_at.to_f kasutamise asemel läksime üle selle otsimisele otse atribuutide räsist: calendar.attributes['created_at'].to_f. Meie kahtlused calendar.reload suhtes kinnitati!

before perform: 1577985089.0547702 after perform: 1577985089.0547702 after reload: 1577985089.05477

Nagu näete, helistades perform ei muutnud created_at, kuid reload tegi.

Veendumaks, et muudatus ei toimu mõnes muus calendar eksemplaris ja siis olles päästetud, tegime veel ühe katse. Laadisime uuesti calendar enne testi:

let(:calendar) { create(:calendar).reload } specify do expect do perform calendar.reload end .not_to change(calendar, :attributes) end

See muutis testi roheliseks.

Parandus

Teades, et andmebaas kärbib meie ajatemplid ja ebaõnnestub testide tegemine, otsustasime kärpimise ära hoida. Lõime DateTime objekt ja ümardas selle tervete sekunditeni. Seejärel kasutasime seda objekti Railsi aktiivse kirje ajatemplite selgesõnaliseks määramiseks. See muudatus fikseeris ja stabiliseeris testid:

let(:time) { 1.day.ago.round } let(:calendar) { create(:calendar, created_at: time, updated_at: time) } specify do expect do perform calendar.reload end .not_to change(calendar, :attributes) end

Põhjus

Miks see juhtus? Aktiivse kirje ajatemplid on rööbaste poolt seatud ’ActiveRecord::Timestamp moodul kasutades Time.now . Time täpsus on OS-st sõltuv ja nagu dokumentides öeldakse, võib sisaldada murdosa sekundeid .

Testisime Time.now eraldusvõime MacOS-is ja Linuxis koos skriptiga, mis loeb osade pikkuste sagedusi:

pry> 10000.times.map { Time.now.to_f.to_s.match(/.(d+)/)[1].size }.group_bya.map [k, v.count].to_h # MacOS => {6=>6581, 7=>2682, 5=>662, 4=>67, 3=>7, 2=>1} # Linux => {6=>2399, 7=>7300, 5=>266, 4=>32, 3=>3}

Nagu näete, oli umbes 70% Linuxi ajatemplitest pärast kümnendkohtade täpsust seitse numbrit, MacOS-is ainult 25%. See on põhjus, miks testid läbisid suurema osa ajast MacOS-is ja ebaõnnestusid enamasti Linuxis. Võib-olla olete märganud, et testväljundil oli üheksakohaline täpsus - seda seetõttu, et RSpec kasutab Time#nsec ajaväljundi vormindamiseks.

Kui Railsi mudelid salvestatakse andmebaasi, salvestatakse kõik nende ajatemplid PostgreSQL-i tüüpi nimega timestamp without time zone, mis on mikrosekundiline eraldusvõime - st kuus numbrit pärast koma. Niisiis, kui 1577987974.6472975 saadetakse PostgreSQL-i, see kärbib murdosa viimase numbri ja salvestab selle asemel 1577987974.647297

Küsimused

Ikka on küsimus, miks calendar.created_at ei laaditud uuesti, kui helistasime calendar.reload, kuigi calendar.attributes['created_at'] laaditi uuesti.

Samuti on Time täpsuskatse on natuke üllatav. Eeldasime, et MacOS-is on maksimaalne täpsus kuus. Me ei tea, miks see nii on mõnikord on seitse numbrit. Mis üllatas meid rohkem, oli viimaste numbrite väärtuse jaotus:

pry> 10000.times.map { Time.now}.map t.to_f.to_s.match(/.(d+)/)[1] .select.group_bye.map [k, v.size].to_h # MacOS => {'9'=>536, '1'=>555, '2'=>778, '8'=>807} # Linux => {'5'=>981, '1'=>311, '3'=>1039, '9'=>309, '8'=>989, '6'=>1031, '2'=>979, '7'=>966, '4'=>978}

Nagu näete, on MacOS-i seitsmes number alati 1, 2, 8 või 9.

Kui teate vastust mõlemale küsimusele, jagage palun meiega selgitust.

Tulevik

Asjaolu, et Ruby on Rails ’ Aktiivne kirje Rakenduse poolel genereeritud ajatemplid võivad kahjustada ka seda, kui neid ajatempleid kasutatakse andmebaasi salvestatud sündmuste usaldusväärseks ja täpseks järjestamiseks. Kuna rakendusserveri kellad võidakse desünkroonida, järjestavad sündmused created_at võivad ilmuda teistsuguses järjekorras kui need tegelikult aset leidsid. Saada usaldusväärsem käitumine , oleks parem lasta andmebaasiserveril ajatemplid käsitseda (nt PostgreSQL-id now() ).

See on aga lugu, mis on väärt teist artiklit.


Eriline tänu Gabriele Renzi selle artikli loomisel aitamise eest.

Põhitõdede mõistmine

Mis on rubriigis ActiveRecord?

ActiveRecord on objektide-seoste kaardistamise teek, mille pakub Ruby on Rails. See võimaldab teil objekte andmebaasis säilitada, seejärel salvestatud andmeid hankida ja objekte kiirendada.

Mis on Active Recordi juurutamine?

Active Record on ettevõtte arhitektuurimuster, mida kasutatakse relatsioonide andmebaasides mälus olevate objektide püsimiseks. Rakenduse Ruby on Rails rakenduses jälgib ActiveRecord muudatusi Railsi mudeli atribuutides. Mudeli salvestamisel saadab ActiveRecord muudatused koos vajalike ajatemplitega andmebaasi.

Miks on ajatempel oluline?

Vaikimisi salvestab ActiveRecord kaks ajatemplit: created_at (aeg, mil mudel esmakordselt salvestati) ja updated_at (aeg, mil mudel viimati salvestati). Need pakuvad põhilisi auditivõimalusi ja võimaldavad rakendustel sorteerida mudeleid alates uusimatest või viimati uuendatud mudelitest.

Mis on ajatempel PostgreSQL-is?

Ajatempel on PostgreSQL-i andmetüüp, mis salvestab nii kuupäeva kui ka kellaaega. Selle eraldusvõime ja täpsus on ühe mikrosekundiga, mis tähendab, et see hoiab sekundite murdosa kuni kuus numbrit.

Mis andmebaasi Ruby on Rails kasutab?

Ruby on Rails võimaldab arendajatel kasutada enamikku populaarsetest andmebaasidest. Vaikimisi kasutab Ruby on Rails teeki ActiveRecord, mis toetab DB2, Firebird, FrontBase, MySQL, OpenBase, Oracle, PostgreSQL, SQLite, Microsoft SQL Server ja Sybase.

Scala vs Java: Miks peaksin Scalat õppima?

Tehnoloogia

Scala vs Java: Miks peaksin Scalat õppima?
Kasvav kasv: tehke selle avatud lähtekoodiga oma kohordianalüüs

Kasvav kasv: tehke selle avatud lähtekoodiga oma kohordianalüüs

Andmeteadus Ja Andmebaasid

Lemmik Postitused
Kuidas veenda e-kaubanduse ostjaid UX-disaini abil
Kuidas veenda e-kaubanduse ostjaid UX-disaini abil
Sissejuhatus PHP 7-sse: mis on uut ja mis kadunud
Sissejuhatus PHP 7-sse: mis on uut ja mis kadunud
Mitme põlvkonna tööjõu võimu vabastamine, 1. osa: kas vanusel on tähtsust?
Mitme põlvkonna tööjõu võimu vabastamine, 1. osa: kas vanusel on tähtsust?
Tööstuse ärkamine: madratsitööstuse häired
Tööstuse ärkamine: madratsitööstuse häired
Sügav sukeldumine tugevdamise õppesse
Sügav sukeldumine tugevdamise õppesse
 
Lemmikloomade pildistamine iPhone'is: kuidas teha kõige armsamaid lemmikloomafotosid
Lemmikloomade pildistamine iPhone'is: kuidas teha kõige armsamaid lemmikloomafotosid
Juhend npm: paketihaldur Node.js
Juhend npm: paketihaldur Node.js
Juhend: kuidas tõhusat UX-i uuringut läbi viia
Juhend: kuidas tõhusat UX-i uuringut läbi viia
Monoreposi juhend esiotsa koodi jaoks
Monoreposi juhend esiotsa koodi jaoks
Flutter juhendaja: kuidas luua oma esimene Flutter App
Flutter juhendaja: kuidas luua oma esimene Flutter App
Kategooriad
Disaineri EluKasumlikkus Ja TõhususJaotatud VõistkonnadPlaneerimine Ja PrognoosimineInvestorid Ja RahastamineFinantsprotsessidladustamineTöö TulevikUx DisainBrändikujundus

© 2023 | Kõik Õigused Kaitstud

socialgekon.com