Ruby voor nieuwkomers werken met DataMapper

Ruby is een van de populairste talen die op internet wordt gebruikt. We zijn hier een nieuwe sessie gestart op Nettuts + die u Ruby zal voorstellen, evenals de geweldige frameworks en tools die horen bij de ontwikkeling van Ruby. Vandaag zullen we de DataMapper-edelstenen bekijken om aan de slag te gaan met een database in Ruby.


Liever een video-zelfstudie?


Stap 0: Introductie van DataMapper

DataMapper is een ORM: een Object-Relational Mapping. Kortom, het is een bibliotheek waarmee je vanuit je object-georiënteerde code met je database kunt werken. Er is helemaal geen SQL in deze tutorial. Een ORM gebruikt echter een gewone database onder de omslagen; we zullen sqlite3 vandaag gebruiken, maar je zou gewoon een andere adapter kunnen gebruiken om te werken met een mysql, postgresql of andere database.

In Singing with Sinatra - The Recall App, introduceerde Dan Harper je bij DataMapper. In deze zelfstudie gaan we dieper duiken in het werken met de bibliotheek.


Stap 1: De juiste edelstenen installeren

De eerste stap is het installeren van de vereiste edelstenen. De DataMapper-functionaliteit is opgedeeld in veel verschillende edelstenen, dus je zult verschillende onderdelen moeten installeren. Natuurlijk gaan we er niet allemaal mee werken; maar dit zijn de edelstenen die je moet installeren.

  • sqlite3: Dit is het juweel van de database.
  • dm-core: Dit is de kernfunctionaliteit van DataMapper.
  • dm-migraties: Dit juweeltje doet de databasemigratie.
  • dm-validaties: Zoals u kunt raden, biedt dit functionaliteit voor gegevensvalidatie.
  • dm-timestamps: Helpt bij het tijdstempelen van databaserecords.
  • dm-sqlite-adapter: Dit is de adapter die DataMapper met uw database verbindt; we zullen sqlite hier gebruiken, maar je kunt de dm-postgres-adapter, dm-mysql-adapter, of wat je maar wilt.

Als je al die edelstenen hebt geïnstalleerd (zie het laatste hoofdstuk als je wilt weten hoe edelstenen te installeren), zijn we klaar om te gaan.


Stap 2: Een basismodel maken

Laten we beginnen met het maken van een basismodel. Modellen worden in klassen gedefinieerd. We moeten echter eerst verbinding maken met onze database.

Eigenlijk is het allereerste dat onze bibliotheken bovenaan ons bestand moeten staan.

vereisen 'dm-core' vereisen 'dm-timestamps' vereisen 'dm-validaties' vereisen 'dm-migration'

Dus nu we DataMapper in de omgeving hebben, laten we ons verbinden met de database.

DataMapper.setup: standaard, "sqlite: // # Dir.pwd /database.db"

De eerste parameter vertelt DataMapper om de standaardadapter voor het databasetype te gebruiken. De tweede is de link / URL voor de database. Omdat we sqlite gebruiken, linken we alleen naar een databasebestand. Merk op dat we dit bestand niet hoeven te maken; DataMapper zal het voor ons maken.

Nu zijn we klaar om het model te maken. Zoals je weet, is dit een les.

klasse Gebruiker omvat DataMapper :: Resource-eigenschap: id, Seriële eigenschap: gebruikersnaam, String-eigenschap: e-mail, String-einde

De eerste stap is om de DataMapper :: Resource module. Dit geeft je de aangepaste methoden die je in je klas zult gebruiken. De belangrijkste methode is hier eigendom. Hier gebruiken we het om drie verschillende eigenschappen te maken: een id, een gebruikersnaam en een e-mail. Zoals je ziet, de eerste parameter in eigendom is een symbool dat de naam van het eigendom is. De tweede is het type. Je begrijpt String natuurlijk, maar wat is serieus. Werkelijk, eigenschap: id, serie is de afkorting van DataMapper voor de primaire sleutel; 'serial' is een auto-verhogend geheel getal. Dat is je primaire sleutel!


Stap 3: de database migreren

Nu we ons model hebben gemaakt, moeten we de database migreren. Als u niet bekend bent met het migreren van een database, is dit het proces waarbij het schema van de database wordt gewijzigd. Dit kan een kolom toevoegen, een kolom hernoemen of eigenschappen van een kolom wijzigen. DataMapper biedt twee manieren om dit te doen:

DataMapper.auto_migrate! DataMapper.auto_upgrade!

Het verschil is dat auto_migrate! zal alle gegevens uit de database wissen; de auto_upgrade! methoden probeert om te verzoenen wat er in de database al is met de wijzigingen die u wilt maken. De manier waarop dit werkt is dat je na je modelklasse een van deze methoden aanroept. Je wilt niet rennen auto_migrate! elke keer dat je het model laadt, natuurlijk, maar misschien wil je het uitvoeren auto_upgrade! op elke herlaadbeurt in ontwikkeling. Ik heb het op deze manier gedaan in Sinatra:

configure: development do DataMapper.auto_upgrade! einde

U zult merken dat we tot nu toe geen enkele SQL-query hoefden aan te raken; dat is het punt van het gebruik van ORM is dat je normale code kunt schrijven en dat je kunt laten werken met relationele databases.


Stap 4: Een aantal geavanceerde attributen toevoegen

Nu we onze voeten hebben met DataMapper, laten we ons model naar een ander niveau tillen. Laten we beginnen met tijdstempels.

timestamps

We hebben de dm-timestamps edelsteen, dus waarom niet gebruiken? Als we eigenschappen 'created_at' en 'updated_at' aan het model toevoegen, zal dit juweeltje deze velden automatisch bijwerken.

eigenschap: created_at, DateTime-eigenschap: updated_at, DateTime

Natuurlijk hoeft u beide niet toe te voegen, als u ze niet wilt.

opties

Er zijn verschillende opties die u aan elk veld kunt toevoegen. Als u bijvoorbeeld een veld nodig of uniek wilt hebben of een standaardwaarde wilt, kunt u dat daar doen. Laten we een postmodel maken om dit te laten zien:

class Post include DataMapper :: Resource-eigenschap: slug, String, key: true, unique_index: true, default: lambda | resource, prop | resource.title.downcase.gsub "", "-" property: title, String, verplicht: true property: body, Tekst, verplicht: true property: created_at, DateTime property: updated_at, DateTime end

We mengen hier een beetje met elkaar; onze 'titel' en 'hoofdtekst' zijn verplichte velden. We definiëren de eigenschap 'slak' als de primaire sleutel en zeggen dat het een unieke index moet zijn. Laat je niet afschrikken door de standaardwaarde van 'slug.' Je kunt natuurlijk gewoon een onbewerkte waarde gebruiken van welk type je eigendom ook is, maar we doen iets meer. Ruby (en andere talen) heeft lambda's, die je zou kunnen zien als een kleine functie. Het is iets dat kan nemen? Parameters? en retourneer een waarde, net als een functie. Als we een lambda gebruiken als de waarde van de 'standaard'-eigenschap, geeft DataMapper deze door aan de resource (of databaserecord waarmee je werkt) en de eigenschap zelf (in dit geval' slug '). Dus hier doen we er alles aan om de waarde in te nemen resource.title (de eigenschap title), in kleine letters plaatsen en gebruiken gsub methode (denk na global substitution) om elke spatie naar een streepje te schakelen. Op deze manier, iets als dit:

"Dit is een titel"

Zal dit worden:

"Dit-is-a-titel"

Opmerking: raak niet verward met hoe we hier opties gebruiken. Denk er allereerst aan dat wanneer een hash de laatste parameter van een methode is, we de accolades niet hoeven toe te voegen. Met Ruby 1.9 is er ook een nieuwe hash-syntaxis. Voorheen zagen hashes er als volgt uit:

: key => "waarde"

Je kunt dit nog steeds doen in 1.9, en je moet het doen als je geen symbolen als je sleutels gebruikt. Maar als u symbolen als sleutels gebruikt, kunt u dit in plaats daarvan doen:

 sleutel waarde" 

In feite verplaatst u de dubbele punt naar het einde van het symbool (geen spatie!) En verwijdert u de raket.

validaties

Er is veel wat u kunt doen met validatie in DataMapper, en u kunt er hier alles over lezen. Laten we echter eens kijken naar de basis.

Er zijn twee manieren om validaties uit te voeren; we gaan de methode gebruiken die je validaties toevoegt aan de hash-opties. Voor de e-maileigenschap in het gebruikersmodel, stellen we de formaatvalidatie in:

property: email, String, format:: email_address

In dit geval gebruiken we een ingebouwde regex die DataMapper biedt; we zouden daar een aangepaste regex kunnen plaatsen als we iets anders wilden.

Laten we een bepaalde lengte van het wachtwoord vereisen:

eigendom: wachtwoord, tekenreeks, lengte: 10? 255

Als u niet bekend bent met de 10? 255 notatie, dat is een Ruby-bereik. We zeggen dat het wachtwoord tussen 10 en 255 tekens lang moet zijn.

verenigingen

Hoe zit het met buitenlandse sleutels? DataMapper maakt dit echt gemakkelijk. Laten we onze gebruikers- en postmodellen associëren. We willen dat een gebruiker veel berichten kan hebben en dat een bericht lid kan zijn van een gebruiker.

Voeg in het gebruikersmodel deze regel toe

heeft n,: berichten

Doe dit in het Post-model als volgt:

belong_to: gebruiker

In de database voegt dit een toe gebruikersnaam eigendom naar een berichtentabel. In de praktijk is het echt gemakkelijk; we zullen dit snel zien.

Aangepaste eigendomsaccessoires

Als u de invoer voor een bepaalde eigenschap wilt aanpassen, kunt u aangepaste toegangsdeigenaren toevoegen. Stel dat we er bijvoorbeeld zeker van willen zijn dat de gebruikersnaam van een gebruiker altijd in kleine letters wordt opgeslagen. We kunnen property accessor-methoden toevoegen die lijken op de manier zoals u zou doen in een normale klas. Op deze manier nemen we de waarde die de gebruiker probeert op te slaan en op te lossen. Laten we dit doen:

def username = new_username super new_username.downcase end

We definiëren de gebruikersnaam =, dus wanneer de gebruikersnaam is toegewezen, wordt deze verlaagd. De super deel geeft gewoon onze waarde door aan de supermethode van deze methode, die we overschrijven.

Opmerking: volgens de documentatie (zie hier en hier) moeten we het kunnen doen @username = new_username.downcase in de bovenstaande methode. Dit heb ik in de screencast gedaan en zoals je weet, werkte het niet zoals verwacht. Sinds ik de screencast heb opgenomen, heb ik ontdekt dat de documentatie fout is en dat super is de manier om dit te doen.


Stap 5: Records maken en vinden

Welnu, nu onze modellen zijn gemaakt, laten we een paar records toevoegen om ze uit te testen. We kunnen dit op een paar manieren doen. Ten eerste kunnen we een record maken met de nieuwe methode, een hash van attributen doorgeven of ze individueel toewijzen.

user = User.new gebruikersnaam: "JoeSchmo", voornaam: "Joe", achternaam: "Schmo", email: "[email protected]", wachtwoord: "password_12345" user.save user = User.new user.username = "Andrew" # etc. user.save

Tijdens gebruik Gebruiker # nieuwe, je moet de opslaan methode om het record daadwerkelijk in de database te plaatsen. Als er een fout is (onthoud die validaties?), De opslaan methode retourneert false. Vervolgens kunt u naar de fouten eigenschap om de fouten te zien; het is een DataMapper :: Validations :: ValidationsErrors-object, maar u kunt de fouten herhalen met de elk methode.

user.errors.each do | error | zet fout einde

Als je een record in één klap wilt maken en opslaan, gebruik dan de creëren methode, uiteraard geeft het een attributen-hash door.

User.create gebruikersnaam: "joeschmo", voornaam: "Joe", achternaam: "Schmo", email: "[email protected]", wachtwoord: "wachtwoord _! @ # $%"

Boom: gemaakt en opgeslagen!

Hoe zit het met het vinden van een record in de database? Als je de sleutel kent van het record dat je zoekt, gebruik dan gewoon de methode get:

User.get (1) Post.get ("dit is een titel")

Ja, je ziet dat dit werkt met zowel normale integere toetsen als andere soorten sleutels. Omdat we zeiden dat de slak de sleutel was in de Post model, we kunnen krijgen door naaktslak.

Hoe zit het met die velden die hetzelfde zouden kunnen zijn voor meerdere records? Daar heb je drie opties voor: eerst, laatste en alles. Geef ze gewoon een hash en ze krijgen de gegevens voor je

User.first voornaam: "Andrew" User.last (: lastname => "Schmo") User.all #gets alle berichten

Conclusie: meer leren

Er is veel meer dat u kunt doen met DataMapper; bekijk de documentatie voor meer! Klik op het vragenvenster als je vragen hebt.