Advertisement
  1. Code
  2. Ruby on Rails

Consultas en Rails, parte 1

Spanish (Español) translation by Esther (you can also view the original English article)

En este artículo aprenderás los fundamentos de las consultas de Active Record y, de paso, aprenderás algunos aspectos básicos de SQL. Está dirigido a principiantes que quieran empezar a aprender más sobre consultas a bases de datos en Ruby on Rails.

Temas

  • Objetos individuales
  • Objetos múltiples
  • Condiciones
  • Pedidos
  • Límites
  • Grupo y Tener

Active Record se utiliza para consultar la base de datos. Puede utilizarse con SQL, PostgresSQL y SQLite. Para recuperar registros de tu base de datos, tienes varios métodos de búsqueda a tu disposición. Lo mejor de ellos es que puedes ahorrarte la molestia de escribir SQL en bruto.

¿Qué hace realmente un método de búsqueda? Básicamente tres cosas: las opciones proporcionadas se convierten en una consulta SQL. Luego la consulta SQL se ejecuta y recupera los datos de la base de datos. Además, por cada fila de esa lista de resultados, obtenemos objetos Ruby recién instanciados del modelo que se corresponde con la consulta.

Si no has jugado con SQL antes, haré lo posible por mantener las cosas simples y presentarte lo más básico. Sigue los ejemplos de SQL e intenta dar sentido a estas sencillas consultas. En realidad, SQL no es una ciencia espacial, solo hay que acostumbrarse a su sintaxis. Esperamos que esto te abra el apetito para buscar algunos tutoriales útiles que completen los espacios en blanco.

Veamos algunos métodos que están a tu disposición:

  • find
  • first
  • last
  • find_by
  • all
  • find_each
  • find_in_batches
  • where
  • order
  • limit
  • offset
  • group
  • having

Todas ellas devolverán una instancia de ActiveRecord::Relation. ¿Una qué? Es una clase que tiene un espacio de nombres dentro del módulo ActiveRecord, y nos permite llamar a múltiples métodos de consulta y encadenarlos. Este objeto es el corazón de la sintaxis de consulta utilizada en Rails. Comprobemos la clase de dicho objeto y veamos por nosotros mismos:

Rieles

Objetos individuales

  • find

Este método te permite proporcionar el id primario de un objeto y recupera ese único objeto para ti. Si proporcionas un array de ids, también puedes recuperar múltiples objetos.

Rieles

SQL

Esta línea de SQL indica que quieres seleccionar todos los atributos (*) de la tabla de agentes y "filtrar" solo el registro con el id 7. Un límite hace que devuelva solo un registro de la base de datos.

  • firstlast

Como es lógico, te proporcionarán el primer y el último registro que se puede identificar por su clave primaria. Sin embargo, lo interesante es que puedes proporcionar un número opcional que te devuelva el primero o el último de ese número de registros.

Rieles

Bajo el capó, está proporcionando un nuevo límite para el número que proporciona y ordenándolo de forma ascendente o descendente.

SQL

  • find_by

Este buscador devuelve el primer objeto que coincida con la condición que tú le indiques.

Rieles

SQL

Objetos múltiples

Obviamente, a menudo necesitamos iterar sobre una colección de objetos con alguna agenda. Recuperar un solo objeto o unos pocos seleccionados a mano está bien, pero la mayoría de las veces queremos que Active Record recupere objetos en lotes.

Mostrar a los usuarios todo tipo de listas es el pan de cada día para la mayoría de las aplicaciones Rails. Lo que necesitamos es una herramienta potente con una API práctica que recoja estos objetos por nosotros, a ser posible de una manera que nos permita evitar escribir nosotros mismos el SQL implicado la mayor parte del tiempo.

  • all

Rieles

SQL

Este método es útil para colecciones de objetos relativamente pequeñas. Intente imaginar que hace esto con una colección de todos los usuarios de Twitter. No, no es una buena idea. Lo que queremos en cambio es un enfoque más afinado para tamaños de tabla más grandes.

La búsqueda de toda la tabla no va a escalar. ¿Por qué? Porque no solo pediríamos un montón de objetos, sino que tendríamos que construir un objeto por cada fila de esta tabla y ponerlos en un array en memoria. Espero que esto no parezca una buena idea. ¿Cuál es la solución para esto? Los lotes. Estamos dividiendo estas colecciones en lotes que son más fáciles de procesar en la memoria. ¡Woohoo!

Echemos un vistazo a find_each y find_in_batches. Ambos son similares, pero se comportan de forma diferente en cuanto a la forma en la que ceden los objetos en bloques. Aceptan una opción para regular el tamaño del lote. El valor por defecto es 1.000.

  • find_each

Rieles

SQL

En este caso, recuperamos un lote por defecto de 1.000 nuevos reclutas, los cedemos al bloque y los enviamos al infierno semana a semana. Dado que los lotes trocean las colecciones, también podemos decirles dónde empezar a través del inicio. Digamos que queremos procesar 3.000 posibles reclutas de una sola vez y queremos empezar por 4.000.

Rieles

SQL

Para reiterar, primero recuperamos un lote de 3.000 objetos Ruby y luego los enviamos al bloque. start nos permite especificar el id de los registros donde queremos empezar a recuperar este lote.

  • find_in_batches

Este cede su lote como un array al bloque, lo pasa a otro objeto que prefiere tratar con colecciones. El SQL es el mismo aquí.

Rieles

Condiciones

  • where

Tenemos que repasar el "where" antes de continuar. Esto nos permite especificar condiciones que limitan el número de registros devueltos por nuestras consultas: un filtro para "where" recuperar registros en la base de datos. Si has jugado con las cláusulas WHERE de SQL, puede que te sientas como en casa: lo mismo ocurre con esta envoltura de Ruby.

En SQL, esto nos permite especificar a qué fila de la tabla queremos afectar, básicamente cuando cumple algún tipo de criterio. Esta es una cláusula opcional, por cierto. En el SQL en bruto de abajo, seleccionamos solo los reclutas que son huérfanos a través de WHERE.

Seleccionar una fila específica de una tabla.

SQL

A través de where, puedes especificar condiciones con cadenas, hashes o arrays. Con todo esto, Active Record te permite filtrar por condiciones como ésta:

Rieles

SQL

Muy bonito, ¿verdad? Quiero mencionar que esto sigue siendo una operación de búsqueda, simplemente especificamos cómo queremos filtrar esta lista de inmediato. De la lista de todos los reclutas, esto devolverá una lista filtrada de candidatos huérfanos. Este ejemplo es una condición de cadena. Mantente alejado de las condiciones de cadena puras ya que no se consideran seguras debido a su vulnerabilidad a las inyecciones SQL.

Seguridad argumental

En el ejemplo anterior, ponemos la variable huérfana en la cadena con las condiciones. Esto se considera una mala práctica porque es insegura. Necesitamos escapar la variable para evitar esta vulnerabilidad de seguridad. Deberías leer sobre la inyección SQL si esto es totalmente nuevo para ti, tu base de datos podría depender de ello.

Rieles

El ? será sustituido como valor de la condición por el siguiente valor de la lista de argumentos. Así que el signo de interrogación es básicamente un marcador de posición. También puedes especificar múltiples condiciones con múltiples ? y encadenarlas. En un escenario de la vida real, usaríamos un hash de parámetros como este:

Si tienes un gran número de condiciones variables, debes utilizar condiciones de marcador de posición de clave/valor.

Rieles

SQL

El ejemplo anterior es una tontería, por supuesto, pero muestra claramente las ventajas de la notación de marcador de posición. La notación hash, en general, es definitivamente la más legible.

Rieles

Como puedes ver, puedes ir con símbolos o con cadenas, depende de ti. Vamos a cerrar esta sección con rangos y condiciones negativas a través de NOT.

Rieles

Dos puntos y puedes establecer cualquier rango que necesites.

Puedes meter el not en el where para filtrar todos los cobardes y obtener solo los resultados que no tengan ese atributo específico y no deseado. Bajo el capó, un != niega el "filtro" WHERE.

SQL

Pedidos

  • order

Para no aburrirte hasta la saciedad, vamos a hacer esto rápido.

Aplica :asc o :desc para ordenarlo como corresponde. Eso es básicamente todo, ¡así que sigamos!

Límites

  • limit

Puedes reducir el número de registros devueltos a un número determinado. Como ya se ha mencionado, la mayoría de las veces no necesitarás todos los registros devueltos. El ejemplo siguiente te dará los cinco primeros reclutas de la base de datos, los cinco primeros identificadores.

Rieles

SQL

  • offset

Si alguna vez te has preguntado cómo funciona la paginación bajo el capó, limit y offset, en conjunto, hacen el trabajo duro. limit puede valerse por sí mismo, pero offset depende del primero.

Establecer un desplazamiento es sobre todo útil para la paginación y te permite saltar el número deseado de filas en la base de datos. La página dos de una lista de candidatos podría buscarse así:

Rieles

El SQL tendría el siguiente aspecto:

De nuevo, estamos seleccionando todas las columnas del modelo de base de datos Recruit, limitando los registros devueltos a 20 objetos Ruby de la clase Recruit y saltando sobre los 20 primeros.

Grupo y Tener

Digamos que queremos una lista de reclutas agrupados por su coeficiente intelectual. En SQL, esto podría ser algo así.

De este modo se obtendría una lista en la que se vería qué posibles reclutas tienen un coeficiente intelectual de, digamos, 120, y luego otro grupo de, digamos, 140, y así sucesivamente, cualquiera que sea su coeficiente intelectual y cuántos estarían por debajo de un número específico. Así, cuando dos reclutas tienen el mismo coeficiente intelectual de 130, se agruparían.

Otra lista podría agruparse por posibles candidatos que sufran claustrofobia, miedo a las alturas o que no sean médicamente aptos para bucear. La consulta del registro activo sería simplemente así:

  • group

Rieles

Cuando contamos el número de candidatos, obtenemos un hash muy útil.

Rieles

Ya está: tenemos siete posibles reclutas con un CI de 130 y solo uno con 141. El SQL resultante sería así:

SQL

Lo importante es la parte de GROUP BY. Como puedes ver, utilizamos la tabla de candidatos para obtener sus ids. Lo que también puedes observar en este sencillo ejemplo es la mayor comodidad de lectura y escritura de las versiones de Active Record. Imagina hacer esto a mano en ejemplos más extravagantes. Claro, a veces hay que hacerlo, pero todo el tiempo es claramente una molestia que podemos evitar con gusto.

  • having

Podemos especificar aún más este grupo utilizando HAVING, una especie de filtro para el group. En ese sentido, having es una especie de cláusula WHERE para GROUP. En otras palabras, having depende del uso de group.

Rieles

SQL

Ahora hemos agrupado a nuestros candidatos en listas de personas que tienen un coeficiente intelectual mínimo de 135. Vamos a contarlos para obtener algunas estadísticas:

Rieles

SQL

También podríamos mezclarlas y ver, por ejemplo, qué candidatos con un coeficiente intelectual superior a 140 tienen relaciones o no.

Rieles

SQL

Contar estos grupos es ahora demasiado fácil:

Rieles

SQL

Reflexiones finales

Espero que este haya sido un primer vistazo útil a lo que Active Record tiene que ofrecer para hacer que tus esfuerzos de consulta sean tan legibles y convenientes como sea posible. En general, diría que es un excelente envoltorio que te evita escribir SQL a mano la mayor parte del tiempo.

En el próximo artículo, analizaremos un par de buscadores más implicados y ampliaremos lo aprendido hasta ahora.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.