Ruby 3.0. Ruby och mindre kända metoder för sekretesskontroll
Tomasz Szkaradek
Utvecklingsarkitekt
En av de mest älskade funktionerna i Ruby är dess mycket flexibla syntax. Personligen älskar jag Ruby för hur många möjligheter vi har att definiera klasser och deras egenskaper, och det är vad jag kommer att diskutera i den här artikeln.
Grundläggande lösningar
Låt oss anta att vi använder klassen Foo som har en offentlig metod och en privat metod:
klass Foo
def bar
:fantastisk
slut
privat
def baz
:något_privat
slut
slut
Allt är bra, vi ser en sådan lösning i praktiskt taget alla projekt. Löpande Foo.new.baz kommer att orsaka felet NoMethodError (privat metod 'baz' anropad för # ) och det var det vi menade att göra. Vad händer om vi försöker ändra sparformatet och lägga till private som ett prefix i klassdefinitionen?
klass Foo
def bar
:fantastisk
slut
privat def baz
:något_privat
slut
slut
Som du kan se efter att ha kört kod, det fungerar faktiskt! Varför kan vi ange metodens synlighet innan vi gör den? Därför att när man definierar en metod returnerar def namnet på metoden som en symbol. Detta uttryck är inte bara en del av syntaxen, utan de facto en metod som härrör från klassen Module och som behandlar denna symbol som ett argument. För mer information, se dokumentationen i denna länk. Eftersom det började så enkelt med private, låt oss försöka ändra synligheten för den privata metoden.
klass Foo
def bar
:fantastisk
slut
privat def baz
:något_privat
slut
offentlig :baz
slut
Vad händer när du har kört koden?
irb(main):012:0> Foo.new.baz
=> :något_privat
Framgång! Vår metod för baser blev offentlig eftersom vi gjorde den synlig två gånger. Naturligtvis gäller samma operation för modulerna. Bra, men vad får vi ut av det? Denna funktionalitet ger oss mycket eftersom vi fritt kan ändra synligheten för en metod när vi definierar den, eller till och med ändra synligheten för metoder när vi ärver dem.
Låt oss nu ta en titt på vad Ruby 2.7 kan göra när det gäller att ändra synligheten för aliaser och accessorer.
klass Foo
privat attr_accessor :awesome_variabel
slut
Tyvärr får vi ett fel eftersom den privata metoden förväntar sig symboler och attr_accessor. Koden returnerar nil och därmed är den här metoden inte kompatibel med den privata användningen i Ruby 2.7. Så vad är våra alternativ?
Vi kan använda attr_accessor under nyckelordet private för att få det att fungera, dvs. vi kommer att få ett fel när vi vill hänvisa till awesome_variabelawesome_variabel metod.
klass Foo
privat
attr_accessor :awesome_variabel
slut
Det andra alternativet är att exekvera den privata metoden på metoder som genereras av attr_attribut; i det här fallet måste vi också komma ihåg att ange settern där.
klass Foo
attr_accessor :awesome_variabel
privat :awesome_variabel, :awesome_variabel=
slut
Problem med Attr_ * metoder är inte de enda hindren. Vi kan stöta på samma problem när vi vill skapa ett privat alias.
klass Foo
private alias :bar, :awesome_bar
slut
Ruby 3.0 och vår verksamhet
Lyckligtvis introducerar Ruby 3.0 en stor förändring eftersom synlighetsmetoderna kan ta matrisen som ett argument och metodernas alias, attr_ *, kan återställa matrisen med namnen på de metoder som har definierats. Du kan läsa mer här.
Låt oss nu se några exempel i den senaste euba och kontrollera om ändringarna faktiskt har gjorts och hur vi kan använda dem. I det första exemplet använder vi private före accessorn attr:
klass Foo
privat attr_accessor :awesome_variabel
slut
Ett sådant anrop kommer inte att orsaka fel vid tolkningen av syntaxen och, vilket är viktigt, fantastisk_variabel ochfantastisk_variabel =metoder blir privata. Aliasmetoden gör samma sak, men nu returnerar den också en symbol som namn på den nya metoden och gör den synlig.
klass Foo
private alias :bar, :awesome_bar
slut
Ett intressant faktum är att vi också kan fördjupa oss i ytterligare metoder, t.ex. den fantastiskautskriftsmodul kan anropas mellan private och attrläsare; det är viktigt att en sådan metod returnerar en array med namnen på de metoder som finns på höger sida av uttrycket.
klass Modul
def awesome_print(namn)
sätter namn
namn
slut
slut
klass Foo
private awesome_print attr_reader :awesome_bar
slut
Sammanfattning
Hoppas att du kommer att hitta den här artikeln användbar! I händelse av fler nyheter om Ruby 3.0. läs mer här.