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.
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.
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.
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.
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!
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.
Ora che abbiamo i piedi bagnati con DataMapper, portiamo il nostro modello su un altro livello. Iniziamo con i timestamp.
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.
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.
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.
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.
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.
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
C'è molto di più che puoi fare con DataMapper; controlla la documentazione di più! Colpisci la casella delle domande se hai domande.