Ruby är ett av de mest populära språk som används på webben. Vi har startat en ny session här på Nettuts + som kommer att introducera dig till Ruby, liksom de stora ramarna och verktygen som följer med Ruby-utvecklingen. Idag ser vi på DataMapper-ädelstenarna för att komma igång med en databas i Ruby.
DataMapper är en ORM: en Object-Relational Mapping. I grund och botten är det ett bibliotek som låter dig arbeta med din databas från objektorienterad kod. Det finns absolut ingen SQL i denna handledning alls. En ORM använder emellertid en vanlig databas under täcken; vi använder sqlite3 idag, men du kan bara använda en annan adapter för att arbeta med en mysql, postgresql eller annan databas.
I Singing med Sinatra - The Recall App presenterade Dan Harper dig till DataMapper. I denna handledning kommer vi att ta ett djupare dykk i för att arbeta med biblioteket.
Det första steget är att installera de nödvändiga ädelstenarna. DataMapper-funktionaliteten är uppdelad i många olika pärlor, så du måste installera flera olika delar. Självklart kommer vi inte att arbeta med allting; men det här är juvelerna du måste installera.
dm-postgres-adapter
, dm-mysql-adapter
, eller vad som helst som passar dig.När du har alla dessa juveler installerade (se det sista kapitlet om du behöver veta hur man installerar juveler), är vi redo att gå.
Låt oss börja med att skapa en grundläggande modell. Modeller definieras i klasser. Men vi måste först ansluta till vår databas.
Faktum är att det allra första kräver våra bibliotek längst upp i vår fil.
kräver 'dm-core' kräver 'dm-timestamps' kräver 'dm-validations' kräver 'dm-migration'
Så nu när vi har DataMapper i miljön, låt oss ansluta till databasen.
DataMapper.setup: standard, "sqlite: // # Dir.pwd /database.db"
Den första parametern berättar DataMapper att använda standardadaptern för databastypen. Den andra är länken / URL för databasen. Eftersom vi använder sqlite länkar vi bara till en databasfil. Observera att vi inte behöver skapa den här filen. DataMapper skapar det för oss.
Nu är vi redo att skapa modellen. Som du vet är det här en klass.
klass Användare inkluderar DataMapper :: Resursegenskap: id, seriell egendom: användarnamn, strängegenskaper: email, string end
Det första steget är att inkludera DataMapper :: Resource
modul. Detta ger dig de anpassade metoderna du ska använda i din klass. Den viktigaste metoden här är fast egendom
. Här använder vi den för att skapa tre olika egenskaper: ett id, ett användarnamn och ett e-postmeddelande. Som du ser, den första parametern i fast egendom
är en symbol som heter fastigheten. Den andra är typen. Du förstår String, men det är seriellt. Faktiskt, egendom: id, serie
är DataMappers stenografi för primärnyckeln; "seriell" är ett automatiskt inkrementellt heltal. Det är din primära nyckel!
Nu när vi har skapat vår modell måste vi migrera databasen. Om du inte är bekant med att migrera en databas är det processen att ändra schemat för databasen. Det här kan vara att lägga till en kolumn, byta namn på en kolumn eller ändra egenskaper för en kolumn. DataMapper erbjuder två sätt att göra detta:
DataMapper.auto_migrate! DataMapper.auto_upgrade!
Skillnaden här är det auto_migrate!
kommer att rensa alla data från databasen; de auto_upgrade!
metoder försöker förena vad som finns i databasen redan med de förändringar du vill göra. Så här fungerar det är att efter din modellklass kommer du att ringa en av dessa metoder. Du vill inte springa auto_migrate!
varje gång du laddar in modellen, förstås, men du kanske vill springa auto_upgrade!
på varje omlastning i utveckling. Jag har gjort det här i Sinatra:
configure: utveckling gör DataMapper.auto_upgrade! slutet
Du kommer märka att hittills har vi inte behövt röra en enda SQL-fråga. det är poängen att använda på ORM är att du kan skriva normal kod och få det att fungera med relationella databaser.
Nu när vi har våra fötter våta med DataMapper, låt oss ta vår modell till en annan nivå. Låt oss börja med tidstämplar.
Vi kräver det dm-tidsstämplar
pärla, så varför inte använda det? Om vi lägger till "created_at" och "updated_at" -egenskaperna till modellen, uppdaterar denna pärla automatiskt de fälten.
egendom: created_at, DateTime-egenskap: updated_at, DateTime
Självklart behöver du inte lägga till båda, om du inte vill ha dem.
Det finns flera alternativ som du kan lägga till i varje fält. Om du till exempel vill ha ett fält, eller unikt, eller ha ett standardvärde, kan du göra det där. Låt oss skapa en postmodell för att visa upp något av detta:
klasspost inkluderar DataMapper :: Resursegenskap: slug, String, nyckel: true, unique_index: true, default: lambda | resource | prop | resource.title.downcase.gsub "", "-" egendom: titel, String, krävs: sann egendom: kropp, text, krävs: sann egendom: created_at, DateTime-egenskap: updated_at, DateTime end
Vi blandar saker här lite här; vår "titel" och "kropp" är obligatoriska fält. Vi definierar egenskapen "slug" som den primära nyckeln och säger att den måste vara ett unikt index. Bli inte rädd av standardvärdet för "slug". Naturligtvis kan du bara använda ett råvärde av vilken typ din egendom är, men vi gör något mer. Ruby (och andra språk) har lambdas, som du kan tänka dig som en liten funktion. Det är något som kan ta? Parametrar? och returnera ett värde, precis som en funktion. Om vi använder en lambda som värdet för "standard" -egenskapen, kommer DataMapper att skicka den till resursen (eller databasposten du arbetar med) och egenskapen själv (i det här fallet "slug"). Så här, vad vi gör är att ta värdet in resource.title
(titelegenskapen), sätta den i små bokstäver och använda gsub
metod (tänk global substitution) för att byta varje utrymme till ett streck. På så sätt, något som detta:
"Detta är en titel"
Kommer att bli så här:
"This-is-a-title"
Obs! Bli inte förvirrad med hur vi använder alternativ här. Först och främst, kom ihåg att när en hasja är den sista parametern för en metod behöver vi inte lägga till de lockiga axlarna. Även med Ruby 1.9 finns det en ny hashsyntax. Tidigare såg hashes så här:
: key => "value"
Du kan fortfarande göra det i 1,9, och du måste om du inte använder symboler som dina nycklar. Men om du använder symboler som nycklar kan du göra det istället:
nyckelvärde"
I grund och botten flyttar du bara kolon i slutet av symbolen (inget utrymme!) Och tar bort raketen.
Det finns mycket du kan göra med validering i DataMapper, och du kan läsa allt om det här. Men låt oss ta en titt på grunderna.
Det finns två sätt att göra valideringar; Vi kommer att använda metoden som lägger till dina valideringar i alternativhacken. För e-postegenskapen i användarmodellen ställer vi in valideringen av formatet:
egendom: e-post, sträng, format:: email_address
I det här fallet använder vi en inbyggd regex som DataMapper erbjuder; vi kunde lägga en anpassad regex om vi ville ha något annat.
Låt oss kräva en viss längd på lösenordet:
egendom: lösenord, sträng, längd: 10? 255
Om du inte känner till 10? 255 notation, det är ett Ruby sortiment. Vi säger att lösenordet måste vara mellan 10 och 255 tecken långt.
Vad sägs om främmande nycklar? DataMapper gör det här enkelt enkelt. Låt oss associera våra användar- och postmodeller. Vi vill att en användare ska kunna ha många inlägg och ett inlägg som tillhör en användare.
I användarmodellen lägger du till den här raden
har n,: inlägg
Därefter gör du följande i Post-modellen:
belongs_to: användare
I databasen lägger detta till en användar ID
egendom till ett postbord. I praktiken är det väldigt enkelt; vi ses snart.
Om du vill anpassa inmatningen för en viss egendom kan du lägga till anpassade fastighetsaccessorer. Låt oss till exempel säga att vi vill se till att användarens användarnamn alltid sparas i små bokstäver. Vi kan lägga till metoder för tillgång till tillgångar som liknar det sätt du skulle göra i en normal klass. På det sättet tar vi det värde som användaren försöker lagra och fixa upp. Nu gör vi det:
def användarnamn = new_username super new_username.downcase end
Vi definierar användarnamn =
, så när användarnamnet är tilldelat kommer det att vara lägre. De super
en del passerar bara vårt värde till denna metodens supermetod, vilket är det vi övertygar.
Obs! Enligt dokumentationen (se både här och här) borde vi kunna göra @username = new_username.downcase
i metoden ovan. Detta är vad jag gjorde i skärmen, och som du vet fungerade det inte som förväntat. Sedan inspelningen av skärmen har jag upptäckt att dokumentationen är fel, och det super
är sättet att göra detta.
Nå, nu när våra modeller skapas, låt oss lägga till några poster för att testa dem. Vi kan göra detta på några sätt. Först kan vi skapa en rekord med ny
metod, passerar en hash av attribut eller tilldela dem individuellt.
user = User.new användarnamn: "JoeSchmo", förnamn: "Joe", efternamn: "Schmo", email: "[email protected]", lösenord: "password_12345" user.save user = User.new user.username = "Andrew" # etc. user.save
När man använder Användare # nytt
, du måste ringa spara
metod för att faktiskt lägga in posten i databasen. Om det finns ett fel (kom ihåg dessa valideringar?), spara
Metoden kommer att returnera falskt. Då kan du gå till fel
egendom för att se fel det är en DataMapper :: Validations :: ValidationsErrors objekt, men du kan iterera över felen med varje
metod.
user.errors.each gör | error | sätter feländen
Om du vill göra och spara en post i ett fall, använder du skapa
metod, naturligtvis passerar den en attribut hash.
User.create användarnamn: "joeschmo", förnamn: "Joe", efternamn: "Schmo", email: "[email protected]", lösenord: "lösenord _! @ # $%"
Boom: skapad och sparad!
Vad sägs om att hitta en post i databasen? Om du känner till nyckeln till den post du letar efter, använd bara get-metoden:
User.get (1) Post.get ("this-is-a-title")
Ja, du ser att det här fungerar med både vanliga heltalsnycklar och andra typer av nycklar. Eftersom vi sa att sluget var nyckeln i Posta
modell, vi kan skaffa sig
genom slug.
Vad sägs om de fält som kan vara desamma för flera poster? Du har tre alternativ för det: först, sista och alla. Ge dem bara en hash, och de får rekorden för dig
Användare.första förnamn: "Andrew" User.last (: efternamn => "Schmo") User.all #gets alla inlägg
Det finns mycket mer du kan göra med DataMapper; kolla in dokumentationen för mer! Klicka på frågeformuläret om du har några frågor.