Ruby para principiantes Trabajar con DataMapper

Ruby es uno de los idiomas más populares utilizados en la web. Comenzamos una nueva sesión aquí en Nettuts + que te presentará a Ruby, así como a los excelentes marcos y herramientas que acompañan el desarrollo de Ruby. Hoy, veremos las gemas de DataMapper para comenzar a utilizar una base de datos en Ruby..


Prefiero un video tutorial?


Paso 0: Introduciendo DataMapper

DataMapper es un ORM: un Mapeo relacional de objetos. Básicamente, es una biblioteca que le permite trabajar con su base de datos desde un código orientado a objetos. No hay absolutamente ningún SQL en este tutorial en absoluto. Sin embargo, un ORM utiliza una base de datos regular debajo de las coberturas; usaremos sqlite3 hoy, pero podría usar un adaptador diferente para trabajar con mysql, postgresql u otra base de datos.

En Singing with Sinatra - La aplicación Recall, Dan Harper te presentó a DataMapper. En este tutorial, vamos a profundizar más en el trabajo con la biblioteca.


Paso 1: Instalando las gemas correctas

El primer paso es instalar las gemas requeridas. La funcionalidad del DataMapper se divide en muchas gemas diferentes, por lo que tendrá que instalar varias partes diferentes. Por supuesto, no vamos a trabajar con todo eso; Pero estas son las gemas que tendrás que instalar..

  • sqlite3: Esta es la gema de la base de datos.
  • dm-core: Esta es la funcionalidad principal de DataMapper.
  • migraciones dm: Esta gema hace la migración de la base de datos.
  • validaciones dm: Como podrás imaginar, esto ofrece funcionalidad de validación de datos..
  • dm-timestamps: Ayuda con los registros de la base de datos.
  • adaptador dm-sqlite: Este es el adaptador que conecta DataMapper a su base de datos; Estaremos usando sqlite aquí, pero puedes usar el adaptador dm-postgres, adaptador dm-mysql, o lo que sea que te guste.

Una vez que tenga todas esas gemas instaladas (consulte el último capítulo si necesita saber cómo instalarlas), estamos listos para comenzar.


Paso 2: Creando un modelo básico

Vamos a empezar por crear un modelo básico. Los modelos se definen en las clases. Sin embargo, primero tenemos que conectarnos a nuestra base de datos..

En realidad, lo primero es requerir que nuestras bibliotecas estén en la parte superior de nuestro archivo..

requiere 'dm-core' requiere 'dm-timestamps' requiere 'dm-validations' requiere 'dm-migration'

Ahora que tenemos DataMapper en el entorno, conectémonos a la base de datos.

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

El primer parámetro le dice a DataMapper que use el adaptador predeterminado para el tipo de base de datos. El segundo es el enlace / URL para la base de datos. Ya que estamos usando sqlite, solo estamos enlazando a un archivo de base de datos. Tenga en cuenta que no tenemos que crear este archivo; DataMapper lo creará para nosotros.

Ahora estamos listos para crear el modelo. Como ustedes saben, esta es una clase..

clase El usuario incluye DataMapper :: Propiedad de recurso: id, Propiedad de serie: nombre de usuario, Propiedad de cadena: correo electrónico, Fin de cadena

El primer paso es incluir el DataMapper :: Resource módulo. Esto te da los métodos personalizados que usarás en tu clase. El método más importante aquí es propiedad. Aquí, lo estamos utilizando para crear tres propiedades diferentes: una identificación, un nombre de usuario y un correo electrónico. Como ves, el primer parámetro en propiedad Es un símbolo que es el nombre de la propiedad. El segundo es el tipo. Entiendes a String, por supuesto, pero lo que es serial. Actualmente, propiedad: ID, serie es la abreviatura de DataMapper para la clave principal; 'serial' es un entero auto-incremental. Esa es tu clave principal!


Paso 3: Migración de la base de datos

Ahora que hemos creado nuestro modelo, necesitamos migrar la base de datos. Si no está familiarizado con la migración de una base de datos, es el proceso de cambiar el esquema de la base de datos. Esto podría ser agregar una columna, cambiar el nombre de una columna o cambiar las propiedades de una columna. DataMapper ofrece dos formas de hacer esto:

DataMapper.auto_migrate! DataMapper.auto_upgrade!

La diferencia aquí es que auto_migrate! borrará todos los datos de la base de datos; la auto_upgrade! los métodos intentan conciliar lo que ya está en la base de datos con los cambios que desea realizar. La forma en que funciona es que después de la clase modelo, llamará a uno de estos métodos. No quieres estar corriendo auto_migrate! Cada vez que carga el modelo, por supuesto, pero es posible que desee ejecutar auto_upgrade! en cada recarga en desarrollo. Lo he hecho así en Sinatra:

configurar: desarrollo de DataMapper.auto_upgrade! fin

Notará que hasta ahora, no hemos tenido que tocar una sola consulta SQL; ese es el punto de uso en ORM es que puede escribir código normal y hacer que funcione con bases de datos relacionales.


Paso 4: Agregar algunos atributos avanzados

Ahora que tenemos los pies mojados con DataMapper, llevemos nuestro modelo a otro nivel. Vamos a empezar con las marcas de tiempo.

Marcas de tiempo

Estamos requiriendo la dm-timestamps gema, entonces ¿por qué no usarlo? Si agregamos las propiedades 'created_at' y 'updated_at' al modelo, esta gema actualizará automáticamente esos campos.

propiedad: created_at, DateTime propiedad: updated_at, DateTime

Por supuesto, no es necesario agregar ambos, si no los desea.

Opciones

Hay varias opciones que puede agregar a cada campo. Por ejemplo, si desea que un campo sea obligatorio, único, o tenga un valor predeterminado, puede hacerlo allí. Vamos a crear un modelo posterior para mostrar algo de esto:

clase Publicación incluye DataMapper :: Propiedad del recurso: slug, String, clave: true, unique_index: true, por defecto: lambda | resource, prop | resource.title.downcase.gsub "", "-" property: title, String, required: true property: body, Text, required: true property: created_at, DateTime property: updated_at, DateTime end

Estamos mezclando las cosas un poco aquí; nuestro 'título' y 'cuerpo' son campos obligatorios. Estamos definiendo la propiedad 'slug' como la clave principal y diciendo que debe ser un índice único. No te asustes por el valor predeterminado de 'slug'. Por supuesto, solo puede usar un valor en bruto del tipo que sea su propiedad, pero estamos haciendo algo más. Ruby (y otros idiomas) tiene lambdas, que puedes considerar como una pequeña función. ¿Es algo que puede tomar parámetros? y devolver un valor, al igual que una función. Si usamos un lambda como el valor de la propiedad 'predeterminada', DataMapper le pasará el recurso (o el registro de la base de datos con el que está trabajando) y la propiedad en sí (en este caso, 'slug'). Así que aquí, lo que estamos haciendo es tomar el valor en resource.title (la propiedad del título), poniéndolo en minúsculas, y usando gsub método sollobal subEstitución) para cambiar cada espacio a un guión. De esta manera, algo como esto:

"Este es un título"

Se convertirá en esto:

"este es un título"

Nota: No se confunda con cómo usamos las opciones aquí. En primer lugar, recuerde que cuando un hash es el último parámetro de un método, no es necesario agregar llaves. Además, con Ruby 1.9, hay una nueva sintaxis de hash. Anteriormente, los hashes se veían así:

: clave => "valor"

Aún puede hacer esto en 1.9, y debe hacerlo si no está utilizando símbolos como sus claves. Pero, si está utilizando símbolos como teclas, puede hacer esto en su lugar:

 valor clave" 

Básicamente, solo mueves los dos puntos hasta el final del símbolo (¡no hay espacio!) Y quitas el cohete.

Validaciones

Hay mucho que puedes hacer con la validación en DataMapper, y puedes leer todo sobre esto aquí. Sin embargo, echemos un vistazo a lo básico..

Hay dos formas de hacer validaciones; Vamos a utilizar el método que agrega sus validaciones al hash de opciones. Para la propiedad de correo electrónico en el modelo de usuario, estableceremos la validación de formato:

propiedad: correo electrónico, cadena, formato: dirección de correo electrónico

En este caso, estamos usando una expresión regular integrada que ofrece DataMapper; Podríamos poner una expresión regular personalizada allí si quisiéramos algo más.

Requerimos una cierta longitud en la contraseña:

propiedad: contraseña, cadena, longitud: 10? 255

Si no estás familiarizado con el 10? Notación 255, eso es un rango de Ruby. Estamos diciendo que la contraseña debe tener entre 10 y 255 caracteres..

Asociaciones

¿Qué hay de las claves extranjeras? DataMapper hace esto muy fácil. Vamos a asociar nuestros modelos de Usuario y Post. Queremos que un usuario pueda tener muchas publicaciones y una publicación que pertenezca a un usuario..

En el modelo Usuario, agregue esta línea.

tiene n,: mensajes

Luego, en el modelo Post, haz esto:

Pertenece a: usuario

En la base de datos, esto agrega un user_id Propiedad a una mesa de correos. En la práctica, es muy fácil; veremos esto pronto.

Accesorios de propiedad personalizados

Si desea personalizar la entrada para una propiedad determinada, puede agregar accesores de propiedades personalizados. Por ejemplo, digamos que queremos asegurarnos de que el nombre de usuario de un usuario siempre se almacene en minúsculas. Podemos agregar métodos de acceso a propiedades similares a la forma en que lo haría en una clase normal. De esta manera, tomamos el valor que el usuario está tratando de almacenar y lo arreglamos. Hagámoslo:

def username = new_username super new_username.downcase end

Estamos definiendo el nombre de usuario =, por lo tanto, cuando se asigna el nombre de usuario, será minúscula. los súper parte simplemente pasa nuestro valor al súper método de este método, que es el que estamos anulando.

Nota: De acuerdo con la documentación (ver aquí y aquí), deberíamos poder hacer @username = new_username.downcase en el método anterior. Esto es lo que hice en el screencast, y como saben, no funcionó como se esperaba. Desde que grabé el screencast, descubrí que la documentación es incorrecta y que súper es la manera de hacer esto.


Paso 5: Crear y encontrar registros

Bueno, ahora que hemos creado nuestros modelos, agreguemos algunos registros para probarlos. Podemos hacer esto de varias maneras. Primero, podemos crear un registro con el nuevo Método, pasando un hash de atributos, o asignándolos individualmente.

usuario = Usuario. nuevo nombre de usuario: "JoeSchmo", nombre: "Joe", apellido: "Schmo", correo electrónico: "[email protected]", contraseña: "contraseña_12345" usuario.save usuario = Usuario.nuevo usuario.username = "Andrew" # etc. user.save

Cuando usas Usuario # nuevo, tienes que llamar al salvar Método para poner realmente el registro en la base de datos. Si hay un error (¿recuerdas esas validaciones?), El salvar El método devolverá false. Entonces, puedes ir a la errores Propiedad para ver los errores; es un objeto DataMapper :: Validations :: ValidationsErrors, pero puede iterar sobre los errores con el cada método.

user.errors.each do | error | pone final de error

Si desea realizar y guardar un registro de un solo golpe, use el crear Método, por supuesto pasándole un hash de atributos..

Usuario.crear nombre de usuario: "joeschmo", nombre: "Joe", apellido: "Schmo", correo electrónico: "[email protected]", contraseña: "contraseña _! @ # $%"

Boom: creado y guardado!

¿Qué hay de encontrar un registro en la base de datos? Si conoce la clave del registro que está buscando, solo use el método de obtención:

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

Sí, está viendo que esto funciona tanto con las teclas enteras normales como con otros tipos de teclas. Desde que dijimos que la babosa era la clave en el Enviar modelo, podemos obtener por babosa.

¿Qué pasa con esos campos que podrían ser los mismos para múltiples registros? Tienes tres opciones para eso: primero, último y todo. Solo pásales un hash, y obtendrán los registros para ti.

Usuario. Primer nombre: "Andrew" User.last (: lastname => "Schmo") User.all #get todos los mensajes

Conclusión: aprendiendo más

Hay mucho más que puedes hacer con DataMapper; Echa un vistazo a la documentación para más! Pulsa la casilla de preguntas si tienes alguna pregunta..