Ruby er et av de mest populære språkene som brukes på nettet. Vi har startet en ny sesjon her på Nettuts + som vil introdusere deg til Ruby, samt de flotte rammer og verktøy som går sammen med Ruby-utviklingen. I dag ser vi på DataMapper-smykkene for å komme seg opp med en database i Ruby.
DataMapper er en ORM: en Objekt-Relasjonell Mapping. I utgangspunktet er det et bibliotek som lar deg jobbe med databasen fra objektorienterte koden. Det er absolutt ingen SQL i denne opplæringen i det hele tatt. En ORM bruker imidlertid en vanlig database under dekslene; vi bruker sqlite3 i dag, men du kan bare bruke en annen adapter for å jobbe med en mysql, postgresql eller annen database.
I Sang med Sinatra - The Recall App, introduserte Dan Harper deg til DataMapper. I denne opplæringen skal vi ta en dypere inn på å jobbe med biblioteket.
Det første trinnet er å installere de nødvendige perlene. DataMapper-funksjonaliteten er brutt inn i mange forskjellige edelstener, så du må installere flere forskjellige deler. Selvfølgelig skal vi ikke jobbe med det hele; men dette er edelstenene du må installere.
dm-postgres-adapter
, dm-mysql-adapter
, eller hva som passer din fancy.Når du har alle disse edelstenene installert (se siste kapittel hvis du trenger å vite hvordan du installerer edelstener), er vi klare til å gå.
La oss begynne med å lage en grunnleggende modell. Modeller er definert i klasser. Vi må imidlertid først koble til vår database.
Faktisk er det aller første som krever bibliotekene våre øverst i filen vår.
krever 'dm-core' krever 'dm-timestamps' krever 'dm-valideringer' krever 'dm-migrasjon'
Så nå at vi har DataMapper i miljøet, la oss koble til databasen.
DataMapper.setup: standard, "sqlite: // # Dir.pwd /database.db"
Den første parameteren forteller DataMapper å bruke standardadapteren for databasetypen. Den andre er lenken / nettadressen til databasen. Siden vi bruker sqlite, kobler vi bare til en databasefil. Legg merke til at vi ikke trenger å lage denne filen; DataMapper vil lage den for oss.
Nå er vi klare til å lage modellen. Som du vet, er dette en klasse.
klassen bruker inkluderer datamapper :: ressursegenskap: id, seriell eiendom: brukernavn, streng eiendom: e-post, streng end
Det første trinnet er å inkludere DataMapper :: Ressurs
modul. Dette gir deg de tilpassede metodene du vil bruke i klassen din. Den viktigste metoden her er eiendom
. Her bruker vi den til å opprette tre forskjellige egenskaper: et ID, et brukernavn og en e-post. Som du ser, er den første parameteren i eiendom
er et symbol som er navnet på eiendommen. Den andre er typen. Du forstår String, selvfølgelig, men hva er serielt. Faktisk, eiendom: id, seriell
er DataMapper's stenografi for primærnøkkelen; 'seriell' er et automatisk stigende heltall. Det er din primære nøkkel!
Nå som vi har opprettet vår modell, må vi migrere databasen. Hvis du ikke er kjent med å migrere en database, er det prosessen med å endre skjemaet i databasen. Dette kan legge til en kolonne, omdøpe en kolonne eller endre egenskapene til en kolonne. DataMapper tilbyr to måter å gjøre dette på:
DataMapper.auto_migrate! DataMapper.auto_upgrade!
Forskjellen her er det auto_migrate!
vil slette alle dataene fra databasen; de auto_upgrade!
Metoder forsøker å forene det som finnes i databasen allerede med endringene du vil gjøre. Måten dette virker på er at etter modellklassen din, vil du ringe en av disse metodene. Du ønsker ikke å kjøre auto_migrate!
hver gang du laster inn modellen, selvfølgelig, men du vil kanskje kjøre auto_upgrade!
på hver omlast i utvikling. Jeg har gjort det på denne måten i Sinatra:
configure: utvikling gjør datamapper.auto_upgrade! slutt
Du vil merke at det hittil ikke har vært nødvendig å berøre en enkelt SQL-spørring; det er poenget med å bruke på ORM, at du kan skrive vanlig kode og få det til å fungere med relasjonsdatabaser.
Nå som vi har føttene våte med DataMapper, la oss ta vår modell til et annet nivå. La oss starte med tidsstempler.
Vi krever dm-tidsstempler
perle, så hvorfor ikke bruke det? Hvis vi legger til 'created_at' og 'updated_at' -egenskapene til modellen, oppdateres denne perlen automatisk de feltene.
eiendom: created_at, DateTime-egenskap: updated_at, DateTime
Selvfølgelig trenger du ikke legge til begge, hvis du ikke vil ha dem.
Det finnes flere alternativer du kan legge til i hvert felt. For eksempel, hvis du vil at et felt skal være påkrevd, eller unikt, eller ha en standardverdi, kan du gjøre det der. La oss lage en postmodell som viser noe av dette:
klasse Post inkluderer DataMapper :: Ressursegenskap: slug, String, nøkkel: true, unique_index: true, default: lambda | ressurs, prop | ressurs.title.downcase.gsub "", "-" eiendom: tittel, streng, kreves: sann eiendom: kropp, tekst, kreves: sann eiendom: created_at, DateTime eiendom: updated_at, DateTime end
Vi blander ting litt her; vår "tittel" og "kropp" er obligatoriske felt. Vi definerer egenskapen "slug" som primærnøkkel, og sier at den må være en unik indeks. Ikke bli redd av standardverdien av "slug." Selvfølgelig kan du bare bruke en rå verdi av hvilken type eiendommen din er, men vi gjør noe mer. Ruby (og andre språk) har lambdas, som du kan tenke på som en liten funksjon. Det er noe som kan ta? Parametere? og returnere en verdi, akkurat som en funksjon. Hvis vi bruker en lambda som verdien av "standard" -egenskapen, vil DataMapper sende den ressursen (eller databaseoppføringen du jobber med) og selve eiendommen (i dette tilfellet "slug"). Så her, hva vi gjør er å ta verdien av resource.title
(tittelegenskapen), sett den i små bokstaver, og bruk gsub
metode (tenk global understitution) for å bytte hvert rom til et dash. På denne måten, noe som dette:
"Dette er et tittel"
Vil bli dette:
"Dette-er-en-tittelen"
Merk: Ikke bli forvirret med hvordan vi bruker alternativer her. Først av alt, husk at når en hash er den siste parameteren til en metode, trenger vi ikke å legge til de krøllete båndene. Også med Ruby 1.9 er det en ny hash-syntaks. Tidligere har hashes sett slik ut:
: key => "value"
Du kan fortsatt gjøre dette i 1.9, og du må hvis du ikke bruker symboler som nøkler. Men hvis du bruker symboler som nøkler, kan du gjøre dette i stedet:
nøkkel: "verdi"
I utgangspunktet flytter du kolonnet til slutten av symbolet (ingen plass!) Og fjern raketten.
Det er mye du kan gjøre med validering i DataMapper, og du kan lese alt om det her. Men la oss ta en titt på det grunnleggende.
Det er to måter å gjøre valideringer på; Vi skal bruke metoden som legger til valideringene i alternativene hash. For e-postegenskapen i brukermodellen vil vi angi formatvalideringen:
eiendom: e-post, streng, format:: email_address
I dette tilfellet bruker vi en innebygd regex som DataMapper tilbyr; vi kunne sette en egendefinert regex der hvis vi ønsket noe annet.
La oss kreve en viss lengde på passordet:
eiendom: passord, streng, lengde: 10? 255
Hvis du ikke er kjent med 10? 255 notat, det er en Ruby-serie. Vi sier at passordet må være mellom 10 og 255 tegn langt.
Hva med utenlandske nøkler? DataMapper gjør dette veldig enkelt. La oss knytte våre bruker- og postmodeller. Vi vil at en bruker skal kunne ha mange innlegg, og et innlegg som tilhører en bruker.
I brukermodellen legger du til denne linjen
har n,: innlegg
Deretter gjør du i Post-modellen:
belongs_to: bruker
I databasen legger dette til en bruker-ID
eiendom til en stolpe. I praksis er det veldig enkelt; vi får se dette snart.
Hvis du vil tilpasse innspillet for en gitt eiendom, kan du legge til tilpassede eiendomsaksessorer. For eksempel, la oss si at vi vil sørge for at brukerens brukernavn alltid er lagret i små bokstaver. Vi kan legge til egenskapstilgangsmetoder som ligner på hvordan du ville i en normal klasse. På den måten tar vi verdien som brukeren prøver å lagre og fikse den opp. La oss gjøre dette:
def brukernavn = new_username super new_username.downcase slutten
Vi definerer username =
, så når brukernavnet er tildelt, blir det lavere. De super
del passerer bare vår verdi til denne metodenes supermetode, som er den som vi er overordnet.
Merk: Ifølge dokumentasjonen (se både her og her), bør vi kunne gjøre @username = new_username.downcase
i metoden ovenfor. Dette er hva jeg gjorde i screencast, og som du vet, fungerte det ikke som forventet. Siden du har tatt opp skjermbildet, har jeg oppdaget at dokumentasjonen er feil, og det super
er måten å gjøre dette på.
Nå, siden våre modeller er opprettet, la oss legge til noen få poster for å teste dem ut. Vi kan gjøre dette på noen måter. Først kan vi lage en rekord med ny
metode, passerer en hash av attributter, eller tilordne dem individuelt.
user = User.new brukernavn: "JoeSchmo", fornavn: "Joe", etternavn: "Schmo", epost: "[email protected]", passord: "password_12345" user.save user = User.new user.username = "Andrew" # etc. user.save
Når du bruker Bruker # new
, du må ringe lagre
Metode for å faktisk sette posten i databasen. Hvis det er en feil (husk disse valideringene?), lagre
Metoden vil returnere falsk. Deretter kan du gå til feil
eiendom for å se feilene; det er en DataMapper :: Validations :: ValidationsErrors objekt, men du kan iterere over feilene med Hver
metode.
user.errors.each do | error | setter feil slutten
Hvis du vil lage og lagre en plate i ett fall, bruk skape
metode, selvfølgelig passerer den en attributter hash.
User.create brukernavn: "joeschmo", fornavn: "Joe", etternavn: "Schmo", e-post: "[email protected]", passord: "passord _! @ # $%"
Boom: opprettet og lagret!
Hva med å finne en post i databasen? Hvis du kjenner nøkkelen til posten du leter etter, bruk bare få-metoden:
User.get (1) Post.get ("this-is-a-title")
Ja, du ser at dette fungerer med både normale heltalltaster og andre typer nøkler. Siden vi sa sluggen var nøkkelen i Post
modell, kan vi få
ved slug.
Hva med de feltene som kan være det samme for flere poster? Du har tre alternativer for det: først, sist og alt. Bare send dem en hash, og de får postene for deg
User.first fornavn: "Andrew" User.last (: lastname => "Schmo") User.all #ger alt innlegget
Det er mye mer du kan gjøre med DataMapper; sjekk ut dokumentasjonen for mer! Treff spørreboksen hvis du har spørsmål.