5 eksempler på hvordan Ruby kan brukes på best mulig måte
Har du noen gang lurt på hva vi kan gjøre med Ruby? Det er nok ingen grenser, men vi snakker gjerne om noen mer eller mindre kjente tilfeller...
Før vi begynner å lage en bang-metode, la oss lære hva denne typen metoder egentlig er og hva som kjennetegner dem. La oss starte med det faktum at det ikke finnes noen entydig definisjon av denne typen metoder. Enkelt sagt er en bang-metode en metode med et utropstegn på slutten.
Vi kan ofte støte på en uttalelse om at bang-metoden på sett og vis er en farlig metode, og utropstegnet på slutten av definisjonen forteller oss at vi skal være på vakt når vi bruker denne metoden. La oss se: Hva er egentlig denne trusselen når det gjelder disse metodene, og hva kjennetegner dem?
Et av de mest populære kjennetegnene ved denne typen metoder er at de vanligvis endrer publikum. La oss ta en titt på map! metoden som et eksempel. Ifølge dokumentasjonen påkaller map! metoden den gitte blokken én gang for hvert element i self, og erstatter elementet med verdien som returneres av blokken, og hvis ingen blokk er gitt, returneres en Enumerator i stedet.
arry = [1, 2, 3, 4, 5]
arry.object_id => 280
arry.map! {|num| num**num } => [1, 4, 27, 256, 3125]
arry.map! => # [1, 2, 3, 4, 5]:map!
arry.map! {|n| n } => [1, 4, 27, 256, 3125]
arry.object_id => 280
Som vi kan se, forblir object_id uendret. Faren ved å bruke en slik metode virker derfor åpenbar. Hvis vi i vår kode vi har brukt variabelen arry et annet sted, vil map! endre den. Dette kan føre til at programmet vårt fungerer på en uønsket måte eller til og med krasjer.
Det finnes objekter i Ruby som ikke kan endres, for eksempel forekomster av klassene Integer, Float og Symbol. Mens du arbeider på en prosjektkan du også møte den såkalte magiske kommentaren som går slik:
frozenstrengliteral: true
Hvis du forsøker å endre String-mottakeren i koden der en slik kommentar er brukt, vil du få en feilmelding som denne:
'abc'.upcase!
FrozenError (kan ikke endre frossen streng)
Interessant nok var det planer om å innføre uforanderlig String i Ruby 3.0, men ble det besluttet å ikke gjøre denne endringen. Det er imidlertid ikke alle bang-metoder som endrer mottakeren, så du bør alltid sjekke i dokumentasjonen hva slags fare du kan forvente ved bruk av en bestemt metode.
Et annet særtrekk ved disse metodene er at mange av dem utløser et unntak. Et eksempel på en slik metode er ActiveRecord::FinderMethods#first! I følge dokumentasjonen er metoden first! den samme som first, men gir ActiveRecord::RecordNotFound hvis ingen post blir funnet. Legg merke til at first! ikke aksepterer noen argumenter.
Fil activerecord/lib/activerecord/relation/findermethods.rb, linje 128
def first!
first || raiserecordnotfoundexception!
end
ActiveRecord::FinderMethods#first-metoden som brukes ovenfor, ser imidlertid slik ut:
Fil activerecord/lib/activerecord/relation/findermethods.rb, linje 116
def first(limit = nil)
checkreorderdeprecation med mindre lastet?
if limit
findnthwithlimit(0, limit)
else
findnth 0
end
end
Takk så eksemplene ovenfor, vi ser faren ved å bruke førstnevnte. Hvis vi bruker ActiveRecord::FinderMethods#find! og den ikke finner en passende post i databasen, vil den returnere ActiveRecord::RecordNotFound, noe som kan føre til at programmet vårt slutter å fungere.
Vi må imidlertid huske at dette ikke betyr at hvis en metode ikke har et utropstegn på slutten, er den trygg og ikke vil utløse unntaket eller endre mottakeren.
I Ruby on Rails 6.0 ble det innført et nytt metodepar: ActiveRecord::Persistence::ClassMethods#insert_all
og ActiveRecord::Persistence::ClassMethods#insert_all!
Den første av disse metodene viser allerede en viss grad av fare. Vel, ifølge dokumentasjonen, sett innsetter inn flere poster i databasen i en enkelt SQL INSERT-setning. Den instansierer ingen modeller og utløser heller ikke ActiveRecord-tilbakekall eller valideringer. Insert-setningenall! utløser i tillegg ActiveRecord::RecordNotUnique hvis noen rader bryter med en unik indeks på tabellen. I så fall blir ingen rader satt inn. Dette betyr at den første av disse metodene vil lagre alle poster unntatt de som bryter med den unike indeksen, mens den andre (farligere) metoden vil utløse et unntak og ikke lagre noen av postene i databasen.
Mange metoder er farlige å bruke, selv om de ikke har et utropstegn på slutten. For eksempel ActiveRecord::FinderMethods#find. I følge dokumentasjonen vil ActiveRecord::RecordNotFound vises hvis en eller flere poster ikke kan finnes for de forespurte id-ene.
Vi ser at selv om denne metoden har samme faregrad som ActiveRecord::FinderMethods#first! har den ikke noe utropstegn.
Det samme gjelder når det gjelder å endre mottakeren. Array.delete (som dokumentert) sletter for eksempel alle elementer fra self som er lik object, og returnerer det siste slettede elementet, eller nil hvis det ikke finnes noen matchende elementer.
a = [1, 2, 3, 4, 5]
a.object_id #=> 320
a.delete(2) #=> 2
a #=> [1, 3, 4, 5]
a.delete(6) #=> nil
a.object_id #=> 320
Du kan tydelig se at objektet har blitt endret. Felles for de to metodene er at de ikke har et tilsvarende utropstegn. Hvis metoden vi ønsker å lage har den typen farer jeg nevnte ovenfor, trenger den derfor ikke umiddelbart å ha et utropstegn på slutten. Dessuten er det lurt å lage en bang-metode hvis det allerede finnes en metode med samme navn som er mindre farlig enn den metoden du vil lage.
Man kan lure på hvorfor man i det hele tatt skal bruke disse farlige metodene, spesielt siden vi vanligvis har mindre farlige motstykker. En av fordelene kan for eksempel være forbedret kodeytelse takket være at antallet objekter som opprettes, reduseres. Her kan du lese mer om hvordan du kan øke ytelsen i Rails.
Når det gjelder å utløse unntak, kan det å bruke create-metoden i stedet for den farlige create! føre til en situasjon der en feil i applikasjonen vår er vanskelig å oppdage fordi postene ikke blir skrevet inn i databasen. Så hvis vi er sikre på at parameterne vi sender til denne metoden er riktige, bør vi bruke create! -metoden, som vil utløse et unntak hvis posten av en eller annen grunn ikke blir lagret i databasen.
Konklusjonen er enkel, og den lyder som følger: Fornuftig bruk av slike metoder kan forbedre ytelsen og kvaliteten på koden vår. Vi må imidlertid alltid huske at feil bruk kan føre til at koden ikke kjører som den skal.
Hvis du vil lage din egen farlige metode, må du gå gjennom en viss beslutningsprosess. Først må man spørre seg om det allerede finnes en metode med samme navn som den man ønsker å lage, men som er mindre farlig. Du kan også vurdere å lage et par metoder der den ene er ekvivalent med den andre, bare farligere.
Det er ingen vits i å lage en bang-metode hvis motstykket uten utropstegn ikke finnes. Det finnes metoder som er farlige fordi de endrer objektet eller utløser et unntak, men som ikke har et utropstegn på slutten av navnet. Hvis du oppretter en bang-metode uten noe tilsvarende, vil det forvirre en programmerer som bruker koden din. Vedkommende ville ikke være i stand til å si hva som er farlig med denne metoden, og hvorfor den fortjener et utropstegn på slutten av navnet.
For det andre bør vi vurdere hva slags farer vi snakker om. Ut fra eksemplene ovenfor kan vi konkludere med at den vanligste typen fare er endring av selve objektet (i stedet for å lage en kopi) eller å utløse et unntak. Dette er selvfølgelig ikke en regel, men snarere et resultat av å analysere metodene som er definert i Ruby og Ruby on Rails. Vi kan for eksempel vurdere implementeringen av et metodepar der metoden uten utropstegn vil lagre posten i databasen, mens metoden med utropstegnet vil hoppe over valideringen av denne posten. I dette tilfellet er det tydelig hvor den potensielle faren ved å bruke slike metoder ligger.
En oppsummering av kunnskapen om bang-metodene peker mot disse konklusjonene: Den første metoden med utropstegnet har en mindre truende
motstykket uten utropstegn, for det andre utfører metoden med utropstegn en farlig handling, f.eks. endrer mottakeren eller utløser et unntak.
Konklusjonen er at forståelsen av begrepet bang-metoder i Ruby programvareutvikling kan forbedre kodingsferdighetene dine og gjøre kodebasen mer oversiktlig. Bang-metodersom er merket med et utropstegn på slutten av navnet, indikerer en destruktiv eller potensielt farlig versjon av en metode. Som konvensjon brukes bang motstykke av en metode bør brukes med forsiktighet, ettersom den kan endre objekter direkte, uten å opprette en separat kopi. Dette kan være spesielt nyttig når man har å gjøre med objekter som kan endres, eller når ytelsesoptimalisering er viktig. Det er imidlertid viktig å være forsiktig når du bruker bang-metoder, da de kan ha utilsiktede konsekvenser hvis de ikke håndteres på riktig måte. Det er også verdt å merke seg at ikke alle metoder har en bang-versjonog deres tilstedeværelse bør vurderes fra sak til sak. Med kunnskap om når og hvordan du skal opprette bang-metoder, kan du bruke dette kraftige verktøyet effektivt og skrive ren og effektiv kode som oppfyller dine spesifikke krav.