Ruby for Newbies lavorare con DataMapper

Ruby è una delle lingue più popolari utilizzate sul web. Abbiamo avviato una nuova sessione qui su Nettuts + che ti introdurrà a Ruby, oltre ai grandi framework e strumenti che accompagnano lo sviluppo di Ruby. Oggi esamineremo le gemme di DataMapper per essere subito operativi con un database in Ruby.


Preferisci un video tutorial?


Passaggio 0: presentazione di DataMapper

DataMapper è un ORM: un mapping relazionale a oggetti. Fondamentalmente, è una libreria che ti permette di lavorare con il tuo database dal codice orientato agli oggetti. Non c'è assolutamente alcun SQL in questo tutorial. Tuttavia, un ORM utilizza un database regolare sotto le copertine; useremo sqlite3 oggi, ma potresti semplicemente usare un adattatore diverso per lavorare con un database mysql, postgresql o altro.

In Singing with Sinatra - The Recall App, Dan Harper ti ha presentato a DataMapper. In questo tutorial, faremo un tuffo più profondo nel lavorare con la biblioteca.


Passaggio 1: installazione delle gemme giuste

Il primo passo è installare le gemme richieste. La funzionalità DataMapper è suddivisa in molte gemme diverse, quindi dovrai installare diverse parti differenti. Certo, non lavoreremo con tutto questo; ma queste sono le gemme che dovrai installare.

  • sqlite3: Questa è la gemma del database.
  • dm-core: Questa è la funzionalità principale di DataMapper.
  • dm-migrazioni: Questa gemma esegue la migrazione del database.
  • dm-convalide: Come puoi immaginare, offre funzionalità di convalida dei dati.
  • dm-timestamp: Aiuta con i record del database di timestamping.
  • dm-sqlite-adattatore: Questo è l'adattatore che collega DataMapper al tuo database; useremo sqlite qui, ma puoi usare il dm-postgres-adattatore, dm-mysql-adattatore, o qualunque cosa sia adatta alla tua fantasia.

Una volta che hai installato tutte queste gemme (vedi l'ultimo capitolo se hai bisogno di sapere come installare le gemme), siamo pronti per partire.


Passaggio 2: creazione di un modello di base

Iniziamo creando un modello base. I modelli sono definiti nelle classi. Tuttavia, dobbiamo prima connetterci al nostro database.

In realtà, la prima cosa è richiedere le nostre librerie nella parte superiore del nostro file.

richiedere 'dm-core' richiede 'dm-timestamp' richiede 'dm-validations' richiedono 'dm-migration'

Quindi ora che abbiamo DataMapper nell'ambiente, connettiamoci al database.

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

Il primo parametro indica a DataMapper di utilizzare l'adattatore predefinito per il tipo di database. Il secondo è il link / URL per il database. Dato che stiamo usando sqlite, stiamo solo collegando un file di database. Si noti che non è necessario creare questo file; DataMapper lo creerà per noi.

Ora siamo pronti per creare il modello. Come sai, questa è una classe.

classe Utente include DataMapper :: Proprietà risorsa: id, Proprietà seriale: nomeutente, Proprietà stringa: email, fine stringa

Il primo passo è includere il DataMapper :: Resource modulo. Questo ti dà i metodi personalizzati che userai nella tua classe. Il metodo più importante qui è proprietà. Qui, lo stiamo usando per creare tre diverse proprietà: un id, un nome utente e un'email. Come vedi, il primo parametro in proprietà è un simbolo che è il nome della proprietà. Il secondo è il tipo. Capisci String, ovviamente, ma cos'è la serie. In realtà, proprietà: id, seriale è la scorciatoia di DataMapper per la chiave primaria; 'seriale' è un numero intero autoincrementante. Questa è la tua chiave primaria!


Passaggio 3: Migrazione del database

Ora che abbiamo creato il nostro modello, abbiamo bisogno di migrare il database. Se non si ha familiarità con la migrazione di un database, è il processo di modifica dello schema del database. Questo potrebbe essere l'aggiunta di una colonna, la ridenominazione di una colonna o la modifica delle proprietà di una colonna. DataMapper offre due modi per farlo:

DataMapper.auto_migrate! DataMapper.auto_upgrade!

La differenza qui è quella auto_migrate! cancellerà tutti i dati dal database; il auto_upgrade! i metodi cercano di riconciliare ciò che c'è nel database già con le modifiche che vuoi apportare. Il modo in cui funziona è che dopo la classe del modello, chiamerai uno di questi metodi. Non vuoi correre auto_migrate! ogni volta che carichi il modello, ovviamente, ma potresti voler correre auto_upgrade! su ogni ricarica nello sviluppo. L'ho fatto in questo modo a Sinatra:

configure: development do DataMapper.auto_upgrade! fine

Noterai che finora non abbiamo dovuto toccare una singola query SQL; questo è il punto di utilizzo su ORM è che è possibile scrivere il codice normale e farlo funzionare con i database relazionali.


Passaggio 4: aggiunta di alcuni attributi avanzati

Ora che abbiamo i piedi bagnati con DataMapper, portiamo il nostro modello su un altro livello. Iniziamo con i timestamp.

timestamps

Stiamo richiedendo il dm-timestamp gemma, quindi perché non usarlo? Se aggiungiamo proprietà 'created_at' e 'updated_at' al modello, questa gemma aggiornerà automaticamente quei campi.

proprietà: created_at, proprietà DateTime: updated_at, DateTime

Naturalmente, non è necessario aggiungere entrambi, se non li vuoi.

Opzioni

Esistono diverse opzioni che è possibile aggiungere a ciascun campo. Ad esempio, se vuoi che un campo sia richiesto, o unico, o abbia un valore predefinito, puoi farlo lì. Creiamo un modello di post per mostrare alcuni di questi:

class post include DataMapper :: Proprietà risorsa: slug, String, chiave: true, unique_index: true, default: lambda | resource, prop | resource.title.downcase.gsub "", "-" proprietà: title, String, obbligatorio: true proprietà: body, Text, obbligatorio: true proprietà: created_at, proprietà DateTime: updated_at, DateTime end

Stiamo unendo le cose un po 'qui; il nostro 'titolo' e 'corpo' sono campi obbligatori. Stiamo definendo la proprietà "slug" come chiave primaria e affermando che deve essere un indice univoco. Non farti spaventare dal valore predefinito di 'slug'. Certo, puoi semplicemente usare un valore grezzo di qualunque tipo sia la tua proprietà, ma stiamo facendo qualcosa di più. Il rubino (e altre lingue) ha lambda, che si potrebbe pensare come una piccola funzione. È qualcosa che può prendere? Parametri? e restituire un valore, proprio come una funzione. Se usiamo un lambda come valore della proprietà 'default', DataMapper gli passerà la risorsa (o il record del database con cui stai lavorando) e la proprietà stessa (in questo caso, 'slug'). Quindi qui, quello che stiamo facendo è prendere valore resource.title (la proprietà title), inserendola in lettere minuscole e usando gsub metodo (pensa global substitution) per cambiare ogni spazio in un trattino. In questo modo, qualcosa del genere:

"Questo è un titolo"

Diventerà questo:

"Questo-è-un-title"

Nota: non essere confuso da come stiamo usando le opzioni qui. Prima di tutto, ricorda che quando un hash è l'ultimo parametro di un metodo, non è necessario aggiungere le parentesi graffe. Inoltre, con Ruby 1.9, c'è una nuova sintassi hash. In precedenza, gli hash sembravano così:

: chiave => "valore"

Puoi ancora farlo in 1.9, e devi farlo se non stai usando i simboli come chiavi. Ma se usi i simboli come chiavi, puoi farlo invece:

chiave: "valore"

Fondamentalmente, basta spostare i due punti alla fine del simbolo (senza spazio!) E rimuovere il razzo.

Validazioni

C'è molto che puoi fare con la convalida in DataMapper, e puoi leggere tutto su di esso qui. Tuttavia, diamo un'occhiata alle basi.

Ci sono due modi per fare convalide; useremo il metodo che aggiunge le tue convalide all'hash delle opzioni. Per la proprietà email nel modello Utente, imposteremo la convalida del formato:

proprietà: email, stringa, formato:: indirizzo_email

In questo caso, stiamo usando una regex incorporata che DataMapper offre; potremmo inserire una regex personalizzata se volessimo qualcos'altro.

Richiediamo una certa lunghezza sulla password:

proprietà: password, stringa, lunghezza: 10? 255

Se non hai familiarità con il 10? Notazione 255, questa è una gamma Ruby. Stiamo dicendo che la password deve essere lunga tra 10 e 255 caratteri.

associazioni

Che ne dici di chiavi straniere? DataMapper rende questo veramente facile. Associamo i nostri modelli Utente e Post. Vogliamo che un utente sia in grado di avere molti post e che un post appartenga a un utente.

Nel modello Utente, aggiungi questa linea

ha n,: post

Quindi, nel modello Post, fai questo:

appartiene a: utente

Nel database, questo aggiunge un ID utente proprietà a un tavolo postale. In pratica, è davvero facile; lo vedremo presto.

Accessors di proprietà personalizzate

Se si desidera personalizzare l'input per una determinata proprietà, è possibile aggiungere proprietà personalizzate. Ad esempio, supponiamo di voler essere sicuri che il nome utente di un utente sia sempre memorizzato in lettere minuscole. Possiamo aggiungere metodi di accesso alle proprietà simili a quelli che fareste in una classe normale. In questo modo, prendiamo il valore che l'utente sta cercando di archiviare e sistemare. Facciamolo:

def username = new_username super new_username.downcase end

Stiamo definendo il username =, quindi, quando il nome utente è assegnato, sarà in minuscolo. Il super parte passa semplicemente il nostro valore al metodo super di questo metodo, che è quello che stiamo sovrascrivendo.

Nota: secondo la documentazione (vedere qui e qui), dovremmo essere in grado di fare @username = new_username.downcase nel metodo sopra. Questo è quello che ho fatto con lo screencast e, come sai, non ha funzionato come previsto. Da quando ho registrato lo screencast ho scoperto che la documentazione è sbagliata, e questo super è il modo per farlo.


Passaggio 5: creazione e ricerca di record

Bene, ora che i nostri modelli sono stati creati, aggiungiamo alcuni record per testarli. Possiamo farlo in alcuni modi. In primo luogo, possiamo creare un record con il nuovo metodo, passando un hash di attributi o assegnandoli singolarmente.

user = User.new username: "JoeSchmo", nome: "Joe", cognome: "Schmo", email: "[email protected]", password: "password_12345" user.save user = User.new user.username = "Andrew" # etc. user.save

Quando si usa Utente # nuova, devi chiamare il salvare metodo per mettere effettivamente il record nel database. Se c'è un errore (ricordate quelle convalide?), Il salvare il metodo restituirà false. Quindi, puoi andare al errori proprietà per vedere gli errori; è un oggetto DataMapper :: Validations :: ValidationsErrors, ma puoi scorrere gli errori con il ogni metodo.

user.errors.each do | errore | mette fine all'errore

Se vuoi fare e salvare un disco in un colpo solo, usa il tasto creare metodo, ovviamente passandogli un hash di attributi.

User.create username: "joeschmo", nome: "Joe", lastname: "Schmo", email: "[email protected]", password: "password _! @ # $%"

Boom: creato e salvato!

Che ne dici di trovare un record nel database? Se conosci la chiave del record che stai cercando, usa il metodo get:

User.get (1) Post.get ("this-is-a-title")

Sì, stai vedendo che questo funziona sia con le normali chiavi intere che con altri tipi di chiavi. Dal momento che abbiamo detto che la lumaca era la chiave nel Inviare modello, possiamo ottenere di lumaca.

Che dire di quei campi che potrebbero essere uguali per più record? Hai tre opzioni per questo: primo, ultimo e tutto. Basta passargli un hash e ottengono i record per te

User.first firstname: "Andrew" User.last (: lastname => "Schmo") User.all #gets all the post

Conclusione: saperne di più

C'è molto di più che puoi fare con DataMapper; controlla la documentazione di più! Colpisci la casella delle domande se hai domande.