Guias de Rails Espanol
Guias de Rails Espanol
de contenido
Introduccin 1.1
Empezar 1.2
I- Fundamentos de Active Record 1.3
1- Que es Active Record? 1.3.1
2- Convencin sobre Configuracin en Active Record 1.3.2
3- Creando Modelos Active Record 1.3.3
4- Sobre-escribiendo las Convenciones de Nombres 1.3.4
5- CRUD: Leyendo y Escribiendo Datos 1.3.5
6- Validaciones 1.3.6
7- Callbacks 1.3.7
8- Migraciones 1.3.8
II- Migraciones en Active Record 1.4
1- Resumen de las Migraciones 1.4.1
2- Creando una Migracin 1.4.2
3- Escribiendo una Migracin 1.4.3
4- Ejecutando Migraciones 1.4.4
5- Cambiando las Migraciones Existentes 1.4.5
6- Volcando el Esquema y T 1.4.6
7- Active Record y la Integridad Referencial 1.4.7
8- Migraciones y Semillas de Datos (Seeds) 1.4.8
III- Validaciones en Active Record 1.5
1- Resumen de las Validaciones 1.5.1
2- Helpers de Validacin 1.5.2
3- Opciones Comunes de Validacin 1.5.3
4- Validaciones Estrictas 1.5.4
5- Validaciones Condicionales 1.5.5
6- Realizacin de validaciones personalizadas 1.5.6
7- Trabajar con errores de validacin 1.5.7
8- Visualizacin de errores de validacin en vistas 1.5.8
IV- Callbacks en Active Record 1.6
1
1- El Ciclo de Vida del Objeto 1.6.1
2- Un vistazo a los Callbacks 1.6.2
3- Callbacks Disponibles 1.6.3
4- Ejecutando Callbacks 1.6.4
5- Saltando Callbacks 1.6.5
6- Parando la Ejecucin 1.6.6
7- Callbacks Relacionados 1.6.7
8- Callbacks Condicionales 1.6.8
9- Clases Callbacks 1.6.9
10- Callbacks de Transacciones 1.6.10
V- Asociaciones en Active Record 1.7
1- Por qu asociaciones? 1.7.1
2- Tipos de Asociaciones 1.7.2
3- Consejos, Trucos y Advertencias 1.7.3
4- Referencia detallada de la asociacin 1.7.4
4.1 Referencia de la asociacin belongs_to 1.7.4.1
4.2 Referencia de la asociacin has_one 1.7.4.2
4.3 Referencia de la asociacin has_many 1.7.4.3
4.4 Referencia de la asociacin has_and_belongs_to_many 1.7.4.4
4.5 Callbacks de la asociacin 1.7.4.5
4.6 Extensiones de la asociacin 1.7.4.6
5- Herencia de tabla nica 1.7.5
VI- Interfaz de Consulta de Active Record 1.8
1- Recuperacin de objetos desde la base de datos 1.8.1
2- Condiciones 1.8.2
3- Ordenando 1.8.3
4- Seleccionando campos especficos 1.8.4
5- Lmite y desplazamiento 1.8.5
6- Grupos 1.8.6
7- Having 1.8.7
8- Sobre-escribiendo condiciones 1.8.8
9- Relacin NULL 1.8.9
10- Objetos de slo lectura 1.8.10
11- Bloqueo de registros para actualizacin 1.8.11
2
12- Unir tablas 1.8.12
13- Asociaciones de carga impaciente 1.8.13
14- Ambitos 1.8.14
15- Buscadores dinmicos 1.8.15
16- Enums 1.8.16
17- Comprensin del mtodo Chaining 1.8.17
18- Buscar o construir un nuevo objeto 1.8.18
19- Bsqueda por SQL 1.8.19
20- Existencia de Objetos 1.8.20
21- Clculos 1.8.21
22- Ejecutando EXPLAIN 1.8.22
VII- Conceptos bsicos de Active Model 1.9
1- Introduccin 1.9.1
VIII- Conceptos bsicos de Action View 1.10
1- Qu es Action View? 1.10.1
2- Uso de Action View con Rails 1.10.2
3- Templates, Partials y Layouts 1.10.3
4- Partial Layouts 1.10.4
5- Rutas de las Vistas 1.10.5
6- Visin general de los helpers proporcionados por Action View 1.10.6
6.1 AssetTagHelper 1.10.6.1
6.2 AtomFeedHelper 1.10.6.2
6.3 BenchmarkHelper 1.10.6.3
6.4 CacheHelper 1.10.6.4
6.5 CaptureHelper 1.10.6.5
6.6 DateHelper 1.10.6.6
6.7 DebugHelper 1.10.6.7
6.8 FormHelper 1.10.6.8
6.9 FormOptionsHelper 1.10.6.9
6.10 FormTagHelper 1.10.6.10
6.11 JavaScriptHelper 1.10.6.11
6.12 NumberHelper 1.10.6.12
6.13 SanitizeHelper 1.10.6.13
3
6.14 CsrfHelper 1.10.6.14
7- Vistas con Locale 1.10.7
IX- Layouts y Rendering en Rails 1.11
1- Descripcin General: Cmo encajan las piezas 1.11.1
2- Creacin de respuestas 1.11.2
2.1 Rendering por defecto: Convencin sobre configuracin en Action
2.2 Uso del render 1.11.2.2 1.11.2.1
2.3 Uso de redirect_to 1.11.2.3
2.4 Uso de los headers para crear respuestas Header-Only 1.11.2.4
3 Estructuracin de los layouts 1.11.3
3.1 Asset Tag Helpers 1.11.3.1
3.2 Entendiendo Yield 1.11.3.2
3.3 Uso del mtodo content_for 1.11.3.3
3.4 Uso de Partials 1.11.3.4
3.5 Uso de layouts anidados 1.11.3.5
X- Helpers de Formulario de Action View 1.12
1- Tratamiento de formularios bsicos 1.12.1
2- Tratamiento de objetos del modelo 1.12.2
3- Hacer Select Boxes con facilidad 1.12.3
4- Uso de los helpers de formulario Fecha y Hora 1.12.4
5- Carga de archivos 1.12.5
6- Personalizacin de los constructores de formularios 1.12.6
7- Entendiendo las convenciones de nombramiento de parmetros 1.12.7
8- Formularios a Recursos Externos 1.12.8
9- Construccin de formularios complejos 1.12.9
XI- Descripcin general de Action Controller 1.13
1- Qu hace un controlador? 1.13.1
2- Convencin de nombres del controlador 1.13.2
3- Mtodos y acciones 1.13.3
4- Parmetros 1.13.4
5- Session 1.13.5
6- Cookies 1.13.6
7- Renderizando datos XML y JSON 1.13.7
8- Filters 1.13.8
4
9- Request Forgery Protection 1.13.9
10- Objetos de solicitud y respuesta 1.13.10
11- Autenticaciones HTTP 1.13.11
12- Streaming y descargas de archivos 1.13.12
13- Filtrado de logs 1.13.13
14- Rescue 1.13.14
15- Forzar el protocolo HTTPS 1.13.15
XII- Enrutamiento en Rails 1.14
1- El Propsito del Enrutador de Rails 1.14.1
2- Ruta resource: el valor predeterminado de Rails 1.14.2
3- Rutas sin resources 1.14.3
4- Personalizacin de rutas de recursos 1.14.4
5- Inspeccin y pruebas de las rutas 1.14.5
XIII - Active Support Extensiones Core 1.15
1- Cmo cargar las extensiones core 1.15.1
2- Extensiones a todos los objetos 1.15.2
XIV- API de Internacionalizacin de Rails (I18n) 1.16
1- Cmo funciona I18n en Ruby on Rails 1.16.1
2- Configuracin de una aplicacin de Rails para la internacionalizacin 1.16.2
3- Internacionalizacin y localizacin 1.16.3
4- Descripcin general de las funciones de la API I18n 1.16.4
5- Cmo almacenar sus traducciones personalizadas 1.16.5
6- Personaliza tu configuracin de I18n 1.16.6
XV- Fundamentos de Action Mailer 1.17
1- Introduccin 1.17.1
2- Envo de mensajes de correo electrnico 1.17.2
3- Recibir correos electrnicos 1.17.3
4- Action Mailer Callbacks 1.17.4
5- Uso de Helpers de Action Mailer 1.17.5
6- Configuracin de Action Mailer 1.17.6
7- Mailer Testing 1.17.7
8- Intercepcin de correos electrnicos 1.17.8
XVI - Conceptos bsicos de Active Jobs 1.18
5
1- Introduccin 1.18.1
2- El Propsito de Active Jobs 1.18.2
3- Creacin de un Job 1.18.3
4- Ejecucin del Job 1.18.4
5- Colas 1.18.5
6- Callbacks 1.18.6
7- Action Mailer 1.18.7
8- Internacionalizacin 1.18.8
9- GlobalID 1.18.9
10- Excepciones 1.18.10
11- Job Testing 1.18.11
XVII - Testing de aplicaciones Rails 1.19
1- Por qu escribir pruebas para sus aplicaciones Rails? 1.19.1
2- Introduccin a las pruebas 1.19.2
3- Base de datos del testing 1.19.3
4- Pruebas de modelos 1.19.4
5- Pruebas del sistema 1.19.5
6- Pruebas de integracin 1.19.6
7- Pruebas funcionales para sus controladores 1.19.7
8- Testeo de Rutas 1.19.8
9- Testeo de las Vistas 1.19.9
10- Testeo de los Helpers 1.19.10
11- Testeo de los Mailers 1.19.11
12- Testeo de los Jobs 1.19.12
13- Recursos Adicionales de Pruebas 1.19.13
XVIII - Seguridad de las aplicaciones de Rails 1.20
1- Introduccin 1.20.1
2- Sesiones 1.20.2
3- Falsificacin de solicitudes entre sitios (CSRF) 1.20.3
4- Redireccin y archivos 1.20.4
5- Intranet y seguridad del administrador 1.20.5
6- Gestin de usuarios 1.20.6
7- Injection 1.20.7
8- Generacin de consultas inseguras 1.20.8
6
9- Encabezados predeterminados 1.20.9
XIX- Debugging de aplicaciones Rails 1.21
1- Helpers de las Vistas para depurar 1.21.1
2- El Logger 1.21.2
3- Debugging con la gema byebug 1.21.3
4- Depuracin con la gema web-console 1.21.4
5- Depuracin de fugas de memoria 1.21.5
6- Plugins para Depurar 1.21.6
XX- Configuracin de aplicaciones de Rails 1.22
XXI- La lnea de comandos de Rails 1.23
1- Conceptos bsicos de la lnea de comandos 1.23.1
2- bin/rails 1.23.2
3- La Lnea de Comando Avanzada de Rails 1.23.3
XXII- La Canalizacin de Recursos 1.24
1- Qu es la Canalizacin de Recursos? 1.24.1
2- Cmo utilizar el canalizador de recursos 1.24.2
3- In Development 1.24.3
4- In Production 1.24.4
5- Personalizacin del Canalizador 1.24.5
6- Almacn de cach de recursos 1.24.6
7- Agregar recursos a sus gemas 1.24.7
8- Hacer de su libreria o gema un preprocesador 1.24.8
9- Actualizacin de versiones antiguas de Rails 1.24.9
XXIII - Trabajar con JavaScript en Rails 1.25
1- Una introduccin a Ajax 1.25.1
2- JavaScript no intrusivo. 1.25.2
3- Helpers integrados 1.25.3
4- Tratamiento de eventos Ajax 1.25.4
5- Problemas con el servidor 1.25.5
6- Turbolinks 1.25.6
7- Otros Recursos 1.25.7
XXIV- El proceso de inicializacin de Rails 1.26
XXV- Carga Automatica y recarga de Constantes 1.27
7
XXVI- Almacenamiento en cach con Rails: una visin general 1.28
XXVII- Instrumentacin de Active Support 1.29
XXVIII- Una gua para perfilar aplicaciones Rails 1.30
XXIX- Uso de Rails para aplicaciones API-only 1.31
1 Qu es una aplicacin API? 1.31.1
2 Por qu utilizar Rails para las API de JSON? 1.31.2
3- La configuracin bsica 1.31.3
4- Eleccin de middleware 1.31.4
5- Seleccin de los mdulos del controlador 1.31.5
XXX- Descripcin de Action Cable 1.32
8
Introduccin
Si deseas hacer alguna correccin o aporte (ya que seguro podra tener errores de
traduccin o interpretacin), puedes hacer un fork al repo principal y solicitar un pull-
request, apreciar dicha ayuda!
9
Empezar
10
I- Fundamentos de Active Record
Cmo se utilizan los modelos Active Record para manipular datos buardados en una
base de datos relacional.
11
1- Que es Active Record?
12
2- Convencin sobre Configuracin en Active Record
Tabla de Base de Datos - Plural con guiones bajos separando las palabras (ej:
book_clubs ).
Clase del Modelo - Singular con la primera letra de cada palabra en maysculas (ej:
BookClub ).
Article articles
LineItem line_items
Deer deers
Mouse mice
Person people
13
2- Convencin sobre Configuracin en Active Record
Tambin hay nombres de columnas opcionales que podrn dar caractersticas adicionales a
las instancias de Active Record:
crea el objeto.
updated_at - Automticamente guarda el da y la hora actual al momento en que se
actualiza un registro.
lock_version - Aade bloqueo optimista a un modelo.
en una asociacin.
Por ejemplo, una columna comments_count en una clase Articles que tiene muchas
instancias de Comment guardar en cache el nmero de los comentarios existentes de cada
artculo.
Mientras estos nombres de columnas son opcionales, estn en realidad reservados por
Active Record. Evita el uso de las palabras reservadas si no quieres funcionalidades extra.
Por ejemplo, type es una palabra reservada utilizada para definir que una tabla est
utilizando Herencia Simple de Tabla (STI). Si no ests utilizando STI, intenta con una
palabra anloga como context , que puede an as mantener la descripcin de los datos
que ests modelando.
14
3- Creando Modelos Active Record
Esto crear una clase modelo Product, mapeada a la tabla products de la base de datos.
Para hacer esto tambin tendrs que tener la posibilidad de mapear columnas de cada fila
con los atributos de cada instancia del modelo.
Supn que la tabla products fue creada utilizando una sentencia SQL como:
Siguiendo el esquema de arriba, tendras la capacidad de escribir cdigo como el que sigue:
p = Product.new
p.name = "Some Book"
puts p.name # "Some Book"
15
4- Sobre-escribiendo las Convenciones de Nombres
utilizada:
Si tu haces esto, tendrs que definir manualmente el nombre de la clase a contiene los
fixtures ( class_name.yml ) utilizando el mtodo the set_fixture_class en la definicin de los
test.
16
5- CRUD: Leyendo y Escribiendo Datos
5.1 Create
Los objetos Active Record pueden crearse desde un hash, un bloque o configurar sus
atributos manualmente antes de la creacin. El mtodo new retornar un nuevo objeto
mientras create retornar el objeto y lo guardar en la base de datos.
Por ejemplo, dado un modelo User con los atributos name y occupation , el mtodo
llamado create crear y guardar un nuevo registro en la base de datos:
Utilizando el mtodo new , un objeto puede ser instanciado sin haber sido guardado:
user = User.new
user.name = "David"
user.occupation = "Code Artist"
5.2 Read
Active Record provee una rica API para acceder a los datos dentro de una base de datos.
Debajo hay algunos ejemplos de diferentes mtodos provistos por Active Record.
17
5- CRUD: Leyendo y Escribiendo Datos
5.3 Update
Una vez que un objeto Active Record ha sido recuperado, sus atributos pueden ser
modificados y volver a ser guardados en la base de datos.
Un camino corto para este uso es mapear un hash con los nombres de los atributos que se
desean modificar y su valor, como por ejemplo:
Esta es la forma ms poderosa de actualizar varios atributos a la vez. Si, por otro lado,
quieres actualizar varios registros a la vez, encontrars muy til el mtodo de clase
update_all :
5.4 Delete
Asimismo, una vez que se recupera el objeto Active Record tambin puede ser destrudo, lo
cual lo borrar de la base de datos.
18
5- CRUD: Leyendo y Escribiendo Datos
19
6- Validaciones
6. Validaciones
Active Record te permite validar el estado del modelo antes que se escriba en la base de
datos. Hay varios mtodos que puedes utilizar para comprobar tu modelo y validar que un
atributo no est vaco, es nico y no est an en la base de datos, que siga un formato
especfico, y muchos ms. La validacin es una tarea muy importante a considerar cuando
se guardan datos en una base de datos, entonces los mtodos save y update toman esto
en cuenta cuando se ejecutan: ellos retornan false cuando una validacin falla y no
mantuvieron ninguna operacin en la base de datos. Todos estos tienen una contrapartida
bang (esta es , save! y update! ), las cuales son estrictas y arrojan una excepcinn
ActiveRecord::RecordInvalid si la validacin falla. Un rpido ejemplo para ilustralo:
user = User.new
user.save # => false
user.save! # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
20
7- Callbacks
7. Callbacks
Las retrollamadas Active Record (o callbacks) te permiten adjuntar ciertos eventos en el
ciclo de vida de tus modelos. Esto te faculta a aadir comportamintos a tus modelos de
forma transparente en la ejecucin cuando estos eventos ocurren. Como cuando tu quieres
crear un nuevo registro, actualizarlo, destrurlo, etc. Puedes aprender ms de retrollamadas
en la Gua de Active Record Callbacks.
21
8- Migraciones
8. Migraciones
Rails provee un lenguaje de dominio especfico para manejar un esquema de base de datos
llamado migraciones (migrations). Las migraciones son ficheros guardados que se ejecutan
contra cualquier base de datos que Active Record soporte utilizando rake. Aqu hay una
migracin que crea una tabla:
Rails mantiene el historial sobre que fichero fue actualizado en la base de datos y provee
caractersticas para deshacer los cambios. Para realmente crear la tabla, deberas ejecutar
rake db:migrate y para deshacerlo rake db:rollback .
22
II- Migraciones en Active Record
Schema Migration
No debe confundirse con la migracin de datos. En la ingeniera de software, la migracin
de esquemas (tambin migracin de base de datos, gestin de cambios de base de datos)
se refiere a la gestin incremental, cambios reversibles a los esquemas de base de datos
relacional. Se realiza una migracin de esquema en una base de datos siempre que sea
necesario actualizar o revertir el esquema de dicha base de datos a alguna versin ms
reciente o anterior.
Riesgos y beneficios
23
II- Migraciones en Active Record
La migracin de esquemas permite corregir errores y adaptar los datos a medida que
cambian los requisitos. Son una parte esencial de la evolucin del software, especialmente
en entornos giles (ver ms abajo).
Los datos daados que fueron escritos por las versiones viejas del software y que no
fueron limpiadas correctamente
Dependencias implcitas en los datos que nadie ms conoce
Personas que cambian directamente la base de datos sin utilizar las herramientas
designadas
Errores en las herramientas de migracin del esquema
Errores en los supuestos de cmo se deben migrar los datos
Por estas razones, el proceso de migracin necesita un alto nivel de disciplina, pruebas
exhaustivas y una estrategia de copia de seguridad.
24
1- Resumen de las Migraciones
Esta migracin aade una tabla llamada products con una columna de cadena de
caractres llamada name y una columna de texto llamada description . Una columna de
clave primaria llamada id ser tambin aadida implcitamente, como la clave primaria
por defecto para todos los modelos Active Record. Los macro timestamps aaden dos
columnas, created_at y updated_at . Estas columnas especiales son automaticamemente
administradas por Active Record si existen.
Nota que nosotros definimos el cambio que queremos que ocurra a travs del tiempo. Antes
de que esta migracin se ejecute, no exista la tabla, despus de la migracin la tabla
existir. Active Record, tambien sabe como revertir esta migracin. Si ejecutamos la
migracin hacia atrs, borrar la tabla. En las bases de datos que soportan transacciones
con declaraciones que cambian el esquema, las migraciones son envueltas en una
transaccin. Si la base de datos no soporta esto, cuando una migracin falla la parte de
esta que ha tenido xito no se vuelve atrs. Tendrs que hacer el retroceso de los cambios
que fueron hechos a mano.
25
1- Resumen de las Migraciones
Si tu deseas en una migracin hacer algo que Active Record no sabe como revertir, puedes
utilizar reversible :
def down
change_table :products do |t|
t.change :price, :integer
end
end
end
26
2- Creando una Migracin
Por supuesto, calcular los instantes no es divertido, entonces Active Record provee un
generador que hace esto por ti:
generar
27
2- Creando una Migracin
De modo similar, puedes generar una migracin para remover una columna desde la lnea
de comandos:
generar
generar
28
2- Creando una Migracin
generar
Esta migracin crear una columna user_id y un ndice apropiado. Hay tambin un
generador que produce tablas de interseccin, si JoinTable es parte del nombre:
29
2- Creando una Migracin
30
3- Escribiendo una Migracin
El cual crea una tabla products con una columna llamada name (y como se discutir a
continuacin, una columna implcita id ).
Por defecto, create_table crear una clave primaria llamada id . Puedes cambiar el
nombre de la clave primaria con la opcin :primary_key (no te olvides de actualizar el
modelo correspondiente) o, si no quieres ninguna clave primaria, puedes escribir la opcin
id: false . Si necesitas pasarle a la base de datos opciones especficas puedes escribir un
Esto aadir ENGINE=BLACKHOLE con la declaracin SQL utilizada para crear una tabla
(cuando utilizamos MySQL, por defecto es ENGINE=InnoDB ).
31
3- Escribiendo una Migracin
La cual crear una tabla categories_products con dos columnas llamadas category_id y
product_id . Esas columnas tienen la opcin :null configurada a false por defecto.
Puedes pasar la opcin :table_name cuando quieras para adaptar el nombre de la tabla a
tus necesidades. Por ejemplo:
create_join_table tambin acepta un bloque, el cual puedes utilizar para aadir ndices
32
3- Escribiendo una Migracin
Esto establece el campo :name de products a una columna NOT NULL y el valor por
defecto del campo :approved a false .
default Permite establecer un valor por defecto de la columna. Nota que si utilizas un
valor dinmico (como una fecha), el valor por defecto solo ser calculado la primera vez
(ej: en la fecha y hora que la migracin es aplicada).
index Aade un ndice para la columna.
required Aade required: true para las asociaciones belongs_to y null: false
33
3- Escribiendo una Migracin
Esto aade una nueva clave fornea a la columna author_id en la tabla articles . La
clave hace referencia a la columna id de la tabla authors . Si los nombres de las
columnas no pueden ser derivados de los nombres de las tablas, puedes utilizar ls opciones
:column y :primary_key .
Rails generar un nombre para cada clave fornea empezando por fk_rails_ seguido por
10 caracteres aleatorios. Hay una opcin :name para especificar un nombre diferente si
fuera necesario.
Active Record solo soporta una columna simple como clave fornea. execute y
structure.sql son requeridas para utilizar claves forneas compuestas.
34
3- Escribiendo una Migracin
add_column
add_index
add_reference
add_timestamps
add_foreign_key
create_table
create_join_table
drop_table (must supply a block)
drop_join_table (must supply a block)
remove_timestamps
rename_column
rename_index
remove_reference
rename_table
35
3- Escribiendo una Migracin
reversible do |dir|
dir.up do
# aadir una restriccin CHECK
execute <<-SQL
ALTER TABLE distributors
ADD CONSTRAINT zipchk
CHECK (char_length(zipcode) = 5) NO INHERIT;
SQL
end
dir.down do
execute <<-SQL
ALTER TABLE distributors
DROP CONSTRAINT zipchk
SQL
end
end
Utilizando reversible nos aseguraremos que las instrucciones son ejecutadas en el orden
correcto tambin. Si el ejemplo de la anterior migracin es revertido, el bloque down ser
ejecutado despus de que la columna home_page_url sea borrada y justo antes de que la
tabla distributors se borre.
Algunas veces tu migracin har algo que es simplemente irreversible, por ejemplo, puede
borrar algunos datos, En tales casos, puedes lanzar una excepcin
ActiveRecord::IrreversibleMigration en tu bloque down . Si alguien intenta revertir tu
ejecutas un up seguido por un down . Por ejemplo, si creas una tabla en el mtodo up ,
36
3- Escribiendo una Migracin
drop_table :distributors
end
end
37
3- Escribiendo una Migracin
require_relative '2012121212_example_migration'
create_table(:apples) do |t|
t.string :variety
end
end
end
El mtodo revert tambin acepta un bloque de instrucciones para revertir. Este puede ser
utilizado para revertir partes seleccionadas de las migraciones. Por ejemplo, vamos a
imaginar que la ExampleMigration es "commiteada" y ms tarde se decide que lo mejor
sera utilizar validaciones Active Record, en lugar de la restriccin CHECK, para verificar el
cdigo postal (zipcode).
La misma migracin podra tambin haberse escrito sin utilizar revert pero esto podra
haber llevado unos pocos pasos ms: revertiendo el orden de create_table y reversible ,
reemplazando create_table por drop_table , y finalmente reemplazando up por down y
vice-versa. Todo esto est a cargo de revert.
38
3- Escribiendo una Migracin
39
4- Ejecutando Migraciones
4. Ejecutando Migraciones
Rails provee un conjunto de tareas Rake para ejecutar cierto conjunto de migraciones.
Si especificas una versin de destino, Active Record ejecturar las migraciones requeridas
( change , up , down ) hasta alcanzar la versin especfica. La versin es el prefijo numrico
en el nombre de fichero de la migracin. Por ejemplo, para migrar a la versin
20080906120000 ejectuta:
$ bin/rake db:rollback
Esto ejecutar hacia atrs la ltima migracin, ya sea por revertir el mtodo change o por
ejecucin del mtodo down . Si necesitas deshacer varias migraciones puedes proveer un
parmetro STEP:
40
4- Ejecutando Migraciones
La tarea db:migrate:redo es un atajo para deshacer y luego migrar hacia arriba otra vez.
Con la tarea db:rollback , tambin puedes utilizar el parmetro STEP .
Ninguna de estas tareas Rake hace algo que no se pueda hacer con db:migrate . Son
simplemente ms convenientes, por que no necesitas escribir la versin especfica desde la
cual hay deshacer y volver a ejecutar las migraciones.
Esto no es lo mismo que ejecutar todas las migraciones. Esto utilizar nicamente el fichero
schema.rb actual. Si una migracin no puede ser revertida, rake db:reset no te podr
ayudar. Para descubrir ms acerca del volcado del esquema ver la seccin El Volcado del
Esquema y T.
ejecutara la migracin 20080906120000 por ejecucin del mtodo change (o del mtodo
up ). Esta tarea primero comprobar si la migracin est ya realizada y no har nada si
41
4- Ejecutando Migraciones
Varios mtodos son provistos en las migraciones que te permiten controlar todo esto:
Metodo Propsito
Toma un bloque como argumento y suprime cualquier salida
suppress_messages
generada por el bloque.
Toma como argumento un mensaje y emite tal cual es. Se le
say puede pasar un segundo argumento booleano para especificar
si se va a tabular o no.
42
4- Ejecutando Migraciones
Si quieres que Active Record no muestre ninguna salida, ejecutando rake db:migrate
VERBOSE=false se suprimirn toda las salidas.
43
5- Cambiando las Migraciones Existentes
En general, editar una migracin existente no es una buena idea. Crears trabajo extra para
ti mismo y tus colaboradores y causar mayores dolores de cabeza si la versin existente
de una migracin ha sido ya ejecutada en los servidores de produccin. En su lugar,
deberas escribir una nueva migracin que realice los cambios que requieres. Editar una
migracin anterior con otra recin generada que no ha sido "commiteada" en la base de
datos, controlamos mejor el cdigo fuente (que adems en general no se ha propagado
ms all de tu mquina de desarrollo) y es relativamente inofensivo, y se convierte en una
mejor practica.
El mtodo revert puede ser de mucha ayuda cuando escribes una nueva migracin para
deshacer migraciones anteriores en conjunto o en parte (ver Revertir Migraciones
Anteriores ver arriba).
44
6- Volcando el Esquema y T
6. Volcando el Esquema y T
6.1 Para qu son los Ficheros de Esquema?
Las migraciones, con lo poderosas que pueden ser, no son la fuente fiel de tu esquema de
base de datos. Este rol cae sobre ya sea sobre el fichero db/schema.rb o un fichero SQL
generado por Active Record al examinar la base de datos. Estos no estn diseados para
ser editados, representan solo el estado actual del esquema de la base de datos.
Por ejemplo, as es como la base de datos de test es creada: la actual base de datos de
desarrollo es volcada (ya sea desde db/schema.rb o desde db/structure.sql ) y luego
grabada en la base de datos de test .
El fichero de esquema tambin es til si quieres echar un vistazo a los atributos que un
objeto Active Record tiene. Esta informacin no est en el cdigo de los modelos y es
frecuentemente propagada a travs de varias migraciones, pero esta informacin est muy
bien resumida en el fichero de esquema.
Si miras este fichero encontrars que luce casi como una gran migracin:
45
6- Volcando el Esquema y T
ActiveRecord::Schema.define(version: 20080906171750) do
create_table "authors", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
En muchos sentidos esto es exactamente lo que es. Este fichero fue creado inspeccionando
la base de datos y expresando su estructura utilizando create_table , add_index , etc.
Porque es independiente de la base de datos, podra ser cargado en cualquier base de
datos que Active Record soporte. Esto podra ser muy til si tienes que distribuir una
aplicacin que debe estar disponible para ejecutarse contra multiples bases de datos.
Sin embargo hay algunas funcionalidades que quedan fuera: db/schema.rb no puede
expresar items especficos de una base de datos como disparadores, o procedimientos
almacenados. Mientras que en una migracin tu puedes ejecutar definiciones SQL
personlizadas, el volcado de esquema no puede reconstituir aquellas definiciones desde la
base de datos. Si ests utilizando caractersticas como estas, entonces deberas configuar
el formato del esquema a :sql .
se utiliza pg_dump . Para MySQL, este fichero contendr la salida SHOW CREATE TABL de te
varias tablas.
Cargar estos esquemas es sencillamente cuestin de ejecutar las definiciones SQL que
contienen. Por defincin, esto crear una copia perfecta de la estructura de la base de
datos. Utilizando el formato del esquema :sql sin embargo, vamos a asegurarnos la carga
del esquema en otro RDBMS(Relational Data Base Manager System - Sistema de gestin
de bases de datos relacionales ) distinto al que fue utilizado para crearlo.
46
6- Volcando el Esquema y T
db/schema.rb contiene la versin actual de la base de datos. Esto asegura que ocurrirn
conflictos en el caso de que se mezclen dos ramas que han tocado el esquema. Cuando
esto ocurre, resuelve los conflictos manualmente, manteniendo el nmero de versin ms
alto entre los dos.
47
7- Active Record y la Integridad Referencial
Las validaciones tal como validates :foreign_key, uniqueness: true son un modo por el
cual los modelos pueden forzar la integridad de los datos. La opcin :dependent en las
asociaciones permite a los modelos destruir los objetos que son hijos cuando el padre es
destruido. Como cualquier cosa que opere a nivel de aplicacin, eso no garantiza integridad
referencial, entonces algunas personas se aseguran esta con restricciones sobre las claves
forneas en la base de datos.
Sin embargo Active Record no provee todas las herramientas para trabajar directamente
con algunas caractersticas, el mtodo execute puede ser utilizado para ejecutar un SQL
arbitrario.
48
8- Migraciones y Semillas de Datos (Seeds)
def down
Product.delete_all
end
end
Sin embargo, Rails tiene una caraterstica 'seeds' que puede ser utilizada para crear las
semillas en una base de datos con datos iniciales. Esta es una caracterstica realmente
simple: solo rellena db/seeds.rb con algn codigo Ruby, y ejecuta rake db:seed:
5.times do |i|
Product.create(name: "Product ##{i}", description: "A product.")
end
49
III- Validaciones en Active Record
Cmo utilizar los mtodos para construir mtodos de ayuda a las validaciones Active
Record.
Cmo crear tus propios mtodos de validacin a medida.
Cmo trabajar con los mensajes de error generados por el proceso de validacin.
50
1- Resumen de las Validaciones
Como puedes ver, nuestra validacin nos hace saber que nuestro objeto Person no es
vlido sin un atributo name . La segunda instancia de Person no ser guardada en la base
de datos.
Hay varias otras maneras de validar los datos antes de guardarlos en tu base de datos,
incluyendo una restricciones nativas de la base de datos, validaciones del lado del cliente y
validaciones en al nivel del controlador. Aqu un resumen de las mismas:
51
1- Resumen de las Validaciones
Las validaciones del lado del cliente suelen ser utilizadas, pero son generalmente poco
confiables si se utilizan solas. Si son implementadas utilizando JavaScript, pueden ser
sobrepasadas si el JavaScript est quitado en el navegador del usuario. Sin embargo,
si se combinan con otras tcnicas, las validaciones del lado del cliente pueden ser una
manera conveniente de proporcionar una respuesta inmediata a quienes utilicen tu
pgina.
Las validaciones en el nivel del controlador pueden ser temporalmente utilizadas, pero
frecuentemente se vuelven incomprensibles y difciles de probar y mantener. Siempre
que sea posible, es una buena idea mantener los controladores limpios, esto har que
sea un placer trabajar en tu aplicacin a largo plazo.
Elgelas con certeza, en casos especficos. Esta es la opinin del equipo de Rails que las
validaciones al nivel del modelo son las ms apropiadas en la mayora de las
circunstancias.
el objeto ser guardado en la tabla apropiada de la base de datos. Active Record utiliza el
mtodo de instancia new_record? para determinar si un objeto est ya en la base de datos
o no. Considera la siguiente clase Active Record:
$ bin/rails console
>> p = Person.new(name: "John Doe")
=> #<Person id: nil, name: "John Doe", created_at: nil, updated_at: nil>
>> p.new_record?
=> true
>> p.save
=> true
>> p.new_record?
=> false
Al crear y guardar un nuevo registro se enviar una operacin SQL INSERT a la base de
datos. En cambio al actualizar un registro existente enviaremos una operacin SQL UPDATE .
Las validaciones tpicamente son ejecutadas antes que estos comandos se enven a la
base de datos. Si alguna validacin falla, el objeto ser marcado como invlido y Active
52
1- Resumen de las Validaciones
Hay muchas maneras para cambiar el estado de un objeto en la base de datos. Algunos
mtodos dispararn validaciones, pero otros no lo harn. Esto significa que es posible
guardar un objeto en la base de datos en un estado invlido si no tienes cuidado.
create
create!
save
save!
update
update!
Las versiones bang (ej: save! ) lanzan una excepcin si el registro es invlido. Las
versiones no-bang como save y update retornan false , y create solo retorna el objeto.
decrement!
decrement_counter
increment!
increment_counter
toggle!
touch
update_all
update_attribute
update_column
update_columns
update_counters
Nota que save tambin tiene la posibilidad de saltar validaciones si se le pasa de argumento
validate: false . Esta tcnica debe ser utilizada con precaucin.
save(validate: false)
53
1- Resumen de las Validaciones
Para verificar si un objeto es o no vlido, Rails utiliza el mtodo valid? . Tambin puedes
utilizar este mtodo por ti mismo. valid? dispara tus validaciones y retorna true si no
fueron encontrados errores en el objeto, y false de lo contrario. Como puedes ver aqu:
Despus de que Active Record ha ejecutado las validaciones, cualquier error encontrado
puede ser conocido a travs de la instancia del mtodo errors.messages , el cual retorna
una coleccin de errores. Por definicin, un objeto es vlido si la coleccin est vaca
despus de ejecutar las validaciones.
Nota que un objeto instanciado con new no reportar errores mientras solo sea
instanciado aunque sea tcnicamente invlido, porque las validaciones no sern
ejecutadas cuando utilizas new.
>> p = Person.new
# => #<Person id: nil, name: nil>
>> p.errors.messages
# => {}
>> p.valid?
# => false
>> p.errors.messages
# => {name:["can't be blank"]}
>> p = Person.create
# => #<Person id: nil, name: nil>
>> p.errors.messages
# => {name:["can't be blank"]}
>> p.save
# => false
>> p.save!
# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
>> Person.create!
# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
54
1- Resumen de las Validaciones
1.5 errors[]
Para verificar si un atributo en particular de un objeto es vlido, lo puedes verificar utilizando
errors[:attribute] . Esto retornar un un array de todos los errores por :attribute . Si no
Este mtodo es solo utilizado despus de que las validaciones se han ejectuado, porque
solo inspecciona la coleccin de errores y no disparan validaciones por si mismos. Esto es
diferente desde el mtodo ActiveRecord::Base#invalid? que explicamos antes porque este
no verifica la validez del objeto no tiene ese objetivo. Solo comprueba para ver si hay
errores encontrados en un atributo individual del objeto.
55
2- Helpers de Validacin
2. Helpers de Validacin
Active Record ofrece muchos helpers de validacin predefinidos que puedes utilizar
directamente dentro de las definiciones de tu clase. Estos helpers proveen las reglas de
validacin comunes. Cada vez que una validacin falla, un mensaje de error es aadido a la
coleccin de errors del objeto, y este mensaje es asociado con el atributo que est siendo
validado.
Cada ayudante acepta un nmero arbitrario de nombres de atributos, entonces con una
simple lnea de cdigo puedes aadir algn tipo de validadacin a varios atributos.
Todos ellos aceptan las opciones :on y :message , las cuales definen cuando la validacin
se ejecuta y el mensaje que debera ser aadido a la coleccin errors si falla,
respectivamente. La opcin :on toma uno de los valores :create o :update . Hay un
mensaje de error por defecto para cada uno de los helpers de validacin. Estos mensajes
son utilizados cuando la opcin :message no est especificada. Vamos a repasar cada uno
de los helpers disponibles.
2.1 acceptance
Este mtodo valida si un checkbox en la interfaz de usuarios es chequeado al enviar un
formulario. Esto es tpicamente utilizado cuando el usuario necesita dar su conformidad
sobre los trminos y servicios de tu aplicacin, confirmndolo despus de leer algn texto o
algo por el estilo. Esta validacin es muy especfica para aplicaciones web y este mtodo
acceptance no necesita guardarse en ningn sitio de tu base de datos (si no tienes un
Puede recibir una opcin :accept , la cual determina que valor ser considerado aceptable.
Por defecto es "1" y puede ser cambiado fcilmente.
56
2- Helpers de Validacin
2.2 validates_associated
Deberas utilizar este helper cuando tu modelo tiene asociaciones con otros modelos y
tambin necesiten ser validados. Cuando intentas guardar tu objeto valid? ser llamado
por cada uno de los objetos asociados.
El mensaje de error por defecto para validates_associated es "is invalid". Nota que cada
objeto asociado contendr sus propias colecciones errors ; los errores no escalan hacia el
modelo llamado.
2.3 confirmation
Puedes utilizar este helper cuando tengas dos campos de texto que deban recibir
exactamente el mismo contenido. Por ejemplo, puedes querer confirmar una direccin de
email y un password. Esta validacin crea un atributo virtual cuyo nombre es el campo que
tiene que ser confirmado con la _confirmation aadida.
57
2- Helpers de Validacin
2.4 exclusion
Este helper valida que los valores de los atributos no estn incluidos en una configuracin
dada. En realidad, esta configuracin puede ser cualquier objeto enumerable.
El helper exclusion tiene una opcin :in que recibe la configuracin de los valores que
no sern aceptados por los atributos validados. La opcin :in tiene un alias llamado
:within que puedes utilizar para el mismo propsito, si lo quieres. Este ejemplo utiliza la
opcin :message para mostrar como puedes incluir los valores de los atributos.
2.5 format
Este helper valida los valores de los atributos por pruebas si coinciden o no con una
expresin regular dada, que se especifica utilizando la opcin :with .
2.6 inclusion
Este helper valida que los valores de los atributos estn incluidos en una configuracin
dada. En realidad, esta configuracin puede ser un objeto enumerable.
58
2- Helpers de Validacin
El helper inclusion tiene una opcin :in que recibe lo que debe ser incluido. La opcin
:in tiene un alias llamado :within que puedes utilizar para algunos propsitos, si lo
deseas. Los ejemplos anteriores utilizan la opcin :message para mostrar como puedes
incluir valores de los atributos.
El mensaje de error para este helper es "is not included in the list".
2.7 length
Este helper valida la longitud de los valores de los atributos. Provee una variedad de
opciones, entonces puedes especificar restricciones de longitud de diferentes maneras:
:minimum - El atributo no puede tener menos caracteres que una longitud especfica.
:in (o :within ) - La longitud del atributo debe estar contenida en un intervalo dado.
Los mensajes de error por defecto dependen del tipo de validacin de longitud que es
utilizada. Puedes personalizar estos mensajes utilizando las opciones :wrong_length ,
:too_long , :too_short y %{count} como referencia para mostrar el nmero que
corresponda para la restriccin que se est utilizando. Tambin puedes utilizar la opcin
:message para especificar un mensaje de error.
59
2- Helpers de Validacin
Este helper cuenta los caracteres por defecto, pero puedes separar el valor de diferentes
maneras utilizanod la opcin :tokenizer option :
Nota que los mensajes de error por defecto estn en plural (ej: "is too short (minimum
is %{count} characters)"). Por esta razn, cuando :minimum es 1 debes indicar un
mensaje personalizado o utilizar en su lugar presence: true . Cuando :in o :within
tienen un un lmite mnimo de 1, puedes proveer tambin un mensaje personalizado o
llamar a presence antes que a length .
2.8 numericality
Este helper valida que tus atributos tienen solo valores numricos. Por defecto, esto se
comparar con una firma seguida por un entero o un nmero de punto flotante. Para
especificar que solo nmeros enteros estn permitidos configuras a true :only_integer .
Nota que la expresin regular de arriba permite un caracter perdido de salto de lnea.
Adems :only_integer, este helper tambin acepta las siguientes opciones para aadir
restricciones a los valores acceptables:
:greater_than - Especifica que el valor del atributo debe debe ser mayor que un valor
determinado. El mensaje de error para esta opcin es "must be greater than %{count}".
:greater_than_or_equal_to - Especifica que el valor del atributo debe ser mayor o igual
a un valor determinado. El mensaje de error por defecto para esta opcin es "must be
greater than or equal to %{count}".
60
2- Helpers de Validacin
:equal_to - Especifica que el valor del atributo debe ser igual a un valor determinado.
un valor determinado. El mensaje de error por defecto es "must be less than or equal to
%{count}".
:odd - Especifica que el valor debe ser un nmero impar si es configurado a true . El
true . El mensaje de error por defecto para esta opcin es "must be even".
Por defecto, numericality no permite valores nil . Puedes utilizar la opcin allow_nil:
true para permitirlo.
2.9 presence
Este ayudante valida que los atributos especificados no estn vacos. Utiliza el mtodo
blank? para comprobar si el valor es nil o una cadena esta en blanco, es decir, una
Si desea estar seguro de que una asociacin est presente, deber probar si el objeto
asociado est presente y no la clave fornea utilizada para asignar la asociacin.
En el modelo order , para validar los registros asociados cuya presencia es necesaria,
debe especificar la opcin :inverse_of para la asociacin:
61
2- Helpers de Validacin
Mediante el uso de una de estas validaciones, se asegurar de que el valor NO ser nil
lo que resultara en un valor NULL en la mayora de los casos.
2.10 absence
Este ayudante valida que los atributos especificados estn ausentes. Utiliza el mtodo
present? para comprobar si el valor no es nil o una cadena en blanco, es decir, una
Si desea estar seguro de que una asociacin est ausente, deber probar si el objeto
asociado est ausente y no la clave fornea utilizada para asignar la asociacin.
Para validar los registros asociados cuyo absence es necesario, debe especificar la opcin:
inverse_of para la asociacin:
62
2- Helpers de Validacin
2.11 uniqueness
Este ayudante valida que el valor del atributo es nico justo antes de que el objeto sea
guardado. No crea una restriccin de unicidad en la base de datos, por lo que puede
suceder que dos conexiones de base de datos diferentes creen dos registros con el mismo
valor para una columna que desea ser nico. Para evitarlo, debe crear un ndice nico en
ambas columnas de la base de datos. Consulte el manual de MySQL para obtener ms
detalles sobre varios ndices de columnas.
La validacin ocurre realizando una consulta SQL en la tabla del modelo, buscando un
registro existente con el mismo valor en ese atributo.
Hay una opcin de :scope que puede utilizar para especificar otros atributos que se
utilizan para limitar la comprobacin de unicidad:
Tambin hay una opcin: case_sensitive que puede utilizar para definir si la restriccin de
unicidad ser sensible a maysculas o minsculas. Esta opcin predeterminada es true .
Tenga en cuenta que algunas bases de datos estn configuradas para realizar bsquedas
sin distincin entre maysculas y minsculas.
2.12 validates_with
Este ayudante pasa el registro a una clase separada para su validacin.
63
2- Helpers de Validacin
Los errores aadidos a record.errors [:base] se refieren al estado del registro como un
todo y no a un atributo especfico.
El ayudante validates_with toma una clase, o una lista de clases para utilizar para la
validacin. No hay un mensaje de error predeterminado para validates_with . Debe
agregar manualmente errores a la coleccin de errores del registro en la clase validator .
Para implementar el mtodo validate , debe tener definido un parmetro record , que es
el registro a validar.
Como todas las dems validaciones, validates_with toma las opciones :if , :unless y
:on . Si pasa otras opciones, enviar las opciones a la clase validator como option :
Tenga en cuenta que el validador se inicializar slo una vez para todo el ciclo de vida de la
aplicacin, y no en cada ejecucin de validacin, as que tenga cuidado al usar variables de
instancia dentro de ella.
2.13 validates_each
64
2- Helpers de Validacin
Este ayudante valida atributos contra un bloque. No tiene una funcin de validacin
predefinida. Deberas crear uno usando un bloque, y cada atributo pasado a
validates_each ser probado. En el ejemplo siguiente, no queremos que los nombres y
El bloque recibe el registro, el nombre del atributo y el valor del atributo. Puede hacer
cualquier cosa que desee para buscar datos vlidos dentro del bloque. Si la validacin falla,
debe agregar un mensaje de error al modelo, por lo que no es vlido.
65
3- Opciones Comunes de Validacin
3.1 :allow_nil
La opcin: allow_nil omite la validacin cuando el valor que se valida es nil .
3.2 :allow_blank
La opcin: allow_blank es similar a la opcin: allow_nil . Esta opcin permitir que la
validacin pase si el valor del atributo est en blank? , como nil o una cadena vaca por
ejemplo.
3.3 :message
Como ya lo ha visto, la opcin: message le permite especificar el mensaje que se agregar
a la coleccin de errores cuando la validacin falle. Cuando no se utiliza esta opcin, Active
Record utilizar el mensaje de error predeterminado respectivo para cada ayudante de
validacin.
3.4 :on
La opcin :on permite especificar cundo debe ocurrir la validacin. El comportamiento
predeterminado de todos los ayudantes de validacin incorporados se ejecutar en la
funcin Guardar (tanto cuando se crea un nuevo registro como cuando se est
66
3- Opciones Comunes de Validacin
67
4- Validaciones Estrictas
4. Validaciones Estrictas
Tambin puede especificar validaciones para que sean estrictas y ejecutar
ActiveModel::StrictValidationFailed cuando el objeto no es vlido.
68
5- Validaciones Condicionales
5. Validaciones Condicionales
A veces tendr sentido validar un objeto slo cuando se cumpla un predicado dado. Puede
hacerlo usando las opciones :if y :unless , que pueden tomar un smbolo, una cadena,
un Proc o un Array. Puede utilizar la opcin :if si desea especificar cundo debe ocurrir la
validacin. Si desea especificar cundo no debera ocurrir la validacin, puede utilizar la
opcin :unless .
def paid_with_card?
payment_type == "card"
end
end
69
5- Validaciones Condicionales
Todas las validaciones dentro del bloque with_options habrn pasado automticamente la
condicin if: :is_admin?
La validacin slo se ejecuta cuando todas las condiciones: if y ninguno de los :unless
se evalen a true .
70
6- Realizacin de validaciones personalizadas
6. Realizacin de validaciones
personalizadas
Cuando los ayudantes de validacin incorporados no son suficientes para sus necesidades,
puede escribir sus propios validadores o mtodos de validacin como prefiera.
class Person
include ActiveModel::Validations
validates_with MyValidator
end
71
6- Realizacin de validaciones personalizadas
Como se muestra en el ejemplo, tambin puede combinar validaciones estndar con sus
propios validadores personalizados.
def expiration_date_cannot_be_in_the_past
if expiration_date.present? && expiration_date < Date.today
errors.add(:expiration_date, "can't be in the past")
end
end
def discount_cannot_be_greater_than_total_value
if discount > total_value
errors.add(:discount, "can't be greater than total value")
end
end
end
72
6- Realizacin de validaciones personalizadas
def active_customer
errors.add(:customer_id, "is not active") unless customer.active?
end
end
73
7- Trabajar con errores de validacin
7.1 errors
Devuelve una instancia de la clase ActiveModel::Errors que contiene todos los errores.
Cada clave es el nombre del atributo y el valor es una matriz de cadenas con todos los
errores.
person = Person.new
person.valid? # => false
person.errors.messages
# => {:name=>["can't be blank", "is too short (minimum is 3 characters)"]}
7.2 errors[ ]
errors[ ] se utiliza cuando se desea comprobar los mensajes de error de un atributo
especfico. Devuelve una matriz de cadenas con todos los mensajes de error para el
atributo dado, cada cadena con un mensaje de error. Si no hay errores relacionados con el
atributo, devuelve una matriz vaca.
74
7- Trabajar con errores de validacin
person = Person.new
person.valid? # => false
person.errors[:name]
# => ["can't be blank", "is too short (minimum is 3 characters)"]
7.3 errors.add
El mtodo add le permite agregar manualmente mensajes relacionados con atributos
particulares. Puede utilizar los mtodos errors.full_messages o errors.to_a para ver los
mensajes en la forma en que se pueden mostrar a un usuario. Esos mensajes particulares
obtienen el nombre de atributo prependido (y capitalizado). add recibe el nombre del
atributo al que desea agregar el mensaje y el propio mensaje.
person.errors[:name]
# => ["cannot contain the characters !@#%*()_-+="]
person.errors.full_messages
# => ["Name cannot contain the characters !@#%*()_-+="]
75
7- Trabajar con errores de validacin
person.errors[:name]
# => ["cannot contain the characters !@#%*()_-+="]
person.errors.to_a
# => ["Name cannot contain the characters !@#%*()_-+="]
7.5 errors.clear
El mtodo clear se utiliza cuando intencionalmente desea borrar todos los mensajes de la
coleccin de errores. Por supuesto, llamar a errors.clear sobre un objeto no vlido en
realidad no lo har valid: la coleccin de errores ahora estar vaca, pero la prxima vez
que llame valid? O cualquier mtodo que intente guardar este objeto en la base de datos,
las validaciones se ejecutarn de nuevo. Si alguna de las validaciones falla, la coleccin de
errores se rellenar de nuevo.
76
7- Trabajar con errores de validacin
person = Person.new
person.valid? # => false
person.errors[:name]
# => ["can't be blank", "is too short (minimum is 3 characters)"]
person.errors.clear
person.errors.empty? # => true
p.errors[:name]
# => ["can't be blank", "is too short (minimum is 3 characters)"]
7.6 errors.size
El mtodo size devuelve el nmero total de mensajes de error para el objeto.
person = Person.new
person.valid? # => false
person.errors.size # => 2
77
8- Visualizacin de errores de validacin en vistas
Debido a que cada aplicacin maneja este tipo de cosas de manera diferente, Rails no
incluye ningn ayudante de vista que le ayude a generar estos mensajes directamente. Sin
embargo, debido al gran nmero de mtodos que Rails le ofrece para interactuar con las
validaciones en general, es bastante fcil de construir su propio helper. Adems, al generar
un scaffold, Rails colocar algn ERB en el _form.html.erb que muestra la lista completa
de errores en ese modelo.
<ul>
<% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Adems, si utiliza los ayudantes de formulario de Rails para generar sus formularios,
cuando se produce un error de validacin en un campo, generar un <div> adicional
alrededor de la entrada.
<div class="field_with_errors">
<input id="article_title" name="article[title]" size="30" type="text" value="">
</div>
A continuacin, puede generar el estilo para este div como quiera. El scaffold que Rails
genera por defecto, por ejemplo, agrega esta regla CSS:
78
8- Visualizacin de errores de validacin en vistas
.field_with_errors {
padding: 2px;
background-color: red;
display: table;
}
Esto significa que cualquier campo con un error termina con un borde rojo de 2 pxeles.
79
IV- Callbacks en Active Record
80
1- El Ciclo de Vida del Objeto
81
2- Un vistazo a los Callbacks
before_validation :ensure_login_has_a_value
protected
def ensure_login_has_a_value
if login.nil?
self.login = email unless email.blank?
end
end
end
Los mtodos de clase macro-style pueden tambin recibir un bloque. Considera utilizar este
estilo si el cdigo dentro de tu bloque est utilizando es tan corto que llevar una sola lnea:
82
2- Un vistazo a los Callbacks
before_create do
self.name = login.capitalize if name.blank?
end
end
protected
def normalize_name
self.name = self.name.downcase.titleize
end
def set_location
self.location = LocationService.query(self)
end
end
Est considerada una buena prctica declarar los mtodos callback como privados o
protegidos. Si los dejas pblicos, pueden ser llamados desde fuera del modelo y violar el
principio de encapsular del objeto.
83
3- Callbacks Disponibles
3. Callbacks Disponibles
Aqu hay una lista con todos los callbacks Active Record, listadas en el mismo orden en el
cual sern llamados durante la ejecucin de las respectivas operaciones:
before_validation
after_validation
before_save
around_save
before_create
around_create
after_create
after_save
after_commit/after_rollback
before_validation
after_validation
before_save
around_save
before_update
around_update
after_update
after_save
after_commit/after_rollback
before_destroy
around_destroy
after_destroy
after_commit/after_rollback
84
3- Callbacks Disponibles
El callback after_find ser llamado siempre que Active Record cargue un registro desde
la base de datos. after_find es llamado antes de after_initialize si ambos estn
definidos.
after_find do |user|
puts "You have found an object!"
end
end
>> User.new
You have initialized an object!
=> #<User id: nil>
>> User.first
You have found an object!
You have initialized an object!
=> #<User id: 1>
3.5 after_touch
El callback after_touch ser llamado si un objeto Active Record es tocado.
85
3- Callbacks Disponibles
>> u.touch
Has tocado un objeto
=> true
# triggers @employee.company.touch
>> @employee.touch
Employee/Company fueron tocados
Un empleado fue tocado
=> true
86
4- Ejecutando Callbacks
4. Ejecutando Callbacks
Los siguientes mtodos disparan callbacks:
create
create!
decrement!
destroy
destroy!
destroy_all
increment!
save
save!
save(validate: false)
toggle!
update_attribute
update
update!
valid?
all
first
find
find_by
find_by_*
find_by_*!
find_by_sql
last
87
5- Saltando Callbacks
5. Saltando Callbacks
As como con las validaciones, es tambin posible saltarse callbacks por el uso de los
siguientes mtodos:
decrement
decrement_counter
delete
delete_all
increment
increment_counter
toggle
touch
update_column
update_columns
update_all
update_counters
Estos mtodos deben ser utilizados con precaucin, porque importantes reglas de negocio y
lgica de la aplicacin pueden ser mantenidas en los callbacks. Pasar por encima de ellas
sin entender las implicaciones potenciales podran dejar invlidos los datos.
88
6- Parando la Ejecucin
6. Parando la Ejecucin
Como comienzas registrando nuevos callbaks para tus modelos, ellos sern encolados para
su ejecucin. Esta cola incluir toda la validacin de tu modelo, los callbaks registrados, y la
operacin en la base de datos que ser ejecutada.
detiene y un hace ROLLBACK ; los callbacks after solo pueden llevar esto a cabo lanzando
una excepcin.
89
7- Callbacks Relacionados
7. Callbacks Relacionados
Los Callbacks trabajan a travs del modelo de relaciones, y pueden tambin ser definidos
por ellos. Supn un ejemplo donde un usuario tiene muchos artculos. Un artculo de
usuario debera ser borrado si el usuario es borrado. Vamos a aadir un callback
after_destroy al modelo User de esta relacin con el modelo Article :
def log_destroy_action
puts 'Artculo borrado'
end
end
90
8- Callbacks Condicionales
8. Callbacks Condicionales
As como las validaciones, podemos tambin crear la llamada de un mtodo condicional
sobre la satisfaccin de un predicado dado. Tambin podemos hacer esto utilizando las
opciones :if y :unless , las cuales pueden tomar un smbolo, un string, un Proc o un
Array. Puedes utilizar la opcin :if cuando quieras especificar bajo que condiciones el
callback debera ser llamado. Si quieres especificar las condiciones bajo las cuales el
callback no debera ser llamado, podras utilizar la opcin :unless .
91
8- Callbacks Condicionales
92
9- Clases Callbacks
9. Clases Callbacks
Algunas veces los mtodos callback que escribirs sern lo suficientemente tiles como
para ser reutilizados por otros modelos. Active Record hace posible crear clases que
encapsulen mtodos callbacks, entonces se vuelve muy sencillo reutilizarlos.
Aqu un ejemplo donde creamos una clase con un callback after_destroy para un modelo
PictureFile :
class PictureFileCallbacks
def after_destroy(picture_file)
if File.exist?(picture_file.filepath)
File.delete(picture_file.filepath)
end
end
end
Cuando declaramos dentro de una clase, como la de arriba, los mtodos callback recibirn
el objeto del modelo como un parmetro. Ahora podemos utilizar la clase callback en el
modelo:
class PictureFileCallbacks
def self.after_destroy(picture_file)
if File.exist?(picture_file.filepath)
File.delete(picture_file.filepath)
end
end
end
93
9- Clases Callbacks
94
10- Callbacks de Transacciones
Considera, por ejemplo, los ejemplos previos donde el modelo PictureFile necesita borrar
un fichero despus de que el registro correspondiente es destrudo. Si por algo se lanzase
una excepcin despus del callback after_destroy y la transaccin se revirtiera, el fichero
se habr borrado y dejar el modelo en un estado inconsistente. Por ejemplo, suponiendo
que picture_file_2 en el cdigo de abajo no es vlido y el mtodo save! arroja un error.
PictureFile.transaction do
picture_file_1.destroy
picture_file_2.save!
end
def delete_picture_file_from_disk
if File.exist?(filepath)
File.delete(filepath)
end
end
end
Los callbacks after_commit y after_rollback nos garantizan que sern llamados por
todos los modelos creados, actualizados, o destudos, dentro de un bloque de transaccin.
Si alguna excepcin es lanzada dentro de estos callbacks, sern ignorados y entonces no
interfieren con otros callbacks. As como tambin, si tu cdigo callback puede lanzar una
excepcin, necesitars rescatarla y manejarla apropiadamente dentro del callback.
95
10- Callbacks de Transacciones
96
V- Asociaciones en Active Record
97
1- Por qu asociaciones?
1. Por qu asociaciones?
En Rails, una asociacin es una conexin entre dos modelos Active Record. Por qu
necesitamos las asociaciones entre modelos? Porque hacen las operaciones comunes ms
simples y ms fciles en su cdigo. Por ejemplo, considere una sencilla aplicacin de Rails
que incluye un modelo para autores y un modelo para libros. Cada autor puede tener
muchos libros. Sin asociaciones, las declaraciones del modelo se veran as:
Ahora, supongamos que queremos agregar un nuevo libro para un autor existente.
Necesitamos hacer algo como esto:
O considere eliminar un autor y asegurarse de que todos sus libros tambin se eliminen:
Con las asociaciones Active Record, podemos agilizar estas y otras operaciones declarando
a Rails que hay una conexin entre los dos modelos. Aqu est el cdigo revisado para la
creacin de autores y libros:
Con este cambio, crear un nuevo libro para un autor en particular es ms fcil:
98
1- Por qu asociaciones?
@author.destroy
Para obtener ms informacin sobre los diferentes tipos de asociaciones, lea la siguiente
seccin de esta gua. A continuacin, algunos consejos y trucos para trabajar con
asociaciones y, a continuacin, una referencia completa a los mtodos y opciones para las
asociaciones en Rails.
99
2- Tipos de Asociaciones
2. Tipos de Asociaciones
Rails soporta seis tipos de asociaciones:
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many
En el resto de esta gua, aprender a declarar y utilizar las diversas formas de asociaciones.
Pero primero, una introduccin rpida a las situaciones donde cada tipo de asociacin es
apropiado.
100
2- Tipos de Asociaciones
Dependiendo del caso de uso, tambin puede ser necesario crear un ndice nico y / o una
restriccin de clave externa en la columna proveedor para la tabla de cuentas. En este
caso, la definicin de columna podra tener este aspecto:
101
2- Tipos de Asociaciones
El nombre del otro modelo se pluraliza cuando se declara una asociacin has_many .
102
2- Tipos de Asociaciones
physician.patients = patients
A continuacin, los nuevos modelos "Join" se crean automticamente para los objetos
recin asociados. Si algunas de las que ya existan anteriormente faltan, sus filas "Join" se
eliminan automticamente.
103
2- Tipos de Asociaciones
@document.paragraphs
104
2- Tipos de Asociaciones
105
2- Tipos de Asociaciones
La distincin est en donde se coloca la clave fornea (va en la tabla para la clase que
declara la asociacin belongs_to ), pero debe reflexionar tambin sobre el significado real
de los datos. La relacin has_one dice que uno de algo es tuyo, es decir, que algo te indica
algo. Por ejemplo, tiene ms sentido decir que un proveedor posee una cuenta que una
cuenta posee un proveedor. Esto sugiere que las relaciones correctas son as:
106
2- Tipos de Asociaciones
El uso de t.integer :supplier_id hace que el nombre de clave externa sea obvio y
explcito. En las versiones actuales de Rails, puede abstraer este detalle de implementacin
utilizando t.references :supplier .
107
2- Tipos de Asociaciones
La regla ms sencilla es que debe establecer una relacin has_many :through si necesita
trabajar con el modelo de relacin como una entidad independiente. Si no necesita hacer
nada con el modelo de relacin, puede ser ms sencillo configurar una relacin
has_and_belongs_to_many (aunque deber recordar crear la "join table" en la base de datos).
Puede pensar en una declaracin polimrfica de belongs_to como configurar una interfaz
que cualquier otro modelo puede usar. Desde una instancia del modelo Employee , puede
recuperar una coleccin de imgenes: @employee.pictures .
108
2- Tipos de Asociaciones
Si tiene una instancia del modelo de imagen, puede llegar a su padre a travs de
@picture.imageable . Para que esto funcione, debe declarar tanto una columna de clave
foranea como una columna "type" en el modelo que declare la interfaz polimrfica:
109
2- Tipos de Asociaciones
110
3- Consejos, Trucos y Advertencias
Pero qu pasa si desea volver a cargar la cach, porque los datos podran haber sido
cambiados por alguna otra parte de la aplicacin? Simplemente llame a "reload" en la
asociacin:
cosas. Por ejemplo, attributes o connection son malos nombres para las asociaciones.
111
3- Consejos, Trucos y Advertencias
Las asociaciones son extremadamente tiles, pero no son mgicas. Usted es responsable
de mantener el esquema de la base de datos para que coincida con sus asociaciones. En la
prctica, esto significa dos cosas, dependiendo del tipo de asociaciones que est creando.
Para asociaciones belongs_to es necesario crear claves forneas y para asociaciones
has_and_belongs_to_many es necesario crear la tabla de unin (join table) adecuada.
Esta declaracin debe ser respaldada por la declaracin de clave fornea adecuada en la
tabla de libros:
Si crea una asociacin algn tiempo despus de crear el modelo subyacente, debe recordar
crear una migracin add_column para proporcionar la clave fornea necesaria.
Es una buena prctica agregar un ndice en la clave fornea para mejorar el rendimiento de
las consultas y una restriccin de clave fornea para garantizar la integridad de los datos
referenciales:
112
3- Consejos, Trucos y Advertencias
La precedencia entre los nombres de modelo se calcula utilizando el operador <=> para
String. Esto significa que si las cadenas son de diferentes longitudes y las cadenas son
iguales en comparacin con la longitud ms corta, entonces la cadena ms larga se
considera de mayor precedencia lxica que la ms corta. Por ejemplo, se podra esperar
que las tablas paper_boxes y papers generen un nombre de tabla de unin de
papers_paper_boxes debido a la longitud del nombre paper_boxes , pero de hecho genera
Independientemente del nombre, debe generar manualmente la tabla de unin con una
migracin adecuada. Por ejemplo, considere estas asociaciones:
113
3- Consejos, Trucos y Advertencias
Estos deben ser respaldados por una migracin para crear la tabla assemblies_parts . Esta
tabla debe crearse sin una clave primaria:
114
3- Consejos, Trucos y Advertencias
module MyApplication
module Business
class Supplier < ApplicationRecord
has_one :account
end
Esto funcionar bien, ya que tanto la clase proveedor como la clase cuenta se definen
dentro del mismo mbito. Pero lo siguiente no funcionar, ya que el proveedor y la cuenta
se definen en mbitos diferentes:
module MyApplication
module Business
class Supplier < ApplicationRecord
has_one :account
end
end
module Billing
class Account < ApplicationRecord
belongs_to :supplier
end
end
end
module MyApplication
module Business
class Supplier < ApplicationRecord
has_one :account,
class_name: "MyApplication::Billing::Account"
end
end
module Billing
class Account < ApplicationRecord
belongs_to :supplier,
class_name: "MyApplication::Business::Supplier"
end
end
end
115
3- Consejos, Trucos y Advertencias
Active Record intentar identificar automticamente que estos dos modelos comparten una
asociacin bidireccional basada en el nombre de la asociacin. De esta manera, Active
Record slo cargar una copia del objeto Author , haciendo que su aplicacin sea ms
eficiente y evite datos incoherentes:
a = Author.first
b = a.books.first
a.first_name == b.author.first_name # => true
a.first_name = 'David'
a.first_name == b.author.first_name # => true
Active Record admite la identificacin automtica para la mayora de las asociaciones con
nombres estndar. Sin embargo, Active Record no identificar automticamente
asociaciones bidireccionales que contengan cualquiera de las siguientes opciones:
:conditions
:through
:polymorphic
:class_name
:foreign_key
116
3- Consejos, Trucos y Advertencias
a = Author.first
b = a.books.first
a.first_name == b.writer.first_name # => true
a.first_name = 'David'
a.first_name == b.writer.first_name # => false
Active Record proporciona la opcin: inverse_of para que pueda declarar explcitamente
asociaciones bidireccionales:
a = Author.first
b = a.books.first
a.first_name == b.writer.first_name # => true
a.first_name = 'David'
a.first_name == b.writer.first_name # => true
117
4- Referencia detallada de la asociacin
118
4.1 Referencia de la asociacin belongs_to
association
association=(associate)
build_association(attributes = {})
create_association(attributes = {})
create_association!(attributes = {})
En todos estos mtodos, la palabra association se sustituye por el smbolo pasado como
el primer argumento a belongs_to . Por ejemplo, dada la declaracin:
Book.author
Book.author=
Book.build_author
Book.create_author
Book.create_author!
Al inicializar una nueva asociacin has_one o belongs_to , debe utilizar el prefijo build_
para crear la asociacin, en lugar del mtodo association.build que se utilizara para las
asociaciones has_many o has_and_belongs_to_many . Para crear uno, use el prefijo create_ .
4.1.1.1 association
El mtodo de association devuelve el objeto asociado, si lo hay. Si no se encuentra ningn
objeto asociado, devuelve nil.
119
4.1 Referencia de la asociacin belongs_to
@author = @book.author
@author = @book.reload.author
4.1.1.2 association=(associate)
El mtodo association= asigna un objeto asociado a este objeto. Detrs de las escenas,
esto significa extraer la clave principal del objeto asociado y establecer la clave externa de
este objeto en el mismo valor.
@book.author = @author
120
4.1 Referencia de la asociacin belongs_to
:autosave
:class_name
:counter_cache
:dependent
:foreign_key
:primary_key
:inverse_of
:polymorphic
:touch
:validate
:optional
4.1.2.1: autosave
Si configura la opcin :autosave en true , Rails guardar todos los miembros cargados y
destruir los miembros marcados para su destruccin cada vez que guarde el objeto
principal.
4.1.2.2: class_name
Si el nombre del otro modelo no puede derivarse del nombre de la asociacin, puede utilizar
la opcin: class_name para proporcionar el nombre del modelo. Por ejemplo, si un libro
pertenece a un autor, pero el nombre real del modelo que contiene los autores es Patron ,
se estableceran las cosas de esta manera:
121
4.1 Referencia de la asociacin belongs_to
4.1.2.3: counter_cache
La opcin: counter_cache se puede utilizar para hacer ms eficiente el hallazgo del nmero
de objetos pertenecientes. Considere estos modelos:
122
4.1 Referencia de la asociacin belongs_to
4.1.2.4 :dependent
Controla qu sucede con los objetos asociados cuando se destruye a su propietario:
:delete_all hace que los objetos asociados sean eliminados directamente de la base
ejecutan).
:restrict_with_exception provoca que se genere una excepcin si hay registros
asociados.
:restrict_with_error causa que se agregue un error al propietario si hay objetos
asociados.
No debe especificar esta opcin en una asociacin belongs_to que est conectada con
una asociacin has_many en la otra clase. Hacerlo puede llevar a registros hurfanos en su
base de datos.
4.1.2.5 :foreign_key
Por convencin, Rails asume que la columna utilizada para mantener la clave fornea en
este modelo es el nombre de la asociacin con el sufijo _id aadido. La opcin:
foreign_key le permite establecer el nombre de la clave externa directamente:
En cualquier caso, Rails no crear columnas de clave foranea para usted. Debe definirlos
explcitamente como parte de sus migraciones.
4.1.2.6: primary_key
Por convencin, Rails asume que la columna id se utiliza para contener la clave primaria
de sus tablas. La opcin: primary_key le permite especificar una columna diferente.
123
4.1 Referencia de la asociacin belongs_to
Por ejemplo, dado que tenemos una tabla de usuarios con guid como la clave principal. Si
queremos una tabla separada de todos para mantener la clave externa user_id en la
columna guid , entonces podemos usar primary_key para lograr esto:
4.1.2.7 :inverse_of
La opcin :inverse_of especifica el nombre de la asociacin has_many o has_one que es
la inversa de esta asociacin. No funciona en combinacin con la opcion :polymorphic .
4.1.2.8 :polymorphic
Pasar true a la opcin :polymorphic indica que se trata de una asociacin polimrfica.
Las asociaciones polimrficas se discutieron en detalle anteriormente en esta gua.
4.1.2.9 :touch
Si establece la opcin: touch en true , entonces la marca de tiempo updated_at o
updated_on en el objeto asociado se establecer en la hora actual siempre que se guarde o
124
4.1 Referencia de la asociacin belongs_to
4.1.2.10 :validate
Si establece la opcin :validate en true , los objetos asociados se validarn cada vez
que guarde este objeto. De forma predeterminada es false. los objetos asociados no se
validarn cuando se guarde este objeto.
4.1.2.11 :optional
Si establece la opcin :optional en true , entonces la presencia del objeto asociado no
ser validada. De forma predeterminada, esta opcin se establece en false .
Puede utilizar cualquiera de los mtodos de consulta estndar dentro del bloque de Scope.
A continuacin se analizan las siguientes:
125
4.1 Referencia de la asociacin belongs_to
where
includes
readonly
select
4.1.3.1 where
El mtodo where permite especificar las condiciones que debe cumplir el objeto asociado.
4.1.3.2 include
Puede utilizar el mtodo include para especificar asociaciones de segundo orden que
deben cargarse con impaciencia cuando se utiliza esta asociacin. Por ejemplo, considere
estos modelos:
126
4.1 Referencia de la asociacin belongs_to
cuando es necesario.
4.1.3.3 readonly
Si utiliza readonly, el objeto asociado ser de slo lectura cuando se recupera a travs de la
asociacin.
4.1.3.4 select
El mtodo select le permite anular la clusula SQL SELECT que se utiliza para recuperar
datos sobre el objeto asociado. De forma predeterminada, Rails recupera todas las
columnas. Si utiliza el mtodo select en una asociacin belongs_to , tambin debe
establecer la opcin: foreign_key para garantizar los resultados correctos.
if @book.author.nil?
@msg = "No author found for this book"
end
127
4.1 Referencia de la asociacin belongs_to
128
4.2 Referencia de la asociacin has_one
association
association=(associate)
build_association(attributes = {})
create_association(attributes = {})
create_association!(attributes = {})
En todos estos mtodos, la asociacin se sustituye por el smbolo pasado como el primer
argumento a has_one . Por ejemplo, dada la declaracin:
Supplier.account
Supplier.account=
Supplier.build_account
Supplier.create_account
Supplier.create_account!
Al inicializar una nueva asociacin has_one o belongs_to , debe utilizar el prefijo build_
para crear la asociacin, en lugar del mtodo association.build que se utilizara para las
asociaciones has_many o has_and_belongs_to_many . Para crear uno, use el prefijo create_ .
4.2.1.1 association
El mtodo de asociacin devuelve el objeto asociado, si lo hay. Si no se encuentra ningn
objeto asociado, devuelve nil .
129
4.2 Referencia de la asociacin has_one
@account = @supplier.account
@account = @supplier.reload.account
4.2.1.2 association=(associate)
El mtodo association= asigna un objeto asociado a este objeto. Detrs de las escenas,
esto significa extraer la clave primaria de este objeto y establecer la clave externa del objeto
asociado al mismo valor.
@supplier.account = @account
130
4.2 Referencia de la asociacin has_one
:as
:autosave
:class_name
:dependent
:foreign_key
:inverse_of
:primary_key
:source
:source_type
:through
:validate
4.2.2.1 :as
Establecer la opcin: as indica que se trata de una asociacin polimrfica. Las
asociaciones polimrficas se discutieron en detalle anteriormente en esta gua.
4.2.2.2 :autosave
Si configura la opcin: autosave en true , Rails guardar todos los miembros cargados y
destruir los miembros marcados para su destruccin cada vez que guarde el objeto
principal.
4.2.2.3 :class_name
Si el nombre del otro modelo no puede derivarse del nombre de la asociacin, puede utilizar
la opcin: class_name para proporcionar el nombre del modelo. Por ejemplo, si un
proveedor tiene una cuenta, pero el nombre real del modelo que contiene cuentas es
Facturacin, debera configurar las cosas de esta manera:
131
4.2 Referencia de la asociacin has_one
4.2.2.4 :dependent
Controla qu sucede con el objeto asociado cuando se destruye su propietario:
:delete hace que el objeto asociado sea eliminado directamente de la base de datos
llamada no se ejecutan.
:restrict_with_exception hace que se eleve una excepcin si hay un registro
asociado
:restrict_with_error provoca que se agregue un error al propietario si hay un objeto
asociado
4.2.2.5: foreign_key
Por convencin, Rails asume que la columna utilizada para mantener la clave externa en el
otro modelo es el nombre de este modelo con el sufijo _id aadido. La opcin:
foreign_key le permite establecer el nombre de la clave externa directamente:
En cualquier caso, Rails no crear columnas de clave externa para usted. Debe definirlos
explcitamente como parte de sus migraciones.
4.2.2.6 :inverse_of
La opcin :inverse_of especifica el nombre de la asociacin belongs_to que es la inversa
de esta asociacin. No funciona en combinacin con las opciones :through o :as .
132
4.2 Referencia de la asociacin has_one
4.2.2.7: primary_key
Por convencin, Rails asume que la columna utilizada para mantener la clave primaria de
este modelo es id . Puede sobrescribirlo y especificar explcitamente la clave principal con
la opcin: primary_key .
4.2.2.8: source
La opcin: source especifica el nombre de la asociacin de origen para una asociacin
has_one: through .
4.2.2.9: source_type
La opcin: source_type especifica el tipo de asociacin fuente para una asociacin
has_one: through que procede a travs de una asociacin polimrfica.
4.2.2.10: through
La opcin: through especifica un modelo de combinacin mediante el cual realizar la
consulta. Las asociaciones has_one: through se discutieron en detalle anteriormente en
esta gua.
4.2.2.11: validate
Si establece la opcin: validate en true , los objetos asociados se validarn cada vez
que guarde este objeto. De forma predeterminada, esto es false : los objetos asociados no
se validarn cuando se guarde este objeto.
133
4.2 Referencia de la asociacin has_one
Puede utilizar cualquiera de los mtodos de consulta estndar dentro del bloque de mbito.
A continuacin se analizan las siguientes:
where
includes
readonly
select
4.2.3.1 where
El mtodo where permite especificar las condiciones que debe cumplir el objeto asociado.
4.2.3.2 include
Puede utilizar el mtodo include para especificar asociaciones de segundo orden que
deben cargarse con impaciencia cuando se utiliza esta asociacin. Por ejemplo, considere
estos modelos:
134
4.2 Referencia de la asociacin has_one
4.2.3.3 readonly
Si utiliza el mtodo readonly , el objeto asociado ser de slo lectura cuando se recupera a
travs de la asociacin.
4.2.3.4 select
El mtodo select le permite anular la clusula SQL SELECT que se utiliza para recuperar
datos sobre el objeto asociado. De forma predeterminada, Rails recupera todas las
columnas.
if @supplier.account.nil?
@msg = "No account found for this supplier"
end
135
4.2 Referencia de la asociacin has_one
Si el objeto principal (el que declara la asociacin has_one ) no se guarda (es decir,
new_record? Devuelve true ) los objetos secundarios no se guardan. Automticamente
Si desea asignar un objeto a una asociacin has_one sin guardar el objeto, utilice el
mtodo association.build .
136
4.3 Referencia de la asociacin has_many
collection
collection<<(object, ...)
collection.delete(object, ...)
collection.destroy(object, ...)
collection=(objects)
collection_singular_ids
collection_singular_ids=(ids)
collection.clear
collection.empty?
collection.size
collection.find(...)
collection.where(...)
collection.exists?(...)
collection.build(attributes = {}, ...)
collection.create(attributes = {})
collection.create!(attributes = {})
En todos estos mtodos, la palabra collection se reemplaza con el smbolo pasado como
el primer argumento a has_many , y collection_singular se reemplaza con la versin
singularizada de ese smbolo. Por ejemplo, dada la declaracin:
137
4.3 Referencia de la asociacin has_many
Author.books
Author.books<<(object, ...)
Author.books.delete(object, ...)
Author.books.destroy(object, ...)
Author.books=(objects)
Author.book_ids
Author.book_ids=(ids)
Author.books.clear
Author.books.empty?
Author.books.size
Author.books.find(...)
Author.books.where(...)
Author.books.exists?(...)
Author.books.build(attributes = {}, ...)
Author.books.create(attributes = {})
Author.books.create!(attributes = {})
4.3.1.1 collection
El mtodo collection devuelve un array de todos los objetos asociados. Si no hay objetos
asociados, devuelve un array vaco.
@books = @author.books
@author.books.delete(@book1)
138
4.3 Referencia de la asociacin has_many
@author.books.destroy(@book1)
4.3.1.5 collection=(objects)
El mtodo collection= hace que la coleccin contenga slo los objetos suministrados,
agregando y eliminando segn corresponda. Los cambios son persistentes en la base de
datos.
4.3.1.6 collection_singular_ids
El mtodo collection_singular_ids devuelve un array de ids de los objetos de la
coleccin.
@book_ids = @author.book_ids
4.3.1.7 collection_singular_ids=(ids)
El mtodo collection_singular_ids= hace que la coleccin contenga slo los objetos
identificados por los valores de clave fornea suministrados, aadiendo y eliminando segn
corresponda. Los cambios son persistentes en la base de datos.
4.3.1.8 collection.clear
El mtodo collection.clear elimina todos los objetos de la coleccin de acuerdo con la
estrategia especificada por la opcin dependiente. Si no se da ninguna opcin, sigue la
estrategia predeterminada. La estrategia predeterminada para has_many: through es
delete_all , y para has_many es establecer las claves externas en NULL.
@author.books.clear
Los objetos se eliminarn si estn asociados con dependent: :destroy , al igual que
dependent: :delete_all .
4.3.1.9 collection.empty?
139
4.3 Referencia de la asociacin has_many
4.3.1.10 collection.size
El mtodo collection.size devuelve el nmero de objetos de la coleccin.
@book_count = @author.books.size
4.3.1.11 collection.find(...)
El mtodo collection.find encuentra objetos dentro de la coleccin. Utiliza la misma
sintaxis y opciones como ActiveRecord::Base.find .
@available_books = @author.books.find(1)
4.3.1.12 collection.where(...)
El mtodo collection.where encuentra objetos dentro de la coleccin basados en las
condiciones suministradas, pero los objetos se cargan perezosamente, lo que significa que
la base de datos se consulta slo cuando se accede a los objetos.
4.3.1.13 collection.exists?(...)
El mtodo collection.exists? comprueba si existe un objeto que cumple las condiciones
suministradas en la coleccin. Utiliza la misma sintaxis y opciones como
ActiveRecord::Base.exists? .
140
4.3 Referencia de la asociacin has_many
@books = @author.books.build([
{ published_at: Time.now, book_number: "A12346" },
{ published_at: Time.now, book_number: "A12347" }
@books = @author.books.create([
{ published_at: Time.now, book_number: "A12346" },
{ published_at: Time.now, book_number: "A12347" }
])
141
4.3 Referencia de la asociacin has_many
:as
:autosave
:class_name
:counter_cache
:dependent
:foreign_key
:inverse_of
:primary_key
:source
:source_type
:through
:validate
4.3.2.1: as
Establecer la opcin: as indica que se trata de una asociacin polimrfica, como se ha
explicado anteriormente en esta gua.
4.3.2.2: autosave
Si configura la opcin: autosave en true , Rails guardar todos los miembros cargados y
destruir los miembros marcados para su destruccin cada vez que guarde el objeto
principal.
4.3.2.3: class_name
Si el nombre del otro modelo no puede derivarse del nombre de la asociacin, puede utilizar
la opcin: class_name para proporcionar el nombre del modelo. Por ejemplo, si un autor
tiene muchos libros, pero el nombre real del modelo que contiene los libros es Transaction ,
configuraras las cosas de esta manera:
4.3.2.4: counter_cache
Esta opcin se puede utilizar para configurar un nombre personalizado denominado:
counter_cache . Slo necesita esta opcin cuando personaliza el nombre de su:
4.3.2.5 :dependent
142
4.3 Referencia de la asociacin has_many
:destroy hace que todos los objetos asociados tambin sean destruidos
:delete_all hace que todos los objetos asociados sean eliminados directamente de la
llamada no se ejecutan.
:restrict_with_exception provoca que se genere una excepcin si hay registros
asociados
:restrict_with_error causa que se agregue un error al propietario si hay objetos
asociados
4.3.2.6: foreign_key
Por convencin, Rails asume que la columna utilizada para mantener la clave externa en el
otro modelo es el nombre de este modelo con el sufijo _id aadido. La opcin:
foreign_key le permite establecer el nombre de la clave externa directamente:
En cualquier caso, Rails no crear columnas de clave externa para usted. Debe definirlos
explcitamente como parte de sus migraciones.
4.3.2.7 :inverse_of
La opcin: inverse_of especifica el nombre de la asociacin belongs_to que es la inversa
de esta asociacin. No funciona en combinacin con las opciones: through o: as .
4.3.2.8: primary_key
143
4.3 Referencia de la asociacin has_many
Por convencin, Rails asume que la columna utilizada para mantener la clave primaria de la
asociacin es id . Puede sobre-escribirlo y especificar explcitamente la clave principal con
la opcin: primary_key .
Digamos que la tabla users tiene id como primary_key pero tambin tiene una columna
guid . El requisito es que la tabla todos debe contener el valor de la columna guid como
4.3.2.9: source
La opcin: source especifica el nombre de la asociacin de origen para una asociacin
has_many: through . Slo es necesario utilizar esta opcin si el nombre de la asociacin de
4.3.2.10: source_type
La opcin: source_type especifica el tipo de asociacin fuente para un has_many: through
de la asociacin que procede a travs de una asociacin polimrfica.
4.3.2.11: through
La opcin: through especifica un modelo de combinacin mediante el cual realizar la
consulta. Las asociaciones has_many: through proveen una manera de implementar
relaciones muchos-a-muchos, como se discuti anteriormente en esta gua.
4.3.2.12: validate
Si establece la opcin: validate en false , los objetos asociados no se validarn cada
vez que guarde este objeto. De forma predeterminada, esto es true donde los objetos
asociados se validarn cuando se guarde este objeto.
144
4.3 Referencia de la asociacin has_many
Puede haber ocasiones en las que desee personalizar la consulta utilizada por has_many .
Tales personalizaciones se pueden conseguir a travs de un bloque de scope. Por ejemplo:
Puede utilizar cualquiera de los mtodos de consulta estndar dentro del bloque de scope.
A continuacin se analizan las siguientes:
where
extending
group
includes
limit
offset
order
readonly
select
distinct
4.3.3.1 where
El mtodo where permite especificar las condiciones que debe cumplir el objeto asociado.
Si utiliza una opcin hash-style where , entonces la creacin de registros a travs de esta
asociacin se escanear automticamente utilizando el hash. En este caso, el uso de
@author.confirmed_books.create o @author.confirmed_books.build crear libros donde la
4.3.3.2 extending
145
4.3 Referencia de la asociacin has_many
4.3.3.3 group
El mtodo group proporciona un nombre de atributo para agrupar el conjunto de
resultados, utilizando una clusula GROUP BY en el buscador SQL .
4.3.3.4 includes
Puede utilizar el mtodo includes para especificar asociaciones de segundo orden que
deben cargarse con impaciencia cuando se utiliza esta asociacin. Por ejemplo, considere
estos modelos:
146
4.3 Referencia de la asociacin has_many
4.3.3.5 limit
El mtodo limit le permite restringir el nmero total de objetos que se obtendrn a travs
de una asociacin.
4.3.3.6 offset
El mtodo offset le permite especificar el desplazamiento inicial para buscar objetos a
travs de una asociacin. Por ejemplo, ->{offset (11)} saltar los primeros 11 registros.
4.3.3.7 order
El mtodo order determina el orden en el que se recibirn los objetos asociados (en la
sintaxis utilizada por una clusula SQL ORDER BY ).
4.3.3.8 readonly
Si utiliza el mtodo readonly , los objetos asociados sern de slo lectura cuando se
recuperen a travs de la asociacin.
147
4.3 Referencia de la asociacin has_many
4.3.3.9 select
El mtodo select le permite anular la clusula SQL SELECT que se utiliza para recuperar
datos sobre los objetos asociados. De forma predeterminada, Rails recupera todas las
columnas. Si especifica su propia seleccin, asegrese de incluir la clave principal y las
columnas de clave externa del modelo asociado. Si no lo hace, Rails lanzar un error.
4.3.3.10 distinct
Utilice el mtodo distinct para mantener la coleccin libre de duplicados. Esto es til en
su mayora con la opcin: through .
En el caso anterior hay dos readings y person.articles saca a relucir a ambos, aunque
estos registros apuntan al mismo artculo.
class Person
has_many :readings
has_many :articles, -> { distinct }, through: :readings
end
En el caso anterior todava hay dos lecturas. Sin embargo person.articles muestra slo
un artculo porque la coleccin carga slo registros nicos.
148
4.3 Referencia de la asociacin has_many
Si desea asegurarse de que, al insertar, todos los registros de la asociacin persistente son
distintos (para que pueda estar seguro de que al inspeccionar la asociacin que nunca
encontrar registros duplicados), debe agregar un ndice nico en La propia tabla. Por
ejemplo, si tiene una tabla denominada readings y desea asegurarse de que los artculos
slo se pueden agregar a una persona una vez, podra agregar lo siguiente en una
migracin:
Una vez que tenga este ndice nico, intentar agregar el artculo a una persona dos veces
disparar un error de ActiveRecord::RecordNotUnique
Tenga en cuenta que la comprobacin de la singularidad con algo como include? Est
sujeto a condiciones de carrera. No intente utilizar include? Para reforzar la distincin en
una asociacin. Por ejemplo, usando el ejemplo del artculo de arriba, el cdigo siguiente
sera racy porque varios usuarios podran estar intentando esto al mismo tiempo:
Si el objeto principal (el que declara la asociacin has_many ) no se guarda (es decir,
new_record? Devuelve true ), los objetos secundarios no se guardan cuando se agregan.
Si desea asignar un objeto a una asociacin has_many sin guardar el objeto, utilice el
mtodo collection.build .
149
4.3 Referencia de la asociacin has_many
150
4.4 Referencia de la asociacin has_and_belongs_to_many
collection
collection<<(object, ...)
collection.delete(object, ...)
collection.destroy(object, ...)
collection=(objects)
collection_singular_ids
collection_singular_ids=(ids)
collection.clear
collection.empty?
collection.size
collection.find(...)
collection.where(...)
collection.exists?(...)
collection.build(attributes = {})
collection.create(attributes = {})
collection.create!(attributes = {})
En todos estos mtodos, la coleccin se sustituye por el smbolo pasado como el primer
argumento a has_and_belongs_to_many , y collection_singular es reemplazado por la
versin singularizada de ese smbolo. Por ejemplo, dada la declaracin:
151
4.4 Referencia de la asociacin has_and_belongs_to_many
Part.assemblies
Part.assemblies<<(object, ...)
Part.assemblies.delete(object, ...)
Part.assemblies.destroy(object, ...)
Part.assemblies=(objects)
Part.assembly_ids
Part.assembly_ids=(ids)
Part.assemblies.clear
Part.assemblies.empty?
Part.assemblies.size
Part.assemblies.find(...)
Part.assemblies.where(...)
Part.assemblies.exists?(...)
Part.assemblies.build(attributes = {}, ...)
Part.assemblies.create(attributes = {})
Part.assemblies.create!(attributes = {})
en la tabla que une dos modelos en una relacin muchos-a-muchos, debera usar una
asociacin has_many: through en lugar de has_and_belongs_to_many .
4.4.1.2 collection
El mtodo collection devuelve una matriz de todos los objetos asociados. Si no hay
objetos asociados, devuelve una matriz vaca.
@assemblies = @part.assemblies
152
4.4 Referencia de la asociacin has_and_belongs_to_many
@part.assemblies.delete(@assembly1)
@part.assemblies.destroy(@ assembly1)
4.4.1.7 collection_singular_ids
El mtodo collection_singular_ids devuelve una matriz de ids de los objetos de la
coleccin.
@assembly_ids = @part.assembly_ids
4.4.1.9 collection.clear
El mtodo collection.clear elimina todos los objetos de la coleccin eliminando las filas
de la tabla de unin. Esto no destruye los objetos asociados.
4.4.1.10 collection.empty?
El mtodo collection.empty? devuelve true si la coleccin no contiene ningn objeto
asociado.
153
4.4 Referencia de la asociacin has_and_belongs_to_many
4.4.1.11 collection.size
El mtodo collection.size devuelve el nmero de objetos de la coleccin.
@assembly_count = @ part.assemblies.size
@assembly = @part.assemblies.find(1)
154
4.4 Referencia de la asociacin has_and_belongs_to_many
:association_foreign_key
:autosave
:class_name
:foreign_key
:join_table
:validate
4.4.2.1: association_foreign_key
155
4.4 Referencia de la asociacin has_and_belongs_to_many
Por convencin, Rails asume que la columna de la tabla de combinacin utilizada para
mantener la clave externa apuntando al otro modelo es el nombre de ese modelo con el
sufijo _id aadido. La opcin: association_foreign_key le permite establecer el nombre
de la clave externa directamente:
4.4.2.2: autosave
Si configura la opcin: autosave en true , Rails guardar todos los miembros cargados y
destruir los miembros marcados para su destruccin cada vez que guarde el objeto
principal.
4.4.2.3: class_name
Si el nombre del otro modelo no puede derivarse del nombre de la asociacin, puede utilizar
la opcin: class_name para proporcionar el nombre del modelo. Por ejemplo, si una parte
tiene muchos ensamblajes, pero el nombre real del modelo que contiene los ensamblajes
es Gadget , debera configurar las cosas de esta manera:
4.4.2.4: foreign_key
Por convencin, Rails asume que la columna de la tabla de combinacin utilizada para
mantener la clave externa apuntando a este modelo es el nombre de este modelo con el
sufijo _id aadido. La opcin: foreign_key le permite establecer el nombre de la clave
externa directamente:
156
4.4 Referencia de la asociacin has_and_belongs_to_many
4.4.2.5: join_table
Si el nombre predeterminado de la tabla de combinacin, basado en ordenamiento lxico,
no es lo que desea, puede utilizar la opcin: join_table para sustituir el valor
predeterminado.
4.4.2.6: validate
Si establece la opcin: validate en false , los objetos asociados no se validarn cada
vez que guarde este objeto. De forma predeterminada, esto es cierto: los objetos asociados
se validarn cuando se guarde este objeto.
Puede utilizar cualquiera de los mtodos de consulta estndar dentro del bloque de mbito.
A continuacin se analizan las siguientes:
where
extending
group
includes
limit
offset
order
readonly
select
distinct
157
4.4 Referencia de la asociacin has_and_belongs_to_many
4.4.3.1 where
El mtodo where permite especificar las condiciones que debe cumplir el objeto asociado.
4.4.3.2 extending
El mtodo extendido especifica un mdulo con nombre para extender el proxy de
asociacin. Las extensiones de la asociacin se discuten en detalle ms adelante en esta
gua.
4.4.3.3 group
El mtodo group proporciona un nombre de atributo para agrupar el conjunto de
resultados, utilizando una clusula GROUP BY en el buscador SQL .
4.4.3.4 includes
Puede utilizar el mtodo includes para especificar asociaciones de segundo orden que
deben cargarse con impaciencia cuando se utiliza esta asociacin.
4.4.3.5 limit
158
4.4 Referencia de la asociacin has_and_belongs_to_many
4.4.3.6 offset
El mtodo offset le permite especificar el desplazamiento inicial para buscar objetos a
travs de una asociacin. Por ejemplo, si ajusta el desplazamiento (11), omitir los primeros
11 registros.
4.4.3.7 order
El mtodo order determina el orden en el que se recibirn los objetos asociados (en la
sintaxis utilizada por una clusula SQL ORDER BY ).
4.4.3.8 readonly
Si utiliza el mtodo readonly , los objetos asociados sern de slo lectura cuando se
recuperen a travs de la asociacin.
4.4.3.9 select
El mtodo select le permite anular la clusula SQL SELECT que se utiliza para recuperar
datos sobre los objetos asociados. De forma predeterminada, Rails recupera todas las
columnas.
4.4.3.10 distinct
Utilice el mtodo distinct para quitar duplicados de la coleccin.
159
4.4 Referencia de la asociacin has_and_belongs_to_many
160
4.5 Callbacks de la asociacin
Las callbacks de la asociacin son similares a las callbacks normales, pero son activadas
por eventos en el ciclo de vida de una coleccin. Existen cuatro callbacks de asociacin
disponibles:
before_add
after_add
before_remove
after_remove
def check_credit_limit(book)
...
end
end
def check_credit_limit(book)
...
end
def calculate_shipping_charges(book)
...
end
end
161
4.5 Callbacks de la asociacin
Si una callback before_add lanza una excepcin, el objeto no se agrega a la coleccin. Del
mismo modo, si una callback before_remove produce una excepcin, el objeto no se quita
de la coleccin.
162
4.6 Extensiones de la asociacin
Si tiene una extensin que debe ser compartida por muchas asociaciones, puede utilizar un
mdulo de extensin con nombre. Por ejemplo:
module FindRecentExtension
def find_recent
where("created_at > ?", 5.days.ago)
end
end
Las extensiones pueden referirse a los internos del proxy de asociacin utilizando estos tres
atributos del accesor de proxy_association :
asociacin.
proxy_association.target devuelve el objeto asociado para belongs_to o has_one , o
163
5- Herencia de tabla nica
Rails hace esto muy fcil. Primero, vamos a generar la base Modelo del vehculo:
Ha notado que estamos agregando un campo de type ? Dado que todos los modelos se
guardarn en una sola tabla de base de datos, Rails guardar en esta columna el nombre
del modelo que se est guardando. En nuestro ejemplo, esto puede ser Car , Motorcycle
o Bicycle . STI no funcionar sin un campo type en la tabla.
A continuacin, vamos a generar los tres modelos que heredan de Vehculo. Para ello,
podemos usar la opcin --parent=PARENT , que generar un modelo que hereda del padre
especificado y sin migracin equivalente (ya que la tabla ya existe).
Esto significa que todos los comportamientos agregados a Vehculo tambin estn
disponibles para Car , como asociaciones, mtodos pblicos, etc.
164
5- Herencia de tabla nica
INSERT INTO "vehicles" ("type", "color", "price") VALUES ('Car', 'Red', 10000)
Consultar los registros de automviles solo buscar vehculos que sean automviles:
Car.all
165
VI- Interfaz de Consulta de Active Record
Si est acostumbrado a usar SQL sin procesar para buscar registros de base de datos,
generalmente encontrar que hay mejores maneras de llevar a cabo las mismas
operaciones en Rails. Active Record le asla de la necesidad de usar SQL en la mayora de
los casos.
Los ejemplos de cdigo a lo largo de esta gua se referirn a uno o ms de los siguientes
modelos:
Todos los modelos siguientes usan id como clave principal, a menos que se especifique
lo contrario.
166
VI- Interfaz de Consulta de Active Record
Active Record realizar consultas en la base de datos para usted y es compatible con la
mayora de los sistemas de bases de datos, incluyendo MySQL, MariaDB, PostgreSQL y
SQLite. Independientemente del sistema de base de datos que est utilizando, el formato
del mtodo Active Record siempre ser el mismo.
167
1- Recuperacin de objetos desde la base de datos
find
create_with
distinct
eager_load
extending
from
group
having
includes
joins
left_outer_joins
limit
lock
none
offset
order
preload
readonly
references
reorder
reverse_order
select
where
Los mtodos finder que devuelven una coleccin, como where y group , devuelven una
instancia de ActiveRecord::Relation . Los mtodos que encuentran una sola entidad, como
find y first , devuelven una sola instancia del modelo.
168
1- Recuperacin de objetos desde la base de datos
hubiere.
1.1.1 find
Utilizando el mtodo find , puede recuperar el objeto correspondiente a la clave primaria
especificada que coincida con las opciones suministradas. Por ejemplo:
Tambin puede utilizar este mtodo para consultar varios objetos. Llame al mtodo find y
pase en una matriz de claves primarias. La devolucin ser una matriz que contiene todos
los registros coincidentes para las claves primarias suministradas. Por ejemplo:
1.1.2 take
El mtodo take recupera un registro sin ningn orden implcito. Por ejemplo:
169
1- Recuperacin de objetos desde la base de datos
client = Client.take
# => #<Client id: 1, first_name: "Lifo">
Puede pasar un argumento numrico al mtodo take para devolver ese nmero de
resultados. Por ejemplo
client = Client.take(2)
# => [
# #<Client id: 1, first_name: "Lifo">,
# #<Client id: 220, first_name: "Sara">
# ]
1.1.3 first
El mtodo first encuentra el primer registro ordenado por clave principal
(predeterminado). Por ejemplo:
client = Client.first
# => #<Client id: 1, first_name: "Lifo">
170
1- Recuperacin de objetos desde la base de datos
Puede pasar un argumento numrico al primer mtodo para traer ese nmero de
resultados. Por ejemplo
client = Client.first(3)
# => [
# #<Client id: 1, first_name: "Lifo">,
# #<Client id: 2, first_name: "Fifo">,
# #<Client id: 3, first_name: "Filo">
# ]
En una coleccin que se ordena utilizando order , first devolver el primer registro
ordenado por el atributo especificado para el order .
client = Client.order(:first_name).first
# => #<Client id: 2, first_name: "Fifo">
1.1.4 last
El mtodo last encuentra el ltimo registro ordenado por clave principal (predeterminado).
Por ejemplo:
client = Client.last
# => #<Client id: 221, first_name: "Russel">
171
1- Recuperacin de objetos desde la base de datos
Puede pasar un argumento numrico al mtodo last para traer ese nmero de resultados.
Por ejemplo
client = Client.last(3)
# => [
# #<Client id: 219, first_name: "James">,
# #<Client id: 220, first_name: "Sara">,
# #<Client id: 221, first_name: "Russel">
# ]
En una coleccin que se ordena utilizando order , last devolver el ltimo registro
ordenado por el atributo especificado para order .
client = Client.order(:first_name).last
# => #<Client id: 220, first_name: "Sara">
1.1.5 find_by
El mtodo find_by encuentra el primer registro que coincide con algunas condiciones. Por
ejemplo:
172
1- Recuperacin de objetos desde la base de datos
Es equivalente a escribir
Client.where(first_name: 'Lifo').take
Pero este enfoque se vuelve poco prctico a medida que aumenta el tamao de la tabla, ya
que User.all.each le indica a Active Record que busque toda la tabla en un solo paso,
construya un objeto de modelo por fila y guarde toda la matriz de objetos de modelo en
memoria. De hecho, si tenemos un gran nmero de registros, toda la coleccin puede
exceder la cantidad de memoria disponible.
173
1- Recuperacin de objetos desde la base de datos
Rails proporciona dos mtodos que solucionan este problema dividiendo los registros en
lotes compatibles con la memoria para su procesamiento. El primer mtodo, find_each ,
recupera un lote de registros y luego produce cada registro en el bloque individualmente
como un modelo. El segundo mtodo, find_in_batches , recupera un lote de registros y
luego produce el lote completo en el bloque como una matriz de modelos.
1.2.1 find_each
El mtodo find_each recupera los registros en lotes y luego reproduce cada uno en el
bloque. En el ejemplo siguiente, find_each recupera usuarios en lotes de 1000 y los
entrega al bloque uno a uno:
User.find_each do |user|
NewsMailer.weekly(user).deliver_now
end
Este proceso se repite, obteniendo ms lotes segn sea necesario, hasta que todos los
registros hayan sido procesados.
find_each trabaja sobre las clases de los modelos, como se ha visto anteriormente, y
Siempre y cuando no tengan un order , ya que el mtodo necesita forzar un orden interno
para iterar.
:batch_size
174
1- Recuperacin de objetos desde la base de datos
:start
Por ejemplo, para enviar boletines slo a usuarios con la clave principal a partir de 2000:
:finish
Por ejemplo, para enviar boletines slo a usuarios con la clave principal desde 2000 hasta
10000:
Otro ejemplo sera si desea que varios workers manejen la misma cola de procesamiento.
Podra hacer que cada worker maneje 10000 registros estableciendo las opciones
apropiadas: start y: finish en cada worker.
:error_on_ignore
175
1- Recuperacin de objetos desde la base de datos
1.2.2 find_in_batches
El mtodo find_in_batches es similar a find_each , ya que ambos recuperan lotes de
registros. La diferencia es que find_in_batches produce lotes al bloque como un array de
modelos, en lugar de individualmente. El ejemplo siguiente ceder al bloque suministrado
una matriz de hasta 1000 facturas a la vez, con el bloque final que contiene las facturas
restantes:
Invoice.pending.find_in_batches do |invoice|
pending_invoices_export.add_invoices(invoices)
end
Siempre y cuando no tengan un order , ya que el mtodo necesita forzar un orden interno
para iterar.
176
2- Condiciones
2. Condiciones
El mtodo where permite especificar condiciones para limitar los registros devueltos, que
representan la parte WHERE de la sentencia SQL . Las condiciones se pueden especificar
como una cadena, una matriz o un hash.
campo orders_count es 2.
Construir sus propias condiciones como cadenas puras puede dejarlo vulnerable a las
explotaciones de SQL injection. Por ejemplo, Client.where("first_name LIKE '%#
{params[:first_name]}%'") no es seguro. Consulte la seccin siguiente para conocer la
177
2- Condiciones
Client.where("orders_count = #{params[:orders]}")
Esto hace ms clara la legibilidad si usted tiene un gran nmero de condiciones variables.
Slo la igualdad, los rangos y la comprobacin de subconjuntos son posibles para las
condiciones con Hash.
Client.where(locked: true)
178
2- Condiciones
En el caso de una relacin belongs_to , se puede utilizar una clave de asociacin para
especificar el modelo si se utiliza un objeto Active Record como valor. Este mtodo funciona
con relaciones polimrficas tambin.
Article.where(author: author)
Author.joins(:articles).where(articles: { author: author })
Los valores no pueden ser smbolos. Por ejemplo, no puede hacer Client.where(status:
:active)
Esto encontrar todos los clientes creados ayer mediante una instruccin BETWEEN SQL :
SELECT * FROM clients WHERE (clients.created_at BETWEEN '2008-12-21 00:00:00' AND '200
8-12-22 00:00:00')
Esto demuestra una sintaxis ms corta para los ejemplos en Array Conditions
Client.where(orders_count: [1,3,5])
Client.where.not(locked: true)
179
2- Condiciones
En otras palabras, esta consulta puede ser generada llamando un where sin argumento, y
entonces inmediatamente lo concatena con not pasar a where las condiciones. Esto
generar SQL como este:
180
3- Ordenando
3. Ordenando
Para recuperar registros de la base de datos en un orden especfico, puede utilizar el
mtodo order .
Client.order(:created_at)
# OR
Client.order("created_at")
Client.order(created_at: :desc)
# OR
Client.order(created_at: :asc)
# OR
Client.order("created_at DESC")
# OR
Client.order("created_at ASC")
Si desea llamar order varias veces, los mtodos order siguientes se aadirn al primero:
181
3- Ordenando
182
4- Seleccionando campos especficos
Client.select("viewable_by, locked")
La consulta SQL utilizada por esta llamada de bsqueda sera algo como:
Tenga cuidado porque esto tambin significa que est inicializando un objeto de modelo con
slo los campos que ha seleccionado. Si intenta acceder a un campo que no est en el
registro inicializado, recibir:
Si desea capturar slo un registro por valor nico en un campo determinado, puede utilizar
distinct :
Client.select(:name).distinct
183
4- Seleccionando campos especficos
query = Client.select(:name).distinct
# => Retorna names nicos
query.distinct(false)
# => Returns todos los names, incluso si estn duplicados
184
5- Lmite y desplazamiento
5. Lmite y desplazamiento
Para aplicar LIMIT al SQL disparado por el Model.find , puede especificar el lmite
utilizando los mtodos limit y offset en la relacin.
Puede utilizar limit para especificar el nmero de registros que se recuperarn y utilizar
offeset para especificar el nmero de registros a omitir antes de comenzar a devolver los
Client.limit(5)
Client.limit(5).offset(30)
185
6- Grupos
6. Grupos
Para aplicar una clusula GROUP BY al SQL disparado por el finder , puede utilizar el
mtodo de group .
Por ejemplo, si desea encontrar una coleccin de las fechas en las que se crearon los
pedidos:
Y esto le dar un nico objeto Order para cada fecha en la que haya pedidos en la base
de datos.
Order.group(:status).count
# => { 'awaiting_approval' => 7, 'paid' => 12 }
186
7- Having
7. Having
SQL utiliza la clusula HAVING para especificar las condiciones en los campos GROUP BY .
Por ejemplo:
Esto devuelve la fecha y el precio total de cada objeto de pedido, agrupados por el da en
que fueron pedidos y donde el precio es superior a $ 100.
187
8- Sobre-escribiendo condiciones
8- Sobre-escribiendo condiciones
8.1 Unscope
Puede especificar ciertas condiciones que se eliminarn mediante el mtodo unscope. Por
ejemplo:
Tambin puede hacer unscope sobre clusulas where especficas. Por ejemplo:
Una relacin que ha utilizado el unscope afectar cualquier relacin en la que se haga
merge :
Article.order('id asc').merge(Article.unscope(:order))
# SELECT "articles".* FROM "articles"
8.2 only
Tambin puede anular las condiciones utilizando el mtodo only . Por ejemplo:
188
8- Sobre-escribiendo condiciones
8.3 reorder
El mtodo reorder reemplaza el orden del scope predeterminado. Por ejemplo:
Article.find(10).comments.reorder('name')
8.4 reverse_order
El mtodo reverse_order invierte la clusula de ordenacin si se especifica.
189
8- Sobre-escribiendo condiciones
8.5 rewhere
El mtodo rewhere reemplaza una condicin existente, denominada where . Por ejemplo:
190
9- Relacin NULL
9. Relacin NULL
El mtodo none devuelve una relacin encadenable sin registros. Cualquier condicin
subsiguiente encadenada a la relacin devuelta continuar generando relaciones vacas.
Esto es til en escenarios donde se necesita una respuesta encadenable a un mtodo o un
scope que podra devolver resultados cero.
def visible_articles
case role
when 'Country Manager'
Article.where(country: country)
when 'Reviewer'
Article.published
when 'Bad User'
Article.none # => devolviendo [] o nil interrumpe el cdigo de llamada en este caso
end
end
191
10- Objetos de slo lectura
client = Client.readonly.first
client.visits += 1
client.save
Client se establece explcitamente para ser un objeto de slo lectura, el cdigo anterior
192
11- Bloqueo de registros para actualizacin
Bloqueo optimista
Bloqueo pesimista
Para utilizar el bloqueo optimista, la tabla necesita tener una columna llamada
lock_version del tipo integer . Cada vez que se actualiza el registro, el registro activo
c1 = Client.find(1)
c2 = Client.find(1)
c1.first_name = "Michael"
c1.save
193
11- Bloqueo de registros para actualizacin
Por ejemplo:
Item.transaction do
i = Item.lock.first
i.name = 'Jones'
i.save!
end
Tambin puede pasar el SQL sin procesar al mtodo de bloqueo para permitir diferentes
tipos de bloqueos. Por ejemplo, MySQL tiene una expresin llamada LOCK IN SHARE MODE
donde puede bloquear un registro pero an as permitir que otras consultas lo lean. Para
especificar esta expresin simplemente entre en la opcin lock :
Item.transaction do
i = Item.lock("LOCK IN SHARE MODE").find(1)
i.increment!(:views)
end
Si ya tiene una instancia de su modelo, puede iniciar una transaccin y adquirir el bloqueo
de una vez usando el siguiente cdigo:
194
11- Bloqueo de registros para actualizacin
item = Item.first
item.with_lock do
# This block is called within a transaction,
# item is already locked.
item.increment!(:views)
end
195
12- Unir tablas
12.1 joins
Hay varias maneras de utilizar el mtodo joins.
SELECT authors.* FROM authors INNER JOIN posts ON posts.author_id = authors.id AND pos
ts.published = 't'
Por ejemplo, considere los siguientes Modelos de Category, Article, Comment, Guest y Tag
196
12- Unir tablas
Ahora todo lo siguiente producir las consultas join esperadas utilizando INNER JOIN :
Category.joins(:articles)
Esto produce:
O, en espaol: "devolver un objeto Category para todas las categoras con artculos".
Tenga en cuenta que ver categoras duplicadas si ms de un artculo tiene la misma
categora. Si desea categoras nicas, puede utilizar Category.joins(:articles).distinct .
Article.joins(:category, :comments)
Esto produce:
197
12- Unir tablas
O, en espaol: "devolver todos los artculos que tienen una categora y al menos un
comentario". Tenga en cuenta que los artculos con varios comentarios se mostrarn varias
veces.
Article.joins(comments: :guest)
Esto produce:
O, en espaol: "devolver todos los artculos que tienen un comentario hecho por un
invitado."
Esto produce:
O, en espaol: "devolver todas las categoras que tienen artculos, donde esos artculos
tienen un comentario hecho por un invitado, y donde esos artculos tambin tienen una
etiqueta".
198
12- Unir tablas
Puede especificar condiciones en las tablas unidas usando las condiciones regulares
Array y String . Las condiciones de hash proporcionan una sintaxis especial para
Esto encontrar todos los clientes que tienen rdenes que se crearon ayer, de nuevo
utilizando una expresin BETWEEN SQL .
12.2 left_outer_joins
Si desea seleccionar un conjunto de registros, independientemente de si tienen o no
registros asociados, puede utilizar el mtodo left_outer_joins .
Que produce:
Lo que significa: "devolver todos los autores con su numero de posts, si tienen o no tienen
posts en absoluto"
199
13- Asociaciones de carga impaciente
Problema de consultas N + 1
Considere el siguiente cdigo, que encuentra 10 clientes e imprime sus cdigos postales:
clients = Client.limit(10)
clients.each do |client|
puts client.address.postcode
end
Este cdigo se ve bien a primera vista. Pero el problema est dentro del nmero total de
consultas ejecutadas. El cdigo anterior ejecuta 1 consulta (para encontrar 10 clientes) + 10
consultas adicionales (uno por cada cliente para cargar la direccin) = 11 consultas en total.
Active Record le permite especificar de antemano todas las asociaciones que se van a
cargar. Esto es posible especificando el mtodo includes de la llamada Model.find. Con
includes , Active Record garantiza que todas las asociaciones especificadas se cargan
clients = Client.includes(:address).limit(10)
clients.each do |client|
puts client.address.postcode
end
200
13- Asociaciones de carga impaciente
Active Record le permite cargar ansiosamente cualquier nmero de asociaciones con una
sola llamada Model.find utilizando un array, hash o un hash anidado de array/hash con el
mtodo includes .
Article.includes(:category, :comments)
Esto carga todos los artculos y la categora asociada y comentarios para cada artculo.
Esto encontrar la categora con id 1 y carga ansiosamente todos los artculos asociados,
las etiquetas y comentarios de los artculos asociados y la asociacin de invitados de cada
comentario.
Sin embargo, si tiene que hacer esto, puede usarlo como lo hara normalmente.
Esto generara una consulta que contiene un LEFT OUTER JOIN , mientras que el mtodo
join generara uno utilizando la funcin INNER JOIN .
Si no haba ninguna condicin where , esto generara el conjunto normal de dos consultas.
El uso de where slo funcionar cuando se pasa un Hash. Para los fragmentos SQL,
debe utilizar referencias para forzar joined tables :
201
13- Asociaciones de carga impaciente
Article.includes(:comments).where("comments.visible = true").references(:comments)
Si, en este caso se incluye una consulta, y no hubo comentarios para ningn artculo, todos
los artculos an se cargaran. Mediante el uso de joins (un INNER JOIN), las condiciones
de unin deben coincidir, de lo contrario no se devolvern registros.
Si una asociacin est cargada con impaciencia como parte de una join table , los
campos de una clusula de seleccin personalizada no aparecern en los modelos
cargados. Esto es porque es ambiguo si deben aparecer en el registro principal, o en el
child.
202
14- Ambitos
14. Ambitos
Scoping le permite especificar consultas de uso comn que pueden ser referenciadas como
llamadas de mtodo en los objetos o modelos de asociacin. Con estos mbitos, puede
utilizar todos los mtodos cubiertos anteriormente, como where , join e includes . Todos
los mtodos de mbito devolvern un objeto ActiveRecord::Relation que permitir que se
apliquen otros mtodos (o otros mbitos).
Para definir un mbito simple, utilizamos el mtodo scope dentro de la clase, pasando la
consulta que queremos ejecutar cuando se llama a este mbito:
Esto es exactamente lo mismo que definir un mtodo de clase, y cul se utiliza es una
cuestin de preferencia personal:
category = Category.first
category.articles.published # => [Artculos publicados pertenecientes a esta categora]
203
14- Ambitos
Article.created_before(Time.zone.now)
category.articles.created_before(time)
Al igual que los otros ejemplos, esto se comportar de manera similar a un mtodo de
clase.
204
14- Ambitos
Sin embargo, hay una advertencia importante: Un scope siempre devolver un objeto
ActiveRecord::Relation , incluso si el condicional se evala como false , mientras que un
mtodo de clase devolver nil . Esto puede causar NoMethodError al encadenar mtodos
de clase con condicionales, si cualquiera de los condicionales devuelve false .
Cuando las consultas se ejecutan en este modelo, la consulta SQL ahora se ver como
esto:
205
14- Ambitos
User.active.inactive
# SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" =
'inactive'
Podemos mezclar y combinar el scope y las condiciones where y el sql final tendr todas
las condiciones unidas con AND .
User.active.where(state: 'finished')
# SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" =
'finished'
Si queremos que la ltima clusula where gane entonces se puede usar Relation#merge
User.active.merge(User.inactive)
# SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
User.all
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
User.active
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state"
= 'active'
User.where(state: 'inactive')
# SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state"
= 'inactive'
Como se puede ver arriba, el default_scope se est fusionando tanto en el scope como
en las condiciones.
206
14- Ambitos
Si queremos eliminar el scope por cualquier razn, podemos usar el mtodo unscoped .
Esto es especialmente til si se especifica un default_scope en el modelo y no se debe
aplicar para esta consulta en particular.
Client.unscoped.load
Este mtodo elimina todo el mbito y realizar una consulta normal en la tabla.
Client.unscoped.all
# SELECT "clients".* FROM "clients"
Client.where(published: false).unscoped.all
# SELECT "clients".* FROM "clients"
Client.unscoped {
Client.created_before(Time.zone.now)
}
207
15- Buscadores dinmicos
Puede especificar un punto de exclamacin (!) al final de los buscadores dinmicos para
que generen un error ActiveRecord::RecordNotFound si no devuelven registros, como
Client.find_by_name!("Ryan")
Si desea encontrar ambos por nombre y bloqueo, puede encadenar estos buscadores
simplemente escribiendo " and " entre los campos. Por ejemplo,
Client.find_by_first_name_and_locked("Ryan", true).
208
16- Enums
16. Enums
La macro de enumeracin asigna una columna de nmero entero a un conjunto de valores
posibles.
Esto crear automticamente los mbitos correspondientes para consultar el modelo. Los
mtodos de transicin entre los estados y la consulta del estado actual tambin se agregan.
209
17- Comprensin del mtodo Chaining
Hay algunos ejemplos a continuacin. Esta gua no cubrir todas las posibilidades, slo
algunas como ejemplos. Cuando se llama a un mtodo de Active Record, la consulta no se
genera inmediatamente y se enva a la base de datos, esto slo sucede cuando los datos
son realmente necesitados. As, cada ejemplo a continuacin genera una sola consulta.
Person
.select('people.id, people.name, comments.text')
.joins(:comments)
.where('comments.created_at > ?', 1.week.ago)
Person
.select('people.id, people.name, companies.name')
.joins(:company)
.find_by('people.name' => 'John') # Esta debe ser la ltima
210
17- Comprensin del mtodo Chaining
Tenga en cuenta que si una consulta coincide con varios registros, find_by buscar
slo el primero e ignorar los dems (consulte la instruccin LIMIT 1 anterior).
211
18- Buscar o construir un nuevo objeto
18.1 find_or_create_by
El mtodo find_or_create_by comprueba si existe un registro con los atributos
especificados. Si no lo hace, entonces se llama a create . Veamos un ejemplo.
Suponga que desea buscar un cliente llamado 'Andy', y si no hay ninguno, cree uno. Puede
hacerlo ejecutando:
Client.find_or_create_by(first_name: 'Andy')
# => #<Client id: 1, first_name: "Andy", orders_count: 0, locked: true, created_at: "2
011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">
Es posible que el nuevo registro no se guarde en la base de datos; Que depende de si las
validaciones pasaron o no (al igual que crear).
Supongamos que queremos poner el atributo ' locked ' en false si estamos creando un
nuevo registro, pero no queremos incluirlo en la consulta. As que queremos encontrar el
cliente llamado "Andy", o si ese cliente no existe, crear un cliente llamado "Andy" que no
est bloqueado.
212
18- Buscar o construir un nuevo objeto
El bloque slo se ejecutar si se est creando el cliente. La segunda vez que ejecutamos
este cdigo, el bloque ser ignorado.
18.2 find_or_create_by!
Tambin puede utilizar find_or_create_by! Para generar una excepcin si el nuevo registro
no es vlido. Las validaciones no estn cubiertas en esta gua, pero supongamos por un
momento que las agregamos temporalmente
Client.find_or_create_by!(first_name: 'Andy')
# => ActiveRecord::RecordInvalid: Validation failed: Orders count can't be blank
18.3 find_or_initialize_by
El mtodo find_or_initialize_by funcionar igual que find_or_create_by pero llamar
new en lugar de create . Esto significa que se crear una nueva instancia del modelo en
nick.persisted?
# => false
nick.new_record?
# => true
Dado que el objeto todava no est almacenado en la base de datos, el SQL generado se
ve as:
213
18- Buscar o construir un nuevo objeto
nick.save
# => true
214
19- Bsqueda por SQL
subyacente devuelve un solo registro. Por ejemplo, puede ejecutar esta consulta:
19.1 select_all
find_by_sql tiene un pariente cercano llamado connection#select_all . select_all
19.2 pluck
pluck se puede utilizar para consultar columnas mltiples o individuales de la tabla
215
19- Bsqueda por SQL
Client.where(active: true).pluck(:id)
# SELECT id FROM clients WHERE active = 1
# => [1, 2, 3]
Client.distinct.pluck(:role)
# SELECT DISTINCT role FROM clients
# => ['admin', 'member', 'guest']
Client.pluck(:id, :name)
# SELECT clients.id, clients.name FROM clients
# => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]
por:
Client.pluck(:id)
# or
Client.pluck(:id, :name)
Client.select(:name).map &:name
# => ["I am David", "I am Jeremy", "I am Jose"]
Client.pluck(:name)
# => ["David", "Jeremy", "Jose"]
216
19- Bsqueda por SQL
Client.pluck(:name).limit(1)
# => NoMethodError: undefined method `limit' for #<Array:0x007ff34d3ad6d8>
Client.limit(1).pluck(:name)
# => ["David"]
19.3 ids
ids se puede utilizar para extraer ( pluck ) todos los identificadores de la relacin con la
Person.ids
# SELECT id FROM people
Person.ids
# SELECT person_id FROM people
217
20- Existencia de Objetos
Client.exists?(1)
El mtodo exist? tambin toma varios valores, pero al capturarlo devolver true si
existe alguno de esos registros.
Client.exists?(id: [1,2,3])
# or
Client.exists?(name: ['John', 'Sergei'])
Incluso es posible utilizar exist? sin ningn argumento sobre un modelo o una relacin.
Client.where(first_name: 'Ryan').exists?
Lo anterior devuelve true si hay al menos un cliente con el first_name 'Ryan' y false
en caso contrario.
Client.exists?
Lo anterior devuelve false si la tabla de clientes est vaca y true en caso contrario.
Tambin puede utilizar any? y many? Para verificar la existencia de un modelo o relacin.
218
20- Existencia de Objetos
# via a model
Article.any?
Article.many?
# via a relation
Article.where(published: true).any?
Article.where(published: true).many?
# via an association
Article.first.categories.any?
Article.first.categories.many?
219
21- Clculos
21. Clculos
Esta seccin usa count como un mtodo de ejemplo en este prembulo, pero las opciones
descritas se aplican a todas las subsecciones.
Client.count
# SELECT count(*) AS count_all FROM clients
O en una relacin:
Client.where(first_name: 'Ryan').count
# SELECT count(*) AS count_all FROM clients WHERE (first_name = 'Ryan')
Tambin puede utilizar varios mtodos de bsqueda en una relacin para realizar clculos
complejos:
Que ejecutar:
21.1 Count
Si desea ver cuntos registros hay en la tabla de su modelo, puede llamar a Client.count
y devolver el nmero. Si desea ser ms especfico y encontrar todos los clientes con su
edad presentes en la base de datos puede utilizar Client.count(:age) .
21.2 Average
Si desea ver el promedio de un determinado nmero en una de sus tablas, puede llamar al
mtodo average de la clase que se relaciona con la tabla. Esta llamada al mtodo se ver
as:
220
21- Clculos
Client.average("orders_count")
Esto devolver un nmero (posiblemente un nmero de punto flotante tal como 3.14159265)
que representa el valor promedio en el campo.
21.3 Minimum
Si desea encontrar el valor mnimo de un campo en su tabla, puede llamar al mtodo
minimum de la clase que se relaciona con la tabla. Esta llamada al mtodo se ver as:
Client.minimum("age")
21.4 Maximum
Si desea encontrar el valor mximo de un campo en su tabla, puede llamar al mtodo
maximum de la clase que se relaciona con la tabla. Esta llamada al mtodo se ver as:
Client.maximum("age")
21.5 Sum
Si desea encontrar la suma de un campo para todos los registros de su tabla, puede llamar
al mtodo sum en la clase que se relaciona con la tabla. Esta llamada al mtodo se ver
as:
Client.sum("orders_count")
221
22- Ejecutando EXPLAIN
User.where(id: 1).joins(:articles).explain
Puede producir
EXPLAIN for: SELECT `users`.* FROM `users` INNER JOIN `articles` ON `articles`.`user_i
d` = `users`.`id` WHERE `users`.`id` = 1
+----+-------------+----------+-------+---------------+
| id | select_type | table | type | possible_keys |
+----+-------------+----------+-------+---------------+
| 1 | SIMPLE | users | const | PRIMARY |
| 1 | SIMPLE | articles | ALL | NULL |
+----+-------------+----------+-------+---------------+
+---------+---------+-------+------+-------------+
| key | key_len | ref | rows | Extra |
+---------+---------+-------+------+-------------+
| PRIMARY | 4 | const | 1 | |
| NULL | NULL | NULL | 1 | Using where |
+---------+---------+-------+------+-------------+
Active Record realiza una impresin bonita que emula la del shell de base de datos
correspondiente. Por lo tanto, la misma consulta que se ejecuta con el adaptador de
PostgreSQL
EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "articles" ON "articles"."user_i
d" = "users"."id" WHERE "users"."id" = 1
QUERY PLAN
------------------------------------------------------------------------------
Nested Loop Left Join (cost=0.00..37.24 rows=8 width=0)
Join Filter: (articles.user_id = users.id)
-> Index Scan using users_pkey on users (cost=0.00..8.27 rows=1 width=4)
Index Cond: (id = 1)
-> Seq Scan on articles (cost=0.00..28.88 rows=8 width=4)
Filter: (articles.user_id = 1)
(6 rows)
222
22- Ejecutando EXPLAIN
User.where(id: 1).includes(:articles).explain
yields
223
VII- Conceptos bsicos de Active Model
224
1- Introduccin
1- Introduccin
Active Model es una biblioteca que contiene varios mdulos utilizados en el desarrollo de
clases que necesitan algunas caractersticas presentes en Active Record. A continuacin se
explican algunos de estos mdulos.
class Person
include ActiveModel::AttributeMethods
attribute_method_prefix 'reset_'
attribute_method_suffix '_highest?'
define_attribute_methods 'age'
attr_accessor :age
private
def reset_attribute(attribute)
send("#{attribute}=", 0)
end
def attribute_highest?(attribute)
send(attribute) > 100
end
end
person = Person.new
person.age = 110
person.age_highest? # => true
person.reset_age # => 0
person.age_highest? # => false
225
1- Introduccin
class Person
extend ActiveModel::Callbacks
define_model_callbacks :update
before_update :reset_me
def update
run_callbacks(:update) do
# This method is called when update is called on an object.
end
end
def reset_me
# This method is called when update is called on an object as a before_update call
back is defined.
end
end
1.3 Conversion
Si una clase define persisted? y el mtodo id , puede incluir el mdulo
ActiveModel::Conversion en esa clase y llamar a los mtodos de conversin de Rails en
class Person
include ActiveModel::Conversion
def persisted?
false
end
def id
nil
end
end
person = Person.new
person.to_model == person # => true
person.to_key # => nil
person.to_param # => nil
1.4 Dirty
Un objeto se ensucia cuando ha pasado por uno o ms cambios en sus atributos y no se ha
guardado. ActiveModel::Dirty permite comprobar si un objeto ha sido cambiado o no.
Tambin tiene mtodos de acceso basados en atributo. Consideremos una clase Person
226
1- Introduccin
class Person
include ActiveModel::Dirty
define_attribute_methods :first_name, :last_name
def first_name
@first_name
end
def first_name=(value)
first_name_will_change!
@first_name = value
end
def last_name
@last_name
end
def last_name=(value)
last_name_will_change!
@last_name = value
end
def save
# do save work...
changes_applied
end
end
227
1- Introduccin
person = Person.new
person.changed? # => false
# returns a Hash of the attributes that have changed with their original values.
person.changed_attributes # => {"first_name"=>nil}
# returns a Hash of changes, with the attribute names as the keys, and the
# values as an array of the old and new values for that field.
person.changes # => {"first_name"=>[nil, "First Name"]}
# attr_name_changed?
person.first_name # => "First Name"
person.first_name_changed? # => true
# attr_name_was accessor
person.first_name_was # => nil
Rastrea el valor anterior y el actual del atributo cambiado. Devuelve una matriz si se
cambia, de lo contrario devuelve nil.
# attr_name_change
person.first_name_change # => [nil, "First Name"]
person.last_name_change # => nil
1.5 Validaciones
El mdulo ActiveModel::Validations agrega la capacidad de validar objetos como en Active
Record.
228
1- Introduccin
class Person
include ActiveModel::Validations
person = Person.new
person.token = "2b1f325"
person.valid? # => false
person.name = 'vishnu'
person.email = 'me'
person.valid? # => false
person.email = '[email protected]'
person.valid? # => true
person.token = nil
person.valid? # => raises ActiveModel::StrictValidationFailed
1.6 Nombrar
ActiveModel::Naming aade una serie de mtodos de clase que facilitan la gestin de
class Person
extend ActiveModel::Naming
end
1.7 Modelo
ActiveModel::Model aade la capacidad de una clase para trabajar con Action Pack y
229
1- Introduccin
class EmailContact
include ActiveModel::Model
def deliver
if valid?
# deliver email
end
end
end
Cualquier clase que incluya ActiveModel::Model se puede utilizar con form_for , render y
cualquier otro mtodo de ayuda Action View, al igual que los objetos Active Record.
1.8 Serializacin
ActiveModel::Serialization proporciona serializacin bsica para su objeto. Debe declarar
un Hash de atributos que contiene los atributos que desea serializar. Los atributos deben
ser cadenas, no smbolos.
230
1- Introduccin
class Person
include ActiveModel::Serialization
attr_accessor :name
def attributes
{'name' => nil}
end
end
person = Person.new
person.serializable_hash # => {"name"=>nil}
person.name = "Bob"
person.serializable_hash # => {"name"=>"Bob"}
1.8.1 ActiveModel::Serializers
Active Model tambin proporciona el mdulo ActiveModel::Serializers::JSON para la
serializacin / deserializacin de JSON. Este mdulo incluye automticamente el mdulo de
ActiveModel::Serialization anteriormente discutido.
1.8.1.1 ActiveModel::Serializers::JSON
class Person
include ActiveModel::Serializers::JSON
attr_accessor :name
def attributes
{'name' => nil}
end
end
231
1- Introduccin
person = Person.new
person.as_json # => {"name"=>nil}
person.name = "Bob"
person.as_json # => {"name"=>"Bob"}
Tambin puede definir los atributos para un modelo de una cadena JSON. Sin embargo,
debe definir el mtodo attributes= en su clase:
class Person
include ActiveModel::Serializers::JSON
attr_accessor :name
def attributes=(hash)
hash.each do |key, value|
send("#{key}=", value)
end
end
def attributes
{'name' => nil}
end
end
Ahora es posible crear una instancia de Person y establecer atributos usando from_json .
1.9 Traduccin
ActiveModel::Translation proporciona integracin entre su objeto y el entorno de
class Person
extend ActiveModel::Translation
end
config/locales/app.pt-BR.yml
232
1- Introduccin
pt-BR:
activemodel:
attributes:
person:
name: 'Nome'
Model.
app/models/person.rb
class Person
include ActiveModel::Model
end
test/models/person_test.rb
require 'test_helper'
setup do
@model = Person.new
end
end
$ rails test
# Running:
......
233
1- Introduccin
No se requiere un objeto para implementar todas las API para trabajar con Action Pack.
Este mdulo slo tiene la intencin de proporcionar orientacin en caso de que desee todas
las caractersticas fuera de la caja.
1.11 SecurePassword
ActiveModel::SecurePassword proporciona una forma de almacenar de forma segura
1.11.1 Requisitos
ActiveModel::SecurePassword depende de bcrypt , as que incluya esta gema en su
1.11.2 Ejemplos
234
1- Introduccin
class Person
include ActiveModel::SecurePassword
has_secure_password
attr_accessor :password_digest
end
person = Person.new
235
VIII- Conceptos bsicos de Action View
236
1- Qu es Action View?
1 Qu es Action View?
En Rails, las solicitudes web son manejadas por Action Controller y Action View.
Normalmente, Action Controller se ocupa de comunicarse con la base de datos y realizar
acciones CRUD cuando sea necesario. Entonces, Action View es responsable de compilar
la respuesta.
Algunas caractersticas de Action View estn vinculadas a Active Record, pero eso no
significa que Action View depende de Active Record. Action View es un paquete
independiente que se puede utilizar con cualquier tipo de bibliotecas Ruby.
237
2- Uso de Action View con Rails
Existe una convencin de naming para las vistas en Rails. Normalmente, las vistas
comparten su nombre con la accin del controlador asociado, como se puede ver ms
arriba. Por ejemplo, la accin del controlador de index del articles_controller.rb
utilizar el archivo de vista index.html.erb en el directorio app / views / articles . El
HTML completo devuelto al cliente se compone de una combinacin de este archivo ERB ,
un template de diseo que lo envuelve y todos los partials al que la vista puede hacer
referencia. Dentro de esta gua encontrar una documentacin ms detallada sobre cada
uno de estos tres componentes.
238
3- Templates, Partials y Layouts
3.1 Templates
Las plantillas de Action View se pueden escribir de varias maneras. Si el archivo de plantilla
tiene una extensin .erb , utiliza una mezcla de ERB (Embedded Ruby) y HTML . Si el
archivo de plantilla tiene una extensin .builder , se utiliza la biblioteca
Builder::XmlMarkup .
Rails soporta mltiples sistemas de plantilla y utiliza una extensin de archivo para distinguir
entre ellos. Por ejemplo, un archivo HTML que utiliza el sistema de plantillas ERB tendr
.html.erb como una extensin de archivo.
3.1.1 ERB
Dentro de una plantilla de ERB , el cdigo Ruby se puede incluir usando las etiquetas <%
%> y <%= %> . Las etiquetas <% %> se utilizan para ejecutar cdigo Ruby que no devuelven
nada, como condiciones, bucles o bloques, y las etiquetas <%= %> se utilizan cuando se
desea que se devuelva un resultado.
239
3- Templates, Partials y Layouts
Para suprimir los espacios en blanco iniciales y remotos, puede utilizar <%- -%> de forma
intercambiable con <% y %> .
3.1.2 Builder
Las plantillas de Builder son una alternativa ms programtica a ERB . Son especialmente
tiles para generar contenido XML . Un objeto XmlMarkup denominado xml se pone
automticamente a disposicin de plantillas con una extensin . builder .
xml.em("emphasized")
xml.em { xml.b("emph & bold") }
xml.a("A Link", "href" => "http://rubyonrails.org")
xml.target("name" => "compile", "option" => "fast")
Que producira:
<em>emphasized</em>
<em><b>emph & bold</b></em>
<a href="http://rubyonrails.org">A link</a>
<target option="fast" name="compile" />
Cualquier mtodo con un bloque ser tratado como una etiqueta de marcado XML con
marcas anidadas en el bloque. Por ejemplo, lo siguiente:
xml.div {
xml.h1(@person.name)
xml.p(@person.bio)
}
<div>
<h1>David Heinemeier Hansson</h1>
<p>A product of Danish Design during the Winter of '79...</p>
</div>
240
3- Templates, Partials y Layouts
3.1.3 Jbuilder
Jbuilder es una gema que mantiene el equipo de Rails y que se incluye en el Railfile
Gemfile por defecto. Es similar a Builder, pero se utiliza para generar JSON , en lugar de
XML .
gem 'jbuilder'
json.name("Alex")
json.email("[email protected]")
Lo que produce
{
"name": "Alex",
"email": "[email protected]"
}
241
3- Templates, Partials y Layouts
3.2 Partials
Las plantillas parciales, usualmente llamadas "partials", son otro dispositivo para romper el
proceso de renderizado en bloques ms manejables. Con partials, puede extraer
fragmentos de cdigo de sus plantillas para separar archivos y tambin reutilizarlos a travs
de sus plantillas.
Esto convertir un archivo denominado _menu.html.erb en ese punto dentro de la vista que
se est procesando. Tenga en cuenta el carcter de subrayado principal: los partials se
nombran con un carcter de subrayado principal para distinguirlos de las vistas regulares,
aunque se consulten sin el subrayado. Esto es vlido incluso cuando est extrayendo una
parte de otra carpeta:
242
3- Templates, Partials y Layouts
<h1>Products</h1>
Dentro del partial _product obtendremos @product en la variable local product , como si
hubiramos escrito:
243
3- Templates, Partials y Layouts
haramos:
Con la opcin as podemos especificar un nombre diferente para dicha variable local. Por
ejemplo, si queremos que sea un elemento en lugar del producto haramos:
que es equivalente a:
Cuando un parcial es llamado con una coleccin, las instancias individuales del parcial
tienen acceso al miembro de la coleccin que se est procesando a travs de una variable
llamada despus del parcial. En este caso, el parcial es _product , y dentro de l puede
244
3- Templates, Partials y Layouts
hacer referencia al producto para obtener el miembro de coleccin que se est procesando.
Puede utilizar una sintaxis abreviada para procesar las colecciones. Suponiendo que
@products es una coleccin de instancias de product , simplemente puede escribir lo
Rails determina el nombre del parcial a utilizar, mirando el nombre del modelo en la
coleccin, Product en este caso. De hecho, puede incluso hacer una coleccin compuesta
de instancias de diferentes modelos utilizando este shorthand, y Rails elegir el parcial
adecuado para cada miembro de la coleccin.
Rails har que el partial _product_ruler (sin datos pasados a ella) entre a cada par de
parciales _product .
3.3 Layouts
Los layouts pueden usarse para renderizar una plantilla de vista comn alrededor de los
resultados de las acciones del controlador de Rails. Normalmente, una aplicacin de Rails
tendr un par de layouts que las pginas renderizarn internamente. Por ejemplo, un sitio
puede tener un layout para un usuario conectado y otro para el lado de marketing o ventas
del sitio. El layout de usuario registrado puede incluir navegacin de nivel superior que debe
estar presente en muchas acciones del controlador. El layout de ventas de una aplicacin
SaaS puede incluir navegacin de nivel superior para cosas como "Precios" y "Contactar
con nosotros". Es de esperar que cada layout tenga una apariencia diferente.
245
4- Partial Layouts
4 Partial Layouts
Los parciales pueden tener sus propios layouts aplicados a ellos. Estos layouts son
diferentes de los aplicados a una accin del controlador, pero funcionan de una manera
similar.
Digamos que estamos mostrando un artculo en una pgina que debe ser envuelto en un
div para fines de visualizacin. En primer lugar, crearemos un nuevo artculo:
<%= render partial: 'article', layout: 'box', locals: { article: @article } %>
<div class='box'>
<%= yield %>
</div>
Tenga en cuenta que el layout de partial tiene acceso a la variable local del artculo que se
pas a la llamada render . Sin embargo, a diferencia de los layouts de la aplicacin
general, los layouts parciales todava tienen el prefijo de subrayado.
Tambin puede procesar un bloque de cdigo dentro de un layout parcial en lugar de llamar
a yield . Por ejemplo, si no tuviramos el parcial _article , podramos hacer esto en su
lugar:
Suponiendo que usamos el mismo parcial _box de arriba, esto producira la misma salida
que el ejemplo anterior.
246
4- Partial Layouts
247
5- Rutas de las Vistas
Podemos agregar otras ubicaciones y darles una cierta prioridad cuando resolvamos rutas
usando los mtodos prepend_view_path y append_view_path .
prepend_view_path "app/views/#{request.subdomain}"
A continuacin, Action View buscar primero en este directorio cuando se resuelvan las
vistas.
append_view_path "app/views/direct"
248
6- Visin general de los helpers proporcionados por Action View
Lo siguiente es slo un breve resumen general de los helpers disponibles en Action View.
Se recomienda revisar la documentacin de la API, que cubre todos los ayudantes con ms
detalle, pero esto debera servir como un buen punto de partida.
249
6.1 AssetTagHelper
6.1 AssetTagHelper
Este mdulo proporciona mtodos para generar HTML que vincula vistas a elementos tales
como imgenes, archivos JavaScript, hojas de estilo y feeds.
De forma predeterminada, Rails enlaza con estos assets en el host actual de la carpeta
pblica, pero puede dirigir a Rails para enlazar con assets desde un servidor de assets
dedicados configurando config.action_controller.asset_host en la configuracin de la
aplicacin, normalmente en config/environments/production.rb . Por ejemplo, digamos que
el host de assets es assets.example.com :
config.action_controller.asset_host = "assets.example.com"
image_tag("rails.png") # => <img src="http://assets.example.com/images/rails.png" alt=
"Rails" />
6.1.1 auto_discovery_link_tag
Devuelve una etiqueta de link que los navegadores y los lectores de feeds pueden usar
para detectar automticamente un feed RSS o Atom .
6.1.2 image_path
Calcula la ruta de acceso a un recurso de imagen en el directorio app/assets/images . Se
pasarn a travs de rutas completas desde la raz del documento. Utilizado internamente
por image_tag para construir la ruta de la imagen.
6.1.3 image_url
250
6.1 AssetTagHelper
6.1.4 image_tag
Devuelve una etiqueta de imagen HTML desde el origen. El origen puede ser una ruta de
acceso completa o un archivo que existe en el directorio app/assets/images .
6.1.5 javascript_include_tag
Devuelve una etiqueta de secuencia de comandos HTML para cada uno de los orgenes
proporcionados. Puede pasar el nombre de archivo (la extensin .js es opcional) de los
archivos JavaScript que existen en el directorio app/assets/javascripts para su inclusin
en la pgina actual o puede pasar la ruta completa relativa a la raz del documento.
javascript_include_tag :defaults
javascript_include_tag :all
Tambin puede almacenar en cach varios archivos JavaScript en un solo archivo, lo que
requiere menos conexiones HTTP para descargar y puede ser mejor comprimirlo por gzip
(lo que lleva a transferencias ms rpidas). El almacenamiento en cach slo ocurrir si
ActionController::Base.perform_caching est establecido en true (que es el caso por
251
6.1 AssetTagHelper
6.1.6 javascript_path
Computa la ruta de acceso a un recurso de JavaScript en el directorio
app/assets/javascripts . Si el nombre de archivo de origen no tiene extensin, se agregar
.js . Se pasar a travs de rutas completas desde la raz del documento. Use
6.1.7 javascript_url
Computa la URL de un recurso de JavaScript en el directorio app/assets/javascripts . Esto
llamar javascript_path internamente y se fusionar con su host actual o con su host de
assets.
6.1.8 stylesheet_link_tag
Devuelve una etiqueta de enlace de hoja de estilo para los orgenes especificados como
argumentos. Si no especifica una extensin, .css se aadir automticamente.
Tambin puede incluir todos los estilos en el directorio de hoja de estilo utilizando :all
como fuente:
stylesheet_link_tag :all
Tambin puede cachear varias hojas de estilo en un archivo, lo que requiere menos
conexiones HTTP y puede ser mejor si es compreso por gzip (lo que lleva a transferencias
ms rpidas). El almacenamiento en cach slo ocurrir si
ActionController::Base.perform_caching est establecido en true (que es el caso por
252
6.1 AssetTagHelper
6.1.9 stylesheet_path
Computa la ruta de acceso a un elemento de hoja de estilo en el directorio
app/assets/stylesheets . Si el nombre de archivo de origen no tiene extensin, se agregar
.css . Se pasarn a travs de rutas completas desde la raz del documento. Se utiliza
6.1.10 stylesheet_url
Computa la URL de un elemento de hoja de estilo en el directorio app/assets/stylesheets .
Esto llamar a stylesheet_path internamente y se fusionar con su host actual o con su
host activo.
253
6.2 AtomFeedHelper
6.2 AtomFeedHelper
6.2.1 atom_feed
Este helper facilita la creacin de un feed Atom . He aqu un ejemplo de uso completo:
config/routes.rb
resources :articles
app/controllers/articles_controller.rb
def index
@articles = Article.all
respond_to do |format|
format.html
format.atom
end
end
app/views/articles/index.atom.builder
atom_feed do |feed|
feed.title("Articles Index")
feed.updated(@articles.first.created_at)
@articles.each do |article|
feed.entry(article) do |entry|
entry.title(article.title)
entry.content(article.body, type: 'html')
entry.author do |author|
author.name(article.author_name)
end
end
end
end
254
6.3 BenchmarkHelper
6.3 BenchmarkHelper
6.3.1 benchmark
Permite medir el tiempo de ejecucin de un bloque en una plantilla y graba el resultado en
el registro. Envuelva este bloque alrededor de operaciones costosas o posibles cuellos de
botella para obtener una lectura de tiempo para la operacin.
Esto aadira algo como "Process data files (0.34523)" al registro, que puede utilizar para
comparar los tiempos al optimizar su cdigo.
255
6.4 CacheHelper
6.4 CacheHelper
6.4.1 cache
Un mtodo para almacenar en cach fragmentos de una vista en lugar de toda una accin o
pgina. Esta tcnica es til para almacenar en cach piezas como mens, listas de temas
de noticias, fragmentos HTML estticos, etc. Este mtodo toma un bloque que contiene el
contenido que desea almacenar en cach. Vea AbstractController::Caching::Fragments
para obtener ms informacin.
256
6.5 CaptureHelper
6.5 CaptureHelper
6.5.1 capture
El mtodo de captura le permite extraer parte de una plantilla en una variable. A
continuacin, puede utilizar esta variable en cualquier parte de las plantillas o del layout.
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<%= @greeting %>
</body>
</html>
6.5.2 content_for
Llamar content_for almacena un bloque de marcado en un identificador para uso
posterior. Puede realizar llamadas posteriores al contenido almacenado en otras plantillas o
el layout, pasando el identificador como argumento yield .
Por ejemplo, digamos que tenemos un diseo de aplicacin estndar, pero tambin una
pgina especial que requiere cierto cdigo JavaScript que el resto del sitio no necesita.
Podemos usar content_for para incluir este JavaScript en nuestra pgina especial sin
engordar el resto del sitio.
app/views/layouts/application.html.erb
257
6.5 CaptureHelper
<html>
<head>
<title>Welcome!</title>
<%= yield :special_script %>
</head>
<body>
<p>Welcome! The date and time is <%= Time.now %></p>
</body>
</html>
app/views/articles/special.html.erb
258
6.6 DateHelper
6.6 DateHelper
6.6.1 date_select
Devuelve un conjunto de etiquetas de seleccin (una por ao, mes y da) preseleccionadas
para acceder a un atributo basado-en-fecha especificado.
date_select("article", "published_on")
6.6.2 datetime_select
Devuelve un conjunto de etiquetas de seleccin (una por ao, mes, da, hora y minuto)
preseleccionadas para acceder a un atributo de fecha y hora especificado.
datetime_select("article", "published_on")
6.6.3 distance_of_time_in_words
Informa la distancia aproximada en el tiempo entre dos objetos Time o Date o nmeros
enteros como segundos. Establezca include_seconds a true si desea obtener
aproximaciones ms detalladas.
6.6.4 select_date
Devuelve un conjunto de etiquetas de seleccin HTML (uno para ao, mes y da)
preseleccionado con la fecha proporcionada.
# Genera una fecha seleccionada que se ajusta por defecto a la fecha proporcionada (se
is das despus de hoy)
select_date(Time.today + 6.days)
# Genera una fecha seleccionada por defecto a la fecha actual (sin fecha especificada)
select_date()
259
6.6 DateHelper
6.6.5 select_datetime
Devuelve un conjunto de etiquetas de seleccin de HTML (una para el ao, el mes, el da, la
hora y el minuto) preseleccionadas con la fecha y hora previstas.
# Genera una fecha y hora que selecciona por defecto la fecha y hora que se proporcion
a (cuatro das despus de hoy)
select_datetime(Time.now + 4.days)
# Genera una fecha y hora que selecciona por defecto a la fecha de hoy (no hay fecha e
specificada)
select_datetime()
6.6.6 select_day
Devuelve una etiqueta de seleccin con opciones para cada uno de los das del 1 al 31 con
el da actual seleccionado.
# Genera un campo de seleccin para los das que predeterminan el nmero dado
select_day(5)
6.6.7 select_hour
Devuelve una etiqueta de seleccin con opciones para cada una de las horas de 0 a 23 con
la hora actual seleccionada.
# Genera un campo de seleccin para las horas que predeterminan las horas para el tiem
po proporcionado
select_hour(Time.now + 6.hours)
6.6.8 select_minute
Devuelve una etiqueta de seleccin con opciones para cada uno de los minutos 0 a 59 con
el minuto actual seleccionado.
# Genera un campo de seleccin para los minutos que predeterminan los minutos para el
tiempo proporcionado.
select_minute(Time.now + 10.minutes)
260
6.6 DateHelper
6.6.9 select_month
Devuelve una etiqueta de seleccin con opciones para cada uno de los meses de enero a
diciembre con el mes actual seleccionado.
6.6.10 select_second
Devuelve una etiqueta de seleccin con opciones para cada uno de los segundos 0 a 59
con el segundo actual seleccionado.
# Genera un campo de seleccin para segundos que esta predeterminado a los segundos pa
ra el tiempo proporcionado
select_second(Time.now + 16.seconds)
6.6.11 select_time
Devuelve un conjunto de etiquetas de seleccin HTML (una por hora y minuto).
# Genera una seleccin de tiempo que se ajusta por defecto a la hora proporcionada
select_time(Time.now)
6.6.12 select_year
Devuelve una etiqueta de seleccin con opciones para cada uno de los cinco aos de cada
lado del actual que est seleccionado. El rango de cinco aos se puede cambiar usando las
teclas :start_year y :end_year en las opciones.
# Genera un campo de seleccin durante cinco aos a cada lado de Date.today predetermi
nado al ao actual
select_year(Date.today)
6.6.13 time_ago_in_words
Como distance_of_time_in_words , pero donde to_time est fijado a Time.now .
261
6.6 DateHelper
6.6.14 time_select
Devuelve un conjunto de etiquetas de seleccin (uno para hora, minuto y opcionalmente
segundos) preseleccionado para acceder a un atributo de tiempo especfico. Los select
se preparan para la asignacin de mltiples parmetros a un objeto de Active Record.
# Creates a time select tag that, when POSTed, will be stored in the order variable in
the submitted attribute
time_select("order", "submitted")
262
6.7 DebugHelper
6.7 DebugHelper
Devuelve una etiqueta pre que tiene un objeto dumping de YAML . Esto crea una forma
muy legible para inspeccionar un objeto.
<pre class='debug_dump'>---
first: 1
second: two
third:
- 1
- 2
- 3
</pre>
263
6.8 FormHelper
6.8 FormHelper
Los ayudantes de formularios estn diseados para facilitar el trabajo con modelos en
comparacin con el uso de elementos HTML estndar proporcionando un conjunto de
mtodos para crear formularios basados en sus modelos. Este ayudante genera HTML para
los formularios, proporcionando un mtodo para cada tipo de entrada (por ejemplo, text,
password, select, etc.). Cuando se enva el formulario (es decir, cuando el usuario pulsa el
botn de envo o form.submit se enva a travs de JavaScript), las entradas del formulario
se incluirn en el objeto params y se devolvern al controlador.
Hay dos tipos de ayudantes de formulario: los que trabajan especficamente con los
atributos del modelo y los que no. FormHeper se ocupa de los que trabajan con atributos del
modelo; Para ver un ejemplo de ayudantes de formulario que no funcionan con atributos de
modelo, consulte la documentacin ActionView::Helpers::FormTagHelper .
# Nota: se habr creado una variable @person en el controlador (por ejemplo, @person =
Person.new)
<%= form_for @person, url: { action: "create" } do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= submit_tag 'Create' %>
<% end %>
{ "action" => "create", "controller" => "people", "person" => { "first_name" => "Willi
am", "last_name" => "Smith" } }
264
6.8 FormHelper
El hash de parmetros tiene un valor de anidado de persona, por lo que se puede acceder
con params[:person] en el controlador.
6.8.1 check_box
Devuelve una etiqueta de casilla de verificacin adaptada para acceder a un atributo
especificado.
6.8.2 fields_for
Crea un scope alrededor de un objeto de modelo especfico como form_for , pero no crea
las etiquetas de formulario por s mismo. Esto hace que fields_for sea adecuado para
especificar objetos de modelo adicionales en el mismo form:
6.8.3 file_field
Devuelve una etiqueta de entrada de carga de archivo adaptada para acceder a un atributo
especificado.
file_field(:user, :avatar)
# => <input type="file" id="user_avatar" name="user[avatar]" />
6.8.4 form_for
Crea un formulario y un scope alrededor de un objeto de modelo especfico que se utiliza
como base para preguntar los valores de los campos.
265
6.8 FormHelper
6.8.5 hidden_field
Devuelve una etiqueta de entrada oculta adaptada para acceder a un atributo especificado.
hidden_field(:user, :token)
# => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />
6.8.6 label
Devuelve una etiqueta label adaptada para etiquetar un campo de entrada para un
atributo especificado.
label(:article, :title)
# => <label for="article_title">Title</label>
6.8.7 password_field
Devuelve una etiqueta de entrada del tipo "contrasea" adaptada para acceder a un atributo
especificado.
password_field(:login, :pass)
# => <input type="text" id="login_pass" name="login[pass]" value="#{@login.pass}" />
6.8.8 radio_button
Devuelve una etiqueta de radio button para acceder a un atributo especificado.
266
6.8 FormHelper
6.8.9 text_area
Devuelve un conjunto de etiquetas de apertura y cierre de textarea adaptadas para
acceder a un atributo especificado.
6.8.10 text_field
Devuelve una etiqueta de entrada del tipo "texto" adaptada para acceder a un atributo
especificado.
text_field(:article, :title)
# => <input type="text" id="article_title" name="article[title]" value="#{@article.tit
le}" />
6.8.11 email_field
Devuelve una etiqueta de entrada del tipo "correo electrnico" adaptada para acceder a un
atributo especificado.
email_field(:user, :email)
# => <input type="email" id="user_email" name="user[email]" value="#{@user.email}" />
6.8.12 url_field
Devuelve una etiqueta de entrada del tipo "url" adaptada para acceder a un atributo
especificado.
url_field(:user, :url)
# => <input type="url" id="user_url" name="user[url]" value="#{@user.url}" />
267
6.9 FormOptionsHelper
6.9 FormOptionsHelper
Proporciona una serie de mtodos para convertir diferentes tipos de contenedores en un
conjunto de etiquetas de opcin.
6.9.1 collection_select
Devuelve las etiquetas select y option para la coleccin de valores de retorno existentes
del mtodo para la clase del objeto.
<select name="article[author_id]">
<option value="">Please select</option>
<option value="1" selected="selected">D. Heinemeier Hansson</option>
<option value="2">D. Thomas</option>
<option value="3">M. Clark</option>
</select>
6.9.2 collection_radio_buttons
268
6.9 FormOptionsHelper
Devuelve las etiquetas radio_button para la coleccin de valores de retorno existentes del
mtodo para la clase del objeto.
6.9.3 collection_check_boxes
Devuelve etiquetas check_box para la coleccin de valores de retorno existentes del
mtodo para la clase del objeto.
269
6.9 FormOptionsHelper
6.9.4 option_groups_from_collection_for_select
Devuelve una cadena de etiquetas option , como options_from_collection_for_select ,
pero las agrupa mediante etiquetas optgroup basadas en las relaciones de objeto de los
argumentos.
270
6.9 FormOptionsHelper
Ejemplo de uso:
Posible salida:
<optgroup label="Africa">
<option value="1">Egypt</option>
<option value="4">Rwanda</option>
...
</optgroup>
<optgroup label="Asia">
<option value="3" selected="selected">China</option>
<option value="12">India</option>
<option value="5">Japan</option>
...
</optgroup>
Nota: Slo se devuelven las etiquetas optgroup y option , por lo que todava tiene que
ajustar la salida en una etiqueta de seleccin adecuada.
6.9.5 options_for_select
Acepta un contenedor (hash, array, enumerable, your type) y devuelve una cadena de
etiquetas option .
Nota: Slo se devuelven las etiquetas option , tiene que ajustar esta llamada en una
etiqueta de seleccin HTML normal.
6.9.6 options_from_collection_for_select
271
6.9 FormOptionsHelper
Devuelve una cadena de etiquetas option que se han compilado iterando sobre la
coleccin y asignando el resultado de una llamada al mtodo value como el valor de la
opcin y el text como el texto de la opcin.
Por ejemplo, imagine un bucle que itera sobre cada persona en @project.people para
generar un input tag:
Nota: Slo se devuelven las etiquetas option, tiene que ajustar esta llamada en una etiqueta
de seleccin HTML normal.
6.9.7 select
Crea una etiqueta select y una serie de etiquetas option contenidas para el objeto y
mtodo proporcionados.
Ejemplo:
<select name="article[person_id]">
<option value=""></option>
<option value="1" selected="selected">David</option>
<option value="2">Eileen</option>
<option value="3">Rafael</option>
</select>
6.9.8 time_zone_options_for_select
Devuelve una cadena de etiquetas option para prcticamente cualquier zona horaria del
mundo.
6.9.9 time_zone_select
272
6.9 FormOptionsHelper
Devuelve las etiquetas select y option para el objeto y el mtodo dados, usando
time_zone_options_for_select para generar la lista de etiquetas de opciones.
6.9.10 date_field
Devuelve una etiqueta de entrada del tipo "fecha" adaptada para acceder a un atributo
especificado.
date_field("user", "dob")
273
6.10 FormTagHelper
6.10 FormTagHelper
Proporciona una serie de mtodos para crear etiquetas de formulario que no dependen de
un objeto Active Record asignado a la plantilla como lo hace FormHelper. En su lugar,
proporciona los nombres y los valores manualmente.
6.10.1 check_box_tag
Crea una etiqueta de entrada de formulario de casilla de verificacin.
check_box_tag 'accept'
# => <input id="accept" name="accept" type="checkbox" value="1" />
6.10.2 field_set_tag
Crea un conjunto de campos para agrupar elementos de formulario HTML.
6.10.3 file_field_tag
Crea un campo de carga de archivos.
Ejemplo de salida:
file_field_tag 'attachment'
# => <input id="attachment" name="attachment" type="file" />
6.10.4 form_tag
274
6.10 FormTagHelper
Inicia una etiqueta de formulario que seala el action a una URL configurada con
url_for_options como ActionController::Base#url_for .
6.10.5 hidden_field_tag
Crea un campo de entrada de formulario oculto que se utiliza para transmitir datos que se
perderan debido a la apatridia de HTTP o datos que deberan estar ocultos al usuario.
6.10.6 image_submit_tag
Muestra una imagen que, cuando se hace clic, enviar el formulario.
image_submit_tag("login.png")
# => <input src="/images/login.png" type="image" />
6.10.7 label_tag
Crea un campo de etiqueta.
label_tag 'name'
# => <label for="name">Name</label>
6.10.8 password_field_tag
Crea un campo de contrasea, un campo de texto enmascarado que oculta la entrada de
los usuarios detrs de un carcter de mscara.
password_field_tag 'pass'
# => <input id="pass" name="pass" type="password" />
6.10.9 radio_button_tag
275
6.10 FormTagHelper
Crea un radio button; Utilice grupos de radio buttons con el mismo nombre para permitir a
los usuarios seleccionar de un grupo de opciones.
6.10.10 select_tag
Crea un cuadro de seleccin desplegable.
6.10.11 submit_tag
Crea un botn de envo con el texto proporcionado como el ttulo.
6.10.12 text_area_tag
Crea un rea de entrada de texto; Utilice una zona de texto para entradas de texto ms
largas, como publicaciones o descripciones de blogs.
text_area_tag 'article'
# => <textarea id="article" name="article"></textarea>
6.10.13 text_field_tag
Crea un campo de texto estndar; Utilice estos campos de texto para introducir fragmentos
ms pequeos de texto como un nombre de usuario o una consulta de bsqueda.
text_field_tag 'name'
# => <input id="name" name="name" type="text" />
6.10.14 email_field_tag
Crea un campo de entrada estndar del tipo email.
276
6.10 FormTagHelper
email_field_tag 'email'
# => <input id="email" name="email" type="email" />
6.10.15 url_field_tag
Crea un campo de entrada estndar de tipo url.
url_field_tag 'url'
# => <input id="url" name="url" type="url" />
6.10.16 date_field_tag
Crea un campo de entrada estndar de tipo fecha.
date_field_tag "dob"
# => <input id="dob" name="dob" type="date" />
277
6.11 JavaScriptHelper
6.11 JavaScriptHelper
Proporciona funcionalidad para trabajar con JavaScript en sus vistas.
6.11.1 escape_javascript
Retornos de portador de escape y comillas simples y dobles para segmentos de JavaScript.
6.11.2 javascript_tag
Devuelve una etiqueta JavaScript que envuelve el cdigo proporcionado.
<script>
//<![CDATA[
alert('All is good')
//]]>
</script>
278
6.12 NumberHelper
6.12 NumberHelper
Proporciona mtodos para convertir nmeros en cadenas formateadas. Los mtodos se
proporcionan para nmeros de telfono, moneda, porcentaje, precisin, notacin posicional
y tamao del archivo.
6.12.1 number_to_currency
Formatea un nmero en una cadena de moneda (por ejemplo, $ 13.65).
6.12.2 number_to_human_size
Formatea los bytes de tamao en una representacin ms comprensible; til para reportar
el tamao de los archivos a los usuarios.
6.12.3 number_to_percentage
Formatea un nmero como una cadena de porcentaje.
6.12.4 number_to_phone
Formatea un nmero en un nmero de telfono (EE.UU. por defecto).
6.12.5 number_with_delimiter
Formatea un nmero con miles agrupados usando un delimitador.
279
6.12 NumberHelper
6.12.6 number_with_precision
Formatea un nmero con el nivel de precisin especificado, que por defecto es 3.
280
6.13 SanitizeHelper
6.13 SanitizeHelper
El mdulo SanitizeHelper proporciona un conjunto de mtodos para borrar el texto de
elementos HTML no deseados.
6.13.1 sanitize
Este helper sanitize codificar en HTML todas las etiquetas y quitar todos los atributos que
no se permiten especficamente.
sanitize @article.body
Si se pasan las opciones :attributes o :tags , slo se permiten los atributos y etiquetas
mencionados y nada ms.
Para cambiar los valores predeterminados para usos mltiples, por ejemplo, agregar
etiquetas de tabla al valor predeterminado:
6.13.2 sanitize_css(style)
Desinfecta un bloque de cdigo CSS.
6.13.3 strip_links(html)
Borra todas las etiquetas de enlace del texto y deja slo el texto del enlace.
281
6.13 SanitizeHelper
6.13.4 strip_tags(html)
Elimina todas las etiquetas HTML del html, incluidos los comentarios. Esta funcionalidad es
alimentada por la gema rails-html-sanitizer .
Nota: La salida todava puede contener caracteres ' < ', ' > ', ' & ' sin escape y confundir los
navegadores.
282
6.14 CsrfHelper
6.14 CsrfHelper
Devuelve las etiquetas meta " csrf-param " y " csrf-token " con el nombre del parmetro de
proteccin de falsificacin de solicitud de cross-site y smbolo, respectivamente.
Los formularios regulares generan campos ocultos para que no utilicen estas etiquetas.
Se pueden encontrar ms detalles en la Gua de seguridad de Rails.
283
7- Vistas con Locale
Por ejemplo, supongamos que tiene un ArticlesController con una accin show . De
forma predeterminada, al llamar a esta accin, renderizamos
app/views/articles/show.html.erb . Pero si usted fija I18n.locale =: de , a continuacin,
est presente, se usar la versin no decorada. Esto significa que no est obligado a
proporcionar vistas localizadas para todos los casos, pero se prefieren y utilizan si estn
disponibles.
Puede utilizar la misma tcnica para localizar los archivos de rescate en su directorio
pblico. Por ejemplo, establecer I18n.locale =: de y crear public/500.de.html y
public/404.de.html le permitira tener pginas de rescate localizadas.
Dado que Rails no restringe los smbolos que utiliza para configurar I18n.locale, puede
aprovechar este sistema para mostrar contenido diferente dependiendo de lo que quiera.
Por ejemplo, suponga que tiene algunos usuarios "expertos" que deberan ver diferentes
pginas en comparacin a los usuarios "normales". Podra agregar lo siguiente a
app/controllers/application.rb :
before_action :set_expert_locale
def set_expert_locale
I18n.locale = :expert if current_user.expert?
end
284
IX- Layouts y Rendering en Rails
285
1- Descripcin General: Cmo encajan las piezas
En trazos generales, esto implica decidir qu se debe enviar como respuesta y llamar a un
mtodo apropiado para crear esa respuesta. Si la respuesta es una vista completa, Rails
tambin hace un trabajo extra para envolver la vista en un layout y posiblemente tambien
deba obtener vistas parciales, y hace ese trabajo. Vers todas esas rutas ms adelante en
esta gua.
286
2- Creacin de respuestas
2- Creacin de respuestas
Desde el punto de vista del controlador, hay tres maneras de crear una respuesta HTTP :
Llamar a render para crear una respuesta completa para enviar de nuevo al
navegador
Llamar a redirect_to para enviar un cdigo de estado de redireccionamiento HTTP al
navegador
Llamar a head para crear una respuesta que consiste nicamente en encabezados
HTTP para enviar de nuevo al navegador
287
2.1 Rendering por defecto: Convencin sobre configuracin en Action
resources :books
Sin embargo, este pantallazo es poco til, por lo que pronto deber crear su modelo de
book y agregar la accin de index de BooksController :
Tenga en cuenta que no tenemos que llamar a render de forma explicita al final de la
accin index de acuerdo con el principio de "convencin sobre configuracin". La regla es
que si no se hace explcitamente algo al final de una accin del controlador, Rails buscar
automticamente la plantilla action_name.html.erb en la ruta de vista del controlador y la
procesar. En este caso, Rails procesar el archivo app/views/books/index.html.erb .
Si queremos mostrar las propiedades de todos los libros en nuestra vista, podemos hacerlo
con una plantilla ERB como esta:
288
2.1 Rendering por defecto: Convencin sobre configuracin en Action
<h1>Listing Books</h1>
<table>
<tr>
<th>Title</th>
<th>Summary</th>
<th></th>
<th></th>
<th></th>
</tr>
<br>
289
2.2 Uso del render
Si desea ver los resultados exactos de una llamada a render sin necesidad de
inspeccionarla en un navegador, puede llamar a render_to_string . Este mtodo toma
exactamente las mismas opciones que render , pero devuelve una cadena en lugar de
enviar una respuesta al navegador.
def update
@book = Book.find(params[:id])
if @book.update(book_params)
redirect_to(@book)
else
render "edit"
end
end
Si lo prefiere, puede utilizar un smbolo en lugar de una cadena para especificar la accin a
renderizar:
def update
@book = Book.find(params[:id])
if @book.update(book_params)
redirect_to(@book)
else
render :edit
end
end
290
2.2 Uso del render
render "products/show"
Rails sabe que esta vista pertenece a un controlador diferente debido all carcter de barra
diagonal incrustado en la cadena. Si desea ser explcito, puede utilizar la opcin :template
(que se requera en Rails 2.2 y anteriores):
La opcin :file toma una ruta absoluta del sistema de archivos. Por supuesto, necesita tener
derechos sobre la vista que est utilizando para procesar el contenido.
El uso de la opcin :file en combinacin con la entrada de los usuarios puede dar lugar
a problemas de seguridad ya que un atacante podra utilizar esta accin para acceder
a archivos sensibles a la seguridad en su sistema de archivos.
Si est ejecutando Rails en Microsoft Windows, debera utilizar la opcin :file para
procesar un archivo, ya que los nombres de archivo de Windows no tienen el mismo
formato que los nombres de archivo Unix.
2.2.4 Envolvindolo
291
2.2 Uso del render
Las tres formas de representacin anteriores (renderizar otra plantilla dentro del controlador,
renderizar una plantilla dentro de otro controlador y renderizar un archivo arbitrario en el
sistema de archivos) son en realidad variantes de la misma accin.
render :edit
render action: :edit
render "edit"
render "edit.html.erb"
render action: "edit"
render action: "edit.html.erb"
render "books/edit"
render "books/edit.html.erb"
render template: "books/edit"
render template: "books/edit.html.erb"
render "/path/to/rails/app/views/books/edit"
render "/path/to/rails/app/views/books/edit.html.erb"
render file: "/path/to/rails/app/views/books/edit"
render file: "/path/to/rails/app/views/books/edit.html.erb"
Cul utiliza usted es realmente una cuestin de estilo y de convencin, pero la regla de oro
es utilizar el ms simple y que tiene sentido para el cdigo que usted est escribiendo.
render inline: "<% products.each do |p| %><p><%= p.name %></p><% end %>"
Rara vez hay una buena razn para usar esta opcin. La mezcla de ERB en sus
controladores derrota la orientacin MVC de Rails y dificultar que otros desarrolladores
sigan la lgica de su proyecto. Utilice una vista erb separada y en su lugar respectivo.
De forma predeterminada, el rendering inline utiliza ERB . Puede forzarlo a que utilice
Builder en su lugar con la opcin :type .
292
2.2 Uso del render
Puede enviar texto plano (sin markups) - de nuevo al navegador usando la opcin :plain
para renderizar:
Renderizar texto plano es muy til cuando respondes a un Ajax o a web services
request que esperan algo distinto del HTML apropiado.
Esto es til cuando ests procesando un pequeo fragmento de cdigo HTML . Sin
embargo, es posible que desee considerar moverlo a un archivo template si el marcado
es complejo.
tiene soporte incorporado para convertir objetos a JSON y hacer que JSON regrese al
navegador:
293
2.2 Uso del render
Dispatch.
:content_type
:layout
:location
:status
:formats
294
2.2 Uso del render
Puede utilizar la opcin :layout para indicar a Rails que utilice un archivo especfico como
el layout de la accin actual:
Tambin puede indicarle a Rails que lo procese sin ningn layout en absoluto:
Rails entiende los cdigos numricos de estado y los smbolos correspondientes que se
muestran a continuacin.
295
2.2 Uso del render
101 :switching_protocols
102 :processing
Success 200 :ok
201 :created
202 :accepted
203 :non_authoritative_information
204 :no_content
205 :reset_content
206 :partial_content
207 :multi_status
208 :already_reported
226 :im_used
Redirection 300 :multiple_choices
301 :moved_permanently
302 :found
303 :see_other
304 :not_modified
305 :use_proxy
307 :temporary_redirect
308 :premanent_redirect
Client Error 400 :bad_request
401 :unauthorized
402 :payment_required
403 :forbidden
404 :not_found
405 :method_not_allowed
406 :not_acceptable
407 :proxy_authentication_required
408 :request_timeout
409 :conflict
296
2.2 Uso del render
410 :gone
411 :length_required
412 :precondition_failed
413 :payload_too_large
414 :uri_too_long
415 :unsupported_media_type
416 :range_not_satisfiable
417 :expectation_failed
422 :unprocessable_entity
423 :locked
424 :failed_dependency
426 :upgrade_required
428 :precondition_required
429 :too_many_requests
431 :request_header_fields_too_large
505 :http_version_not_supported
506 :variant_also_negotiates
507 :insufficient_storage
508 :loop_detected
510 :not_extended
511 :network_authentication_required
Si intenta procesar el contenido junto con un cdigo de estado sin contenido (100-199,
204, 205 o 304), se eliminar de la respuesta.
297
2.2 Uso del render
diseo .builder si existe. Rails tambin proporciona varias maneras de asignar con mayor
precisin layouts especficos a controladores y acciones individuales.
Con esta declaracin, todas las vistas generadas por el ProductsController utilizarn
app/views/layouts/inventory.html.erb como su layout.
Para asignar un layout especfico para toda la aplicacin, utilice una declaracin de layout
en su clase ApplicationController :
298
2.2 Uso del render
def show
@product = Product.find(params[:id])
end
private
def products_layout
@current_user.special? ? "special" : "products"
end
end
Ahora, si el usuario actual es un usuario especial, ver un layout especial cuando acceda a
un producto.
Incluso puede utilizar un mtodo inline, como un Proc , para determinar el layout. Por
ejemplo, si pasa un objeto Proc , al bloque que le da el Proc se le dar la instancia del
controlador, por lo que el layout se puede determinar sobre la base de la solicitud actual:
299
2.2 Uso del render
Con esta declaracin, el layout del producto se utilizara para todo, excepto los mtodos
rss e index .
application_controller.rb
articles_controller.rb
special_articles_controller.rb
old_articles_controller.rb
def show
@article = Article.find(params[:id])
end
def index
@old_articles = Article.older
render layout: "old"
end
# ...
end
En esta aplicacin:
300
2.2 Uso del render
# in app/controllers/application_controller
class ApplicationController < ActionController::Base
end
# in app/controllers/admin_controller
class AdminController < ApplicationController
end
# in app/controllers/admin/products_controller
class Admin::ProductsController < AdminController
def index
end
end
app/views/admin/products/
app/views/admin/
app/views/application/
Esto hace que app/views/application/ sea un gran lugar para tus patials compartidos, que
luego se pueden renderizar en tu ERB como tal:
301
2.2 Uso del render
en que funciona.
def show
@book = Book.find(params[:id])
if @book.special?
render action: "special_show"
end
render action: "regular_show"
end
def show
@book = Book.find(params[:id])
if @book.special?
render action: "special_show" and return
end
render action: "regular_show"
end
Asegrese de usar and return en lugar solo return porque and return no funcionar
debido a la precedencia del operador en el lenguaje Ruby
def show
@book = Book.find(params[:id])
if @book.special?
render action: "special_show"
end
end
Esto har que se renderice book con special? establecido con la plantilla special_show ,
mientras que otros books se procesarn con la plantilla de show predeterminada.
302
2.2 Uso del render
303
2.3 Uso de redirect_to
redirect_to photos_url
Puede utilizar redirect_back para devolver al usuario a la pgina de la que proceden. Esta
ubicacin se extrae del encabezado HTTP_REFERER que el navegador no garantiza que se
establezca, por lo que debe proporcionar el fallback_location para utilizar en este caso.
redirect_back(fallback_location: root_path)
ejecucin del mtodo, sino que simplemente establecen respuestas HTTP . Las
declaraciones que ocurran despus de ellos en un mtodo sern ejecutadas. Usted
puede detener por un return explcito o algn otro mecanismo de detencin, si es
necesario.
Al igual que la opcin :status para render , :status para redirect_to acepta las
designaciones de encabezados numricos y simblicos.
304
2.3 Uso de redirect_to
A veces, los desarrolladores sin experiencia piensan en redirect_to como una especie de
comando go-to , que mueve la ejecucin de un lugar a otro en su cdigo Rails. Esto no es
correcto. Su cdigo deja de ejecutarse y espera una nueva solicitud para el navegador.
Sucede que le has dicho al navegador qu solicitud debe hacer a continuacin, enviando un
cdigo de estado HTTP 302 .
def index
@books = Book.all
end
def show
@book = Book.find_by(id: params[:id])
if @book.nil?
render action: "index"
end
end
destino, de modo que nada configurar la variable @books que probablemente requiera la
vista de index . Una manera de arreglar esto es redireccionar en lugar de renderizar:
def index
@books = Book.all
end
def show
@book = Book.find_by(id: params[:id])
if @book.nil?
redirect_to action: :index
end
end
Con este cdigo, el navegador har una nueva solicitud para la pgina index , y el cdigo
en el mtodo index se ejecutar, y todo estar bien.
El nico inconveniente de este cdigo es que requiere un viaje de ida y vuelta al navegador:
el navegador solicita la accin show con /books/1 y el controlador detecta que no hay
libros, por lo que el controlador enva una respuesta de redireccin 302 al navegador
dicindole que vaya a /books/ , el navegador cumple y enva una nueva solicitud al
controlador solicitando ahora la accin index , el controlador obtiene todos los libros de la
base de datos y procesa la plantilla index , devolvindola a la navegador que luego lo
muestra en su pantalla.
305
2.3 Uso de redirect_to
Mientras que en una pequea aplicacin, esta latencia aadida podra no ser un problema,
es algo en lo que pensar si el tiempo de respuesta es una preocupacin. Podemos
demostrar una manera de manejar esto con un ejemplo:
def index
@books = Book.all
end
def show
@book = Book.find_by(id: params[:id])
if @book.nil?
@books = Book.all
flash.now[:alert] = "Your book was not found"
render "index"
end
end
Esto detectara que no hay libros con el ID especificado, llena la variable de instancia de
@books con todos los libros del modelo y luego renderiza directamente la plantilla
306
2.4 Uso de los headers para crear respuestas Header-Only
head :bad_request
Lo que producira:
307
3 Estructuracin de los layouts
Partials
308
3.1 Asset Tag Helpers
auto_discovery_link_tag
javascript_include_tag
stylesheet_link_tag
image_tag
video_tag
audio_tag
Puede utilizar estas etiquetas en los layouts o en otras vistas, aunque la etiqueta
auto_discovery_link_tag , javascript_include_tag y stylesheet_link_tag se utilizan con
MIME apropiado.
:title especifica el ttulo del enlace. El valor predeterminado es el valor del type en
309
3.1 Asset Tag Helpers
Si est utilizando Rails con el assets pipeline activado, este helper generar un enlace a
/assets/javascripts/ en lugar de public/javascripts que se utiliz en versiones
Puede especificar una ruta de acceso completa y relativa a la raz del documento, o una
URL, si lo prefiere. Por ejemplo, para vincular a un archivo JavaScript que est dentro de un
directorio llamado javascripts dentro de uno de app/assets , lib/assets o
vendor/assets , hara esto:
<script src='/assets/main.js'></script>
310
3.1 Asset Tag Helpers
Si est utilizando Rails con el "Asset Pipeline" habilitado, este helper generar un enlace a
/assets/stylesheets/ . Este enlace es procesado por la gema de Sprockets. Un archivo de
311
3.1 Asset Tag Helpers
Puede suministrar texto alternativo para la imagen que se utilizar si el usuario tiene
imgenes desactivadas en su navegador. Si no especifica un texto alt explcitamente, el
valor predeterminado es el nombre del archivo, en maysculas y sin extensin. Por ejemplo,
estas dos etiquetas de imagen devolveran el mismo cdigo:
Adems de las etiquetas especiales anteriores, puede proporcionar un hash de las opciones
HTML estndar, como :class , :id o :name :
produce
312
3.1 Asset Tag Helpers
Al igual que un image_tag , puede proporcionar una ruta, absoluta o relativa al directorio
public/videos . Adems, puede especificar el tamao: " #{width}x#{height} " como una
image_tag . Las etiquetas de vdeo tambin pueden tener cualquiera de las opciones HTML
La etiqueta de vdeo tambin admite todas las opciones de <video> HTML a travs del
hash de opciones HTML, incluyendo:
poster : " image_name.png ", proporciona una imagen para poner en lugar del video
loop :true , hace un loop el video una vez que llega al final.
pgina.
Tambin puede especificar varios videos para reproducir pasando un array de videos a la
video_tag :
El cual produce
<video>
<source src="/videos/trailer.ogg">
<source src="/videos/movie.ogg">
</video>
Tambin puede proporcionar un hash de opciones adicionales, tales como :id , :class
etc.
313
3.1 Asset Tag Helpers
pgina.
314
3.2 Entendiendo Yield
<html>
<head>
</head>
<body>
<%= yield %>
</body>
</html>
<html>
<head>
<%= yield :head %>
</head>
<body>
<%= yield %>
</body>
</html>
El cuerpo principal de la vista siempre renderizar el yield sin nombre. Para convertir el
render en un yield con nombre, utilice el mtodo content_for .
315
3.3 Uso del mtodo content_for
<p>Hello, Rails!</p>
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, Rails!</p>
</body>
</html>
El mtodo content_for es muy til cuando el diseo contiene regiones distintas, como
barras laterales y pies de pgina, que deben tener sus propios bloques de contenido
insertados. Tambin es til para insertar etiquetas que cargan archivos JavaScript o CSS
especficos de la pgina en el encabezado de un diseo que de otra forma es genrico.
316
3.4 Uso de Partials
<h1>Products</h1>
317
3.4 Uso de Partials
Como se ve en las secciones anteriores de esta gua, yield es una herramienta muy
poderosa para limpiar sus layouts. Tenga en cuenta que es Ruby puro, por lo que puede
utilizarlo casi en todas partes. Por ejemplo, podemos usarlo para no repetir cdigo en
definiciones de diseos de formulario para varios recursos similares:
users/index.html.erb
roles/index.html.erb
shared/_search_filters.html.erb
Para el contenido que se comparte entre todas las pginas de la aplicacin, puede utilizar
parciales directamente desde los layouts.
318
3.4 Uso de Partials
new.html.erb
<h1>New zone</h1>
<%= render partial: "form", locals: {zone: @zone} %>
edit.html.erb
<h1>Editing zone</h1>
<%= render partial: "form", locals: {zone: @zone} %>
_form.html.erb
Para pasar una variable local a un parcial slo en casos especficos, utilice local_assigns .
319
3.4 Uso de Partials
index.html.erb
show.html.erb
_article.html.erb
De esta manera es posible utilizar el parcial sin necesidad de declarar todas las variables
locales.
Cada parcial tambin tiene una variable local con el mismo nombre que el parcial (menos el
subrayado). Puede pasar un objeto a esta variable local mediante la opcin :object :
Dentro del parcial del cliente , la variable cliente se referir a @new_customer desde la vista
principal.
Si tiene una instancia de un modelo para renderizar en un parcial, puede usar una sintaxis
abreviada:
Suponiendo que la variable de instancia @customer contiene una instancia del modelo
Customer , se utilizar _customer.html.erb para procesarla y pasar al cliente de variable
320
3.4 Uso de Partials
index.html.erb
<h1>Products</h1>
<%= render partial: "product", collection: @products %>
_product.html.erb
Cuando un parcial es llamado con una coleccin pluralizada, entonces las instancias
individuales del parcial tienen acceso al miembro de la coleccin que se est procesando a
travs de una variable llamada despus del parcial. En este caso, el parcial es _product , y
dentro del parcial _product , puede referirse al producto para obtener la instancia que se
est procesando.
Tambin hay una abreviatura para esto. Suponiendo que @products es una coleccin de
instancias de producto, simplemente puede escribir esto en index.html.erb para producir
el mismo resultado:
<h1>Products</h1>
<%= render @products %>
Rails determina el nombre del parcial que se va a usar al mirar el nombre del modelo en la
coleccin. De hecho, incluso puede crear una coleccin heterognea y convertirlo de esta
manera, y Rails elegir el parcial adecuado para cada miembro de la coleccin:
index.html.erb
<h1>Contacts</h1>
<%= render [customer1, employee1, customer2, employee2] %>
customers/_customer.html.erb
employees/_employee.html.erb
En este caso, Rails usar el parcial de cliente o empleado segn corresponda para cada
miembro de la coleccin.
321
3.4 Uso de Partials
En el caso de que la coleccin est vaca, render volver nil, por lo que debera ser
bastante sencillo proporcionar contenido alternativo.
<h1>Products</h1>
<%= render(@products) || "There are no products available." %>
Con este cambio, puede acceder a una instancia de la coleccin @products como la
variable local item dentro del parcial.
Tambin puede pasar variables arbitrarias locales a cualquier parcial que est procesando
con los locales :{} option :
En este caso, el parcial tendr acceso a un ttulo de variable local con el valor "Products
page".
Rails tambin hace que una variable de contador est disponible dentro de un parcial
llamado por la coleccin, nombrado despus del miembro de la coleccin seguido de
_counter . Por ejemplo, si est procesando @products , en el parcial puede referirse a
Tambin puede especificar un segundo parcial que se renderizar entre instancias del
parcial principal mediante la opcin: spacer_template :
Rails har que _product_ruler sea parcial (sin datos pasados a ella) entre cada par de
_product partials.
322
3.4 Uso de Partials
El diseo se renderizar junto con el parcial para cada elemento de la coleccin. Las
variables actuales de objeto y objeto-contador estarn disponibles en el layout, as como en
el parcial.
323
3.5 Uso de layouts anidados
<html>
<head>
<title><%= @page_title or "Page Title" %></title>
<%= stylesheet_link_tag "layout" %>
<style><%= yield :stylesheets %></style>
</head>
<body>
<div id="top_menu">Top menu items here</div>
<div id="menu">Menu items here</div>
<div id="content"><%= content_for?(:content) ? yield(:content) : yield %></div>
</body>
</html>
En las pginas generadas por NewsController , desea ocultar el men superior y agregar un
men de la derecha:
app/views/layouts/news.html.erb
Eso es. La vista News utilizarn el nuevo layout, ocultando el men superior y aadiendo un
nuevo men derecho dentro del div " content ".
Hay varias maneras de obtener resultados similares con diferentes esquemas de sub-
plantillas usando esta tcnica. Tenga en cuenta que no hay lmite en los niveles de
anidamiento. Puede usar el mtodo ActionView::render a travs de la plantilla de render:
324
3.5 Uso de layouts anidados
' layouts/news ' para basar un nuevo layout en el layout de news. Si est seguro de que no
quiere "sub-templear" el layout de noticias, puede reemplazar el content_for?
(:news_content) ? yield(:news_content) : yield por un simple yield .
325
X- Helpers de Formulario de Action View
Esta gua no pretende ser una documentacin completa de los helpers de formulario
disponibles y de sus argumentos. Visite la documentacin de la API de Rails para
obtener una referencia completa.
326
1- Tratamiento de formularios bsicos
Cuando se llama sin argumentos como ste, crea una etiqueta <form> que, cuando se
enve, se publicar en la pgina actual. Por ejemplo, asumiendo que la pgina actual es
/home/index , el HTML generado se ver as:
Observar que el HTML contiene un elemento de entrada con el tipo oculto. Esta entrada es
importante, porque el formulario no se puede enviar correctamente sin l. El elemento de
entrada oculto con el nombre utf8 hace que los navegadores respeten debidamente la
codificacin de caracteres de su formulario y se genera para todos los formularios, ya sea
que su accin sea " GET " o " POST ".
327
1- Tratamiento de formularios bsicos
Para cada input del formulario, se genera un atributo ID desde su name (" q " en el
ejemplo anterior). Estos identificadores pueden ser muy tiles para los estilos CSS o la
manipulacin de controles de formulario con JavaScript .
Siempre use " GET " como el mtodo para los formularios de bsqueda. Esto permite a
los usuarios marcar una bsqueda especfica y volver a ella. Ms generalmente, Rails
le anima a usar el verbo HTTP correcto para una accin.
328
1- Tratamiento de formularios bsicos
Cuando nombra los inputs, Rails utiliza ciertas convenciones que hacen posible enviar
parmetros con valores no escalares tales como arrays o hashes, que tambin sern
accesibles en params . Puede leer ms sobre ellos en el captulo 7 de esta gua. Para
obtener detalles sobre el uso preciso de estos ayudantes, consulte la documentacin de la
API.
329
1- Tratamiento de formularios bsicos
Salida:
Utilice siempre las etiquetas de checkbox o radio buttons. Asocian el texto a una
opcin especfica y, al expandir la regin seleccionable, facilitan que los usuarios
hagan clic en las entradas.
330
1- Tratamiento de formularios bsicos
Salida
Las entradas ocultas no se muestran al usuario, sino que en su lugar contienen datos como
cualquier entrada textual. Los valores dentro de ellos se pueden cambiar con JavaScript.
331
1- Tratamiento de formularios bsicos
Las entradas de bsqueda, telfono, fecha, hora, color, fecha, fecha, hora, mes,
semana, URL, correo electrnico, nmero y rango son controles HTML5. Si requiere
que su aplicacin tenga una experiencia consistente en navegadores antiguos,
necesitar un polyfill HTML5 (proporcionado por CSS y / o JavaScript).
Definitivamente no hay escasez de soluciones para esto, aunque una herramienta
popular en este momento es Modernizr , que proporciona una forma sencilla de
agregar funcionalidad basada en la presencia de caractersticas HTML5 detectadas.
332
2- Tratamiento de objetos del modelo
Debe pasar el nombre de una variable de instancia, es decir :person o " person ", no una
instancia real del objeto de modelo.
Rails proporciona ayuda para mostrar los errores de validacin asociados con un objeto del
modelo. Estas son cubiertas en detalle por la gua de validacin de Active Record.
333
2- Tratamiento de objetos del modelo
Mientras que esto es un aumento en la comodidad, est lejos de ser perfecto. Si Person
tiene muchos atributos para editar entonces estaramos repitiendo el nombre del objeto
editado muchas veces. Lo que queremos hacer de alguna manera es vincular un formulario
a un objeto del modelo, que es exactamente lo que form_for hace.
def new
@article = Article.new
end
<%= form_for @article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
<%= f.text_field :title %>
<%= f.text_area :body, size: "60x12" %>
<%= f.submit "Create" %>
<% end %>
una opcin de namespace para su formulario para garantizar la unicidad de los atributos
de id en los elementos del formulario. El atributo spacename ser prefijado con
subrayado en el id del HTML generado.
El mtodo form_for produce un objeto form builder (la variable f ).
Los mtodos para crear controles del formulario se llaman en el objeto de constructor
de formularios f .
El nombre pasado a form_for controla la clave utilizada en params para acceder a los
valores del formulario. Aqu el nombre es article y por lo tanto todos los inputs tienen
nombres del formulario article[attribute_name] . En consecuencia, en la accin de
334
2- Tratamiento de objetos del modelo
creacin params[:article] ser un hash con keys :title y :body . Puede leer ms sobre
la importancia de los nombres de entrada en la seccin parameter_names .
Los mtodos auxiliares llamados al constructor (builder) de formularios son idnticos a los
helpers de objetos del modelo, excepto que no es necesario especificar qu objeto se est
editando ya que ste ya est administrado por el constructor de formularios.
Puede crear un enlace similar sin crear realmente etiquetas <form> con el campo
fields_for helper. Esto es til para editar objetos de modelo adicionales con el mismo
El objeto dado por fields_for es un constructor de formularios como el que se obtiene por
form_for (de hecho form_for llama fields_for internamente).
resources :articles
Declarar un recurso tiene varios efectos secundarios. Vea "Rails Routing From Outside
In" para obtener ms informacin sobre cmo configurar y usar recursos.
335
2- Tratamiento de objetos del modelo
Cuando est utilizando STI (herencia de tabla nica) con sus modelos, no puede
confiar en la identificacin de registros en una subclase, si slo su clase principal se
declara a un recurso. Deber especificar el nombre del modelo, :url , y :method
explicitamente.
336
2- Tratamiento de objetos del modelo
Rails trabaja alrededor de este problema emulando otros mtodos en POST con una
entrada oculta denominada " _method ", que se establece para reflejar el mtodo deseado:
salida:
Al analizar datos POSTed, Rails tendr en cuenta el parmetro especial _method y actuar
como si el mtodo HTTP fuera el especificado dentro de l (" PATCH " en este ejemplo).
337
3- Hacer Select Boxes con facilidad
Aqu tiene una lista de ciudades cuyos nombres se le presentan al usuario. Internamente, la
aplicacin slo quiere manejar sus IDs para que se usen como el atributo value de las
opciones. Veamos cmo Rails nos puede ayudar aqu.
Esto es un comienzo, pero no crea dinmicamente las etiquetas option . Puede generar
etiquetas option con el helper options_for_select :
output:
<option value="1">Lisbon</option>
<option value="2">Madrid</option>
...
338
3- Hacer Select Boxes con facilidad
id de un objeto de la base de datos correspondiente, pero este no tiene que ser siempre
el caso.
output:
<option value="1">Lisbon</option>
<option value="2" selected="selected">Madrid</option>
...
Siempre que Rails vea que el valor interno de una opcin generada coincide con este valor,
agregar el atributo selected a esa opcin.
<%= options_for_select(
[
['Lisbon', 1, { 'data-size' => '2.8 million' }],
['Madrid', 2, { 'data-size' => '3.2 million' }]
], 2
) %>
output:
339
3- Hacer Select Boxes con facilidad
# controller:
@person = Person.new(city_id: 2)
# view:
<%= select(:person, :city_id, [['Lisbon', 1], ['Madrid', 2], ...]) %>
Al igual que con otros helpers, si utilizas el helper select en un constructor de formularios
con un alcance al objeto @person , la sintaxis sera:
esto es que los helpers de formulario slo editan los atributos. Tambin debe tener en
cuenta las potenciales ramificaciones de seguridad de permitir a los usuarios editar
claves forneas directamente.
340
3- Hacer Select Boxes con facilidad
Esta es una solucin perfectamente vlida, pero Rails proporciona una alternativa menos
verbosa: options_from_collection_for_select . Este ayudante espera una coleccin de
objetos arbitrarios y dos argumentos adicionales: los nombres de los mtodos para leer el
valor y texto de la opcin, respectivamente:
Como su nombre lo indica, esto slo genera etiquetas de opcin. Para generar un cuadro
de seleccin que funcione, necesitar utilizarlo junto con select_tag , tal como lo hara con
options_for_select . Cuando se trabaja con objetos de un modelo, de la misma manera
341
3- Hacer Select Boxes con facilidad
Para aprovechar el soporte de zona horaria en Rails, debe preguntar a los usuarios en qu
zona horaria se encuentran. Debera generar opciones de seleccin de una lista de objetos
TimeZone predefinidos mediante collection_select , pero puede usar simplemente el
Rails sola tener un ayudante country_select para elegir pases, pero esto se ha extrado
en el plugin country_select . Al usar esto, tenga en cuenta que la exclusin o inclusin de
ciertos nombres de la lista puede ser algo controversial (y fue la razn de que esta
funcionalidad se extrajo de Rails).
342
4- Uso de los helpers de formulario Fecha y Hora
Las fechas y los tiempos no son representables por un nico elemento input. En su
lugar, tiene varios, uno para cada componente (year, month, day etc.) y, por lo tanto, no
hay un valor nico en su params hash con su fecha o hora.
Otros helpers usan el sufijo _tag para indicar si un helper es un helper de barebones
o uno que opera con objetos de un modelo. En fechas y horas, select_date ,
select_time y select_datetime son los helpers de barebones, y date_select ,
Ambas familias de helpers crearn una serie de cajas de seleccion para los diferentes
componentes (ao, mes, da, etc.).
Las entradas anteriores daran lugar a params[:start_date] siendo un hash con claves
:year , :month , :day . Para obtener un objeto Date , Time o DateTime real, tendra que
343
4- Uso de los helpers de formulario Fecha y Hora
Record ya que Active Record espera que cada elemento del hash params corresponda a
un atributo. Los helpers de objetos de un modelo para fechas y horas envan parmetros
con nombres especiales; Cuando Active Record ve parmetros con tales nombres sabe que
deben ser combinados con los otros parmetros y dados a un constructor apropiado al tipo
de columna. Por ejemplo:
Cuando se pasa a Person.new (o update ), Active Record indica que todos estos
parmetros deben usarse para construir el atributo birth_date y utiliza la informacin del
sufijo para determinar en qu orden debe pasar estos parmetros a funciones como
Date.civil .
344
4- Uso de los helpers de formulario Fecha y Hora
Como regla general, debe utilizar date_select cuando trabaje con objetos de un modelo y
select_date en otros casos, como un formulario de bsqueda que filtre los resultados por
fecha.
En muchos casos los date pickers incorporados son torpes ya que no ayudan al
usuario en la elaboracin de la relacin entre la fecha y el da de la semana.
un input con el nombre del componente tiempo (por ejemplo, "year" para select_year ,
"month" para select_month , etc.), aunque esto puede anularse con la opcin :field_name .
La opcin :prefix funciona de la misma manera que hace para select_date y
select_time y tiene el mismo valor predeterminado.
El primer parmetro especifica qu valor debe seleccionarse y puede ser una instancia de
Date , Time o DateTime , en cuyo caso se extraer el componente relevante o un valor
Producir la misma salida si el ao actual es 2009 y el valor elegido por el usuario puede
ser recuperado por params[:date] [:year] .
345
5- Carga de archivos
5- Carga de archivos
Una tarea comn es cargar algn tipo de archivo, ya sea una imagen de una persona o un
archivo CSV que contenga datos para procesar. Lo ms importante a recordar con las
subidas de archivos es que la codificacin de la forma renderizada DEBE establecerse en
" multipart/form-data ". Si utiliza form_for , esto se hace automticamente. Si utiliza
form_tag , debe configurarlo usted mismo, como en el ejemplo siguiente.
atributo content_type que contiene el tipo MIME del archivo subido. El fragmento siguiente
guarda el contenido cargado en #{Rails.root}/public/uploads con el mismo nombre que el
archivo original (suponiendo que el formulario era el del ejemplo anterior).
def upload
uploaded_io = params[:person][:picture]
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb')
do |file|
file.write(uploaded_io.read)
end
end
346
5- Carga de archivos
Una vez que se ha cargado un archivo, hay una multitud de tareas potenciales, desde:
dnde almacenar los archivos (en disco, Amazon S3, etc.) y asociarlos con modelos para
cambiar el tamao de los archivos de imagen y generar miniaturas. Las complejidades de
esto estn ms all del alcance de esta gua, pero hay varias bibliotecas diseadas para
ayudar con ellas. Dos de los ms conocidos son CarrierWave y Paperclip.
347
6- Personalizacin de los constructores de formularios
Si reutiliza esto con frecuencia, puede definir un ayudante label_form_for que aplique
automticamente al constructor: por ejemplo la Opcin LabellingFormBuilder :
348
6- Personalizacin de los constructores de formularios
349
7- Entendiendo las convenciones de nombramiento de parmetros
todos los atributos para la persona a crear. El hash de parmetros tambin puede contener
arrays, arrays de hashes y as sucesivamente.
Las hashes pueden anidarse en tantos niveles como se requiera, por ejemplo:
350
7- Entendiendo las convenciones de nombramiento de parmetros
7.2 Combinndolos
Podemos mezclar y combinar estos dos conceptos. Un elemento de un hash podra ser un
array como en el ejemplo anterior, o puede tener un array de hashes. Por ejemplo, un
formulario puede permitirle crear cualquier nmero de direcciones repitiendo el siguiente
fragmento de formulario
Esto resultara en params[:addresses] siendo un array de hashes con las claves line1 ,
line2 y city . Rails decide comenzar a acumular valores en un nuevo hash cada vez que
Hay una restriccin, sin embargo, mientras que los hashes pueden anidarse
arbitrariamente, solo se permite un nivel de "arrayness". Los arrays pueden usualmente ser
reemplazadas por hashes; Por ejemplo, en lugar de tener un array de objetos de un modelo,
se puede tener un hash de objetos de un modelo indexados por su id , un array de indices
o algn otro parmetro.
351
7- Entendiendo las convenciones de nombramiento de parmetros
Suponiendo que la persona tena dos direcciones, con ids 23 y 45 esto creara una salida
similar a esto:
{'person' => {'name' => 'Bob', 'address' => {'23' => {'city' => 'Paris'}, '45' => {'ci
ty' => 'London'}}}}
352
7- Entendiendo las convenciones de nombramiento de parmetros
Rails sabe que todas estas entradas deben ser parte del hash de Person porque has
llamado fields_for en el primer constructor de formularios. Al especificar una opcin
:index , le est diciendo a Rails que en lugar de nombrar los inputs person[address]
[city] , debe insertar ese index rodeado de [] entre la direccin y la ciudad. Esto es a
menudo til ya que es fcil localizar qu registro de direccin debe ser modificado. Puede
pasar nmeros con alguna otra significacin, cadenas o incluso nil (lo que resultar en un
parmetro array que se est creando).
Como regla general, el nombre del input final es la concatenacin del name dado a
fields_for / form_for , el valor del index y el nombre del atributo. Tambin puede pasar una
opcin index directamente a helpers como text_field , pero suele ser menos repetitivo
especificar esto a nivel del constructor de formularios en lugar de en controles de input
individuales.
353
8- Formularios a Recursos Externos
A veces, cuando se envan datos a un recurso externo, como una pasarela de pago, los
campos que se pueden utilizar en el formulario estn limitados por una API externa y puede
ser indeseable generar un authenticity_token . Para no enviar un token , simplemente
pase false a la opcin :authenticity_token :
354
9- Construccin de formularios complejos
355
9- Construccin de formularios complejos
Cuando una asociacin acepta atributos anidados fields_for devuelve su bloque una vez
para cada elemento de la asociacin. En particular, si una persona no tiene direcciones, no
renderiza nada. Un patrn comn es que el controlador construya uno o ms childrens
vacos de manera que al menos un conjunto de campos se muestre al usuario. El ejemplo
siguiente resultara en 2 conjuntos de campos de direccin que se representan en el
formulario de la nueva persona.
def new
@person = Person.new
2.times { @person.addresses.build}
end
356
9- Construccin de formularios complejos
{
'person' => {
'name' => 'John Doe',
'addresses_attributes' => {
'0' => {
'kind' => 'Home',
'street' => '221b Baker Street'
},
'1' => {
'kind' => 'Office',
'street' => '31 Spooner Street'
}
}
}
}
Las claves del hash :addresses_attributes no son importantes, solo necesitan ser
diferentes para cada direccin.
coloca en una ubicacin donde una etiqueta de entrada no es HTML vlido o cuando se
utiliza un ORM donde los children no tienen un ID .
9.3 El controlador
Como de costumbre, necesitas incluir en la lista blanca los parmetros en el controlador
antes de pasarlos al modelo:
def create
@person = Person.new(person_params)
# ...
end
private
def person_params
params.require(:person).permit(:name, addresses_attributes: [:id, :kind, :street])
end
357
9- Construccin de formularios complejos
direcciones:
No olvide actualizar los parmetros de la lista blanca en su controlador para incluir tambin
el campo _destroy :
def person_params
params.require(:person).
permit(:name, addresses_attributes: [:id, :kind, :street, :_destroy])
end
devuelve false entonces Active Record no crear un objeto asociado para ese hash. El
ejemplo siguiente slo intenta generar una direccin si se establece el atributo kind.
358
9- Construccin de formularios complejos
Como conveniencia, puede pasar el smbolo: all_blank que crear un proc que rechazar
los registros donde todos los atributos estn en blanco, excluyendo cualquier valor para
_destroy .
359
XI- Descripcin general de Action Controller
360
1- Qu hace un controlador?
1- Qu hace un controlador?
Action Controller es la C en MVC. Despus de que el enrutador ha determinado qu
controlador utilizar para una solicitud, el controlador es responsable de dar sentido a la
solicitud y producir la salida adecuada. Por suerte, el controlador de accin hace la mayor
parte del trabajo duro por usted y utiliza las convenciones inteligentes para hacer esto lo
ms directo posible.
Por lo tanto, un controlador puede considerarse como un intermediario entre los modelos y
las vistas. Hace que los datos del modelo estn disponibles para que la vista pueda mostrar
esos datos al usuario, y guarda o actualiza los datos que ingresa un usuario en el modelo.
361
2- Convencin de nombres del controlador
sucesivamente.
362
3- Mtodos y acciones
3- Mtodos y acciones
Un controlador es una clase Ruby que hereda de ApplicationController y tiene mtodos
como cualquier otra clase. Cuando su aplicacin recibe una solicitud, el enrutamiento
determinar qu controlador y accin ejecutar, entonces Rails crea una instancia de ese
controlador y ejecuta el mtodo con el mismo nombre que la accin.
def new
@client = Client.new
end
mtodos tiles. Esta gua cubre algunos de estos, pero si tienes curiosidad de ver lo que
hay ah, puedes verlos todos en la documentacin de la API o en la fuente misma.
Slo los mtodos pblicos son llamados como acciones. Es una buena prctica reducir la
visibilidad de los mtodos (privados o protegidos) que no pretenden ser acciones, como los
mtodos auxiliares o los filtros.
363
4- Parmetros
4- Parmetros
Es probable que desee acceder a los datos enviados por el usuario u otros parmetros en
las acciones del controlador. Hay dos tipos de parmetros posibles en una aplicacin web.
Los primeros son los parmetros que se envan como parte de la URL, llamados
parmetros de la cadena de consulta. La cadena de consulta es todo lo que hay despus de
" ? " En la URL. El segundo tipo de parmetro se denomina normalmente datos POST . Esta
informacin normalmente proviene de un formulario HTML que ha sido llenado por el
usuario. Se llama datos POST porque slo se puede enviar como parte de una solicitud
HTTP POST. Rails no hace ninguna distincin entre los parmetros de cadena de consulta y
los parmetros de POST, y ambos estn disponibles en el hash params en su controlador:
364
4- Parmetros
GET /clients?ids[]=1&ids[]=2&ids[]=3
permitidos en las URL. La mayora de las veces no tienes que preocuparte por esto
porque el navegador lo codificar por ti, y Rails lo descodificar automticamente, pero
si alguna vez te encuentras teniendo que enviar esas solicitudes al servidor
manualmente debes tener esto en cuenta .
El valor de params[:ids] ser ahora ["1", "2", "3"] . Tenga en cuenta que los valores de
los parmetros son siempre cadenas; Rails no intenta adivinar o lanzar el type .
Valores como [nil] o [nil, nil, ...] en params se sustituyen por [] por motivos
de seguridad de forma predeterminada. Consulte la Gua de seguridad para obtener
ms informacin.
Para enviar un hash, debe incluir el nombre de la clave dentro de los corchetes:
Cuando se enve este formulario, el valor de params[:client] ser { "name" => "Acme",
"phone" => "12345", "address" => { "postcode" => "12345", "city" => "Carrot City" } } .
El objeto params acta como un Hash, pero le permite usar smbolos y cadenas de forma
intercambiable como claves.
365
4- Parmetros
Su controlador recibir params[:company] como {"name" => "acme", "address" => "123
Carrot Street"} .
parmetro JSON . En este caso, los parmetros sern clonados y envueltos con una clave
elegida basada en el nombre de su controlador. Por lo tanto, la peticin JSON anterior
puede escribirse como:
Y, asumiendo que usted est enviando los datos a CompaniesController , entonces sera
envuelto dentro de la llave :company as:
{ name: "acme", address: "123 Carrot Street", company: { name: "acme", address: "123 C
arrot Street" } }
Puede personalizar el nombre de la clave o los parmetros especficos que desea ajustar
consultando la documentacin de la API
366
4- Parmetros
4.4 default_url_options
Puede definir parmetros globales predeterminados para la generacin de las URLs
definiendo un mtodo denominado default_url_options en su controlador. Tal mtodo
debe devolver un hash con los valores predeterminados deseados, cuyas keys deben ser
smbolos:
Estas opciones se utilizarn como punto de partida al generar las URLs, por lo que es
posible que se anulen por las opciones que se pasan a url_for en las llamadas.
En una solicitud dada, el mtodo no es realmente llamado para cada URL generada; Por
razones de rendimiento, el hash devuelto se almacena en cach, y hay como mximo una
invocacin por solicitud.
Adems, los parmetros se pueden marcar como se requiera y fluirn a travs de un flujo
de raise/rescue predefinido que dar lugar a que se devuelva una 400 Bad Request si no se
pasan todos los parmetros requeridos.
367
4- Parmetros
# Esto pasar sin problemas, siempre y cuando hay una key person
# en los parmetros, de lo contrario dispara una excepcin
# ActionController::ParameterMissing, que obtendr una captura
# de ActionController::Base y lo convierte en un error 400 Bad
# Request.
def update
person = current_account.people.find(params[:id])
person.update!(person_params)
redirect_to person
end
private
# Utilizando un mtodo privado para encapsular los parmetros permitidos
# es slo un buen patrn ya que podr reutilizar el mismo
# permit del whitelist en create y update. Adems, puede especializarse
# este mtodo con la verificacin por usuario de los atributos permitidos.
def person_params
params.require(:person).permit(:name, :age)
end
end
params.permit(:id)
La clave :id pasa la lista blanca si aparece en params y tiene un valor escalar permitido
asociado. De lo contrario, la clave se va a filtrar, por lo que no se pueden inyectar arrays,
hashes ni ningn otro objeto.
Los tipos escalares permitidos son String , Symbol , NilClass , Numeric , TrueClass ,
FalseClass , Date , Time , DateTime , StringIO , IO ,
ActionDispatch::Http::UploadedFile , y Rack::Test::UploadedFile .
Para declarar que el valor en params debe ser un array de valores escalares permitidos,
debe mapear la key a un array vaco:
368
4- Parmetros
params.permit(id: [])
params.permit(preferences: {})
Pero tenga cuidado porque esto abre la puerta a un input arbitrario. En este caso, el
permit asegura que los valores en la estructura devuelta se permitan escalares y filtra
params.require(:log_entry).permit!
Esto marca los hash params :log_entry y cualquier sub-hash de l como permitido y no se
comprueba para los escalares permitidos, porque cualquier cosa es aceptada. Se debe
tener mucho cuidado cuando se usa permit! , ya que permitir asignar masivamente todos
los atributos actuales y futuros del modelo.
params.permit(:name, { emails: [] },
friends: [ :name,
{ family: [ :name ], hobbies: [] }])
Esta declaracin de lista blanca (whitelist) de name , emails y friends espera que los
emais sean un array de valores escalares permitidos y que los friends sean un array de
recursos con atributos especficos: deben tener un atributo name (cualquier valor escalar
permitido permitido), un atributo hobbies como un array escalar permitido, y valores y un
atributo de family que est restringido a tener un name (tambin se permiten valores
escalares aqu).
4.5.3 Ms ejemplos
Tambin puede usar los atributos de permit en su nueva accin. Esto dispara el problema
que no puede utilizar require en la clave raz porque, normalmente, no existe al llamar a
new :
369
4- Parmetros
Los hashs con claves enteras se tratan de forma diferente y se pueden declarar los
atributos como si fueran hijos directos. Obtiene este tipo de parmetros cuando utiliza
accept_nested_attributes_for en combinacin con una asociacin has_many :
def product_params
params.require(:product).permit(:name, data: params[:product][:data].try(:keys))
end
370
5- Session
5- Session
Su aplicacin tiene una sesin para cada usuario en la que puede almacenar pequeas
cantidades de datos que se mantendrn entre solicitudes. La sesin slo est disponible en
el controlador y la vista y puede utilizar uno de varios mecanismos de almacenamiento
diferentes:
Para la mayora del almacenamiento, este ID se utiliza para buscar los datos de sesin en
el servidor, por ejemplo: en una tabla de base de datos. Hay una excepcin, que es el
almacenamiento de sesin predeterminado y recomendado - el CookieStore - que
almacena todos los datos de sesin en la propia cookie (el ID an est disponible para
usted si lo necesita). Esto tiene la ventaja de ser muy ligero y requiere cero configuracin en
una nueva aplicacin para poder usar la sesin. Los datos de las cookies se firman
criptogrficamente para que sean inviolables. Y tambin est encriptada para que
cualquiera con acceso a ella no pueda leer su contenido. (Rails no lo aceptar si se ha
editado).
El CookieStore puede almacenar alrededor de 4kB de datos - mucho menos que los otros -
pero esto es generalmente suficiente. El almacenamiento de grandes cantidades de datos
en la sesin se desaconseja sin importar el almacn de sesin que utilice su aplicacin.
Debe evitar especialmente el almacenamiento de objetos complejos (cualquier objeto que
no sea bsico de Ruby, el ejemplo ms comn es instancias de un modelo) en la sesin, ya
que es posible que el servidor no pueda volver a montarlos entre las solicitudes, lo que
resultar en un error.
371
5- Session
# Utilice la base de datos para las sesiones en lugar del predeterminado basado en coo
kies,
# que no debe usarse para almacenar informacin altamente confidencial
# (create the session table with "rails g active_record:session_migration")
# Rails.application.config.session_store :active_record_store
Rails configura una clave de sesin (el nombre de la cookie) al firmar los datos de la sesin.
Estos tambin se pueden cambiar en un inicializador:
Tambin puede pasar una clave de dominio y especificar el nombre de dominio para la
cookie:
Rails configura (para CookieStore) una clave secreta utilizada para firmar los datos de la
sesin. Esto se puede cambiar en config/secrets.yml
372
5- Session
# Si cambia esta clave, todas las viejas cookies firmadas sern invlidas!
# asegrese de que la clave es de al menos 30 caracteres y todo aleatorio,
# y no hay palabras regulares o estars expuesto a ataques de diccionario.
# Puede utilizar `rails secret` para generar una clave secreta segura.
# asegrese de que las claves de este archivo se mantengan privadas
# si est compartiendo su cdigo pblicamente.
development:
secret_key_base: a75d...
test:
secret_key_base: 492f...
private
373
5- Session
Para almacenar algo en la sesin, slo tiene que asignarla a la clave como un hash:
5.2 El Flash
El flash es una parte especial de la sesin que se borra con cada solicitud. Esto significa
que los valores almacenados all solo estarn disponibles en la siguiente peticin, que es
til para pasar mensajes de error, etc.
Se accede de la misma manera que la sesin, como un hash (es una instancia de
FlashHash).
Utilicemos el acto de cerrar sesin como ejemplo. El controlador puede enviar un mensaje
que se mostrar al usuario en la siguiente solicitud:
374
5- Session
Tenga en cuenta que tambin es posible asignar un mensaje de flash como parte de una
redireccin. Usted puede asignarlo como :notice , :alert o de propsito general
:flash :
<html>
<!-- <head/> -->
<body>
<% flash.each do |name, msg| -%>
<%= content_tag :div, msg, class: name %>
<% end -%>
Puede pasar cualquier cosa que la sesin pueda almacenar; No se limita a avisos y alertas:
Si desea que un valor de flash se transfiera a otra solicitud, utilice el mtodo keep :
375
5- Session
# You can also use a key to keep only some kind of value.
# flash.keep(:notice)
redirect_to users_url
end
end
5.2.1 flash.now
De forma predeterminada, agregar valores a flash los har disponibles para la siguiente
solicitud, pero a veces es posible que desee acceder a esos valores en la misma solicitud.
Por ejemplo, si la accin create no puede guardar un recurso y renderizar la nueva
plantilla directamente, no resultar en una nueva solicitud, pero es posible que quiera
mostrar un mensaje utilizando flash. Para ello, puede utilizar flash.now de la misma
manera que utiliza el flash normal:
376
6- Cookies
6- Cookies
Su aplicacin puede almacenar pequeas cantidades de datos en el cliente, llamadas
cookies , que se mantendrn en las solicitudes e incluso en las sesiones. Rails proporciona
un fcil acceso a las cookies a travs del mtodo cookies , que - al igual que la sesin -
funciona como un hash:
def create
@comment = Comment.new(params[:comment])
if @comment.save
flash[:notice] = "Thanks for your comment!"
if params[:remember_name]
# Remember the commenter's name.
cookies[:commenter_name] = @comment.author
else
# Delete cookie for the commenter's name cookie, if any.
cookies.delete(:commenter_name)
end
redirect_to @comment.article
else
render action: "new"
end
end
end
Tenga en cuenta que mientras que para los valores de sesin se establece la key a nil ,
para eliminar un valor de cookie debe utilizar cookies.delete (:key) .
Rails tambin proporciona un cookie jar (tarro de cookies) firmado (signed) y un tarro de
galletas encriptado para almacenar datos confidenciales. El cookie firmado anexa una firma
criptogrfica en los valores de cookie para proteger su integridad. El tarro de cookies cifrado
cifra los valores adems de firmarlos, de modo que no puedan ser ledos por el usuario
final. Consulte la documentacin de la API para obtener ms detalles.
Estos tarros de galletas especiales utilizan un serializador para serializar los valores
asignados en cadenas y los deserializa en objetos Ruby para la lectura.
377
6- Cookies
Rails.application.config.action_dispatch.cookies_serializer = :json
Tambin puede establecer esta opcin en :hybrid , en cuyo caso Rails deserializara de
forma transparente las cookies existentes ( Marshal -serialized) en lectura y volver a
escribirlas en el formato JSON . Esto es til para migrar aplicaciones existentes a :json
serializer.
Rails.application.config.action_dispatch.cookies_serializer = MyCustomSerializer
Cuando utilice el serializador :json o :hybrid , debe tener cuidado de que no todos los
objetos de Ruby se pueden serializar como JSON . Por ejemplo, los objetos Fecha y Hora
se serializarn como cadenas y los Hashes tendrn sus claves constreidas (stringified).
def read_cookie
cookies.encrypted[:expiration_date] # => "2014-03-20"
end
end
Es aconsejable que slo almacene datos sencillos (cadenas y nmeros) en las cookies. Si
tiene que almacenar objetos complejos, necesitar manejar la conversin manualmente al
leer los valores en solicitudes posteriores.
378
7- Renderizando datos XML y JSON
Puede notar en el cdigo anterior que estamos utilizando render xml: @users , no render
xml: @users.to_xml . Si el objeto no es una cadena, Rails invocar automticamente to_xml
por nosotros.
379
8- Filters
8- Filters
Los filtros son mtodos que se ejecutan before "antes", after "despus" o around
"alrededor" de una accin del controlador.
Un filtro "before" puede detener el ciclo de una solicitud. Un filtro "before" comn es aquel
que requiere que un usuario est conectado para que se ejecute una accin. Puede definir
el mtodo de filtro de esta manera:
private
def require_login
unless logged_in?
flash[:error] = "You must be logged in to access this section"
redirect_to new_login_url # halts request cycle
end
end
end
380
8- Filters
Ahora, las acciones new y create de LoginsController funcionarn como antes sin
requerir que el usuario est conectado. La opcin :only se usa para omitir este filtro solo
para estas acciones, y tambin hay una opcin :except que funciona de manera opuesta.
Estas opciones tambin se pueden utilizar al agregar filtros, por lo que puede agregar un
filtro que slo se ejecuta para acciones seleccionadas en primer lugar.
Los filtros "after" son similares a los filtros "before", pero debido a que la accin ya se ha
ejecutado tienen acceso a los datos de respuesta que estn a punto de ser enviados por el
cliente. Obviamente, los filtros "after" no pueden detener la ejecucin de la accin.
Los filtros "around" son responsables de ejecutar sus acciones asociadas por yielding,
similar a cmo funcionan los middlewares Rack.
Por ejemplo, en un sitio web en el que los cambios tienen un flujo de trabajo de aprobacin,
un administrador puede obtener una vista previa de ellos fcilmente, y solo debe aplicarlos
en una transaccin:
private
def wrap_in_transaction
ActiveRecord::Base.transaction do
begin
yield
ensure
raise ActiveRecord::Rollback
end
end
end
end
Usted puede elegir no ceder y construir la respuesta usted mismo, en cuyo caso la accin
no se ejecutar.
381
8- Filters
La primera es usar un bloque directamente con los mtodos * _action . El bloque recibe el
controlador como un argumento. El filtro require_login de arriba podra ser reescrito para
usar un bloque:
Tenga en cuenta que el filtro en este caso utiliza send porque el metodo logged_in? es
privado y el filtro no se ejecuta en el mbito del controlador. Esta no es la forma
recomendada de implementar este filtro en particular, pero en casos ms simples podra ser
til.
La segunda forma es usar una clase (en realidad, cualquier objeto que responda a los
mtodos correctos lo har) para manejar el filtrado. Esto es til en casos que son ms
complejos y no se pueden implementar de una manera legible y reutilizable usando los
otros dos mtodos. Como ejemplo, podra volver a escribir el filtro de inicio de sesin de
nuevo para usar una clase:
class LoginFilter
def self.before(controller)
unless controller.send(:logged_in?)
controller.flash[:error] = "You must be logged in to access this section"
controller.redirect_to controller.new_login_url
end
end
end
Una vez ms, este no es un ejemplo ideal para este filtro, ya que no se ejecuta en el mbito
del controlador, pero obtiene el controlador pasado como un argumento. La clase filter debe
implementar un mtodo con el mismo nombre que el filtro, por lo que para el filtro
382
8- Filters
383
9- Request Forgery Protection
El primer paso para evitar esto es asegurarse de que todas las acciones "destructivas"
( create , update y destroy ) slo se puede acceder con las solicitudes no-GET. Si sigues
las convenciones RESTful ya lo ests haciendo. Sin embargo, un sitio malicioso todava
puede enviar una solicitud no GET a su sitio con bastante facilidad, y ah es donde entra en
juego la proteccin contra la falsificacin de solicitudes. Como dice el nombre, protege de
las solicitudes falsificadas.
La forma en que se hace esto es agregando un token no adivinable que slo conoce su
servidor en cada solicitud. De esta manera, si una solicitud llega sin el token adecuado, se
le denegar el acceso.
Rails agrega este token a cada formulario que se genera utilizando los ayudantes de
formulario, por lo que la mayor parte del tiempo no tiene que preocuparse por ello. Si est
escribiendo un formulario manualmente o necesita agregar el token por otro motivo, est
disponible a travs del mtodo form_authenticity_token :
384
9- Request Forgery Protection
385
10- Objetos de solicitud y respuesta
Propiedad de la
Propsito
solicitud
host El nombre de host utilizado para esta solicitud.
Los primeros n segmentos del nombre de host,
domain(n=2)
comenzando desde la derecha (el TLD).
format El tipo de contenido solicitado por el cliente.
method El mtodo HTTP utilizado para la solicitud.
get?, post?, path?, put?, Devuelve true si el mtodo HTTP es GET / POST / PATCH
delete?, head? / PUT / DELETE / HEAD
Devuelve un hash que contiene los encabezados
headers
asociados con la peticin.
386
10- Objetos de solicitud y respuesta
Rails recopila todos los parmetros enviados junto con la solicitud en el hash de
parmetros, ya sea que se enven como parte de la cadena de consulta o el cuerpo de la
publicacin. El objeto de la peticin tiene tres accesores que le dan acceso a estos
parmetros dependiendo de su procedencia. El hash query_parameters contiene
parmetros que se enviaron como parte de la cadena de consulta mientras que el hash
request_parameters contiene los parmetros enviados como parte del cuerpo de la
Propiedad de
Propsito
la respuesta
response.headers["Content-Type"] = "application/pdf"
387
10- Objetos de solicitud y respuesta
388
11- Autenticaciones HTTP
Autenticacin bsica
Autenticacin Digest
389
11- Autenticaciones HTTP
before_action :authenticate
private
def authenticate
authenticate_or_request_with_http_digest do |username|
USERS[username]
end
end
end
390
12- Streaming y descargas de archivos
require "prawn"
class ClientsController < ApplicationController
# Generates a PDF document with information on the client and
# returns it. The user will get the PDF as a file download.
def download_pdf
client = Client.find(params[:id])
send_data generate_pdf(client),
filename: "#{client.name}.pdf",
type: "application/pdf"
end
private
def generate_pdf(client)
Prawn::Document.new do
text client.name, align: :center
text "Address: #{client.address}"
text "Email: #{client.email}"
end.render
end
end
391
12- Streaming y descargas de archivos
Esto leer y transmitir el archivo 4kB en ese momento, evitando cargar todo el archivo en
la memoria a la vez. Puede desactivar la transmisin con la opcin :stream o ajustar el
tamao del bloque con la opcin :buffer_size .
application/octet-stream .
Tenga cuidado al utilizar los datos procedentes del cliente (params, cookies, etc.) para
localizar el archivo en disco, ya que se trata de un riesgo de seguridad que podra
permitirle a alguien acceder a archivos a los que no estn destinados.
392
12- Streaming y descargas de archivos
respond_to do |format|
format.html
format.pdf { render pdf: generate_pdf(@client) }
end
end
end
Para que este ejemplo funcione, debe agregar el tipo MIME PDF a Rails. Esto se puede
hacer agregando la siguiente lnea al archivo config/initializers/mime_types.rb :
Los archivos de config no se vuelven a cargar en cada solicitud, por lo que debe
reiniciar el servidor para que sus cambios surtan efecto.
Ahora el usuario puede solicitar para obtener una versin en PDF de un cliente simplemente
aadiendo " .pdf " a la URL:
GET /clients/1.pdf
393
12- Streaming y descargas de archivos
def stream
response.headers['Content-Type'] = 'text/event-stream'
100.times {
response.stream.write "hello world\n"
sleep 1
}
ensure
response.stream.close
end
end
El cdigo anterior mantendr una conexin persistente con el navegador y enviar 100
mensajes de " hola mundo \ n ", cada segundo.
Si queramos devolver las letras en modo Karaoke (slo enviar la lnea cuando el cantante
haya terminado la lnea anterior), entonces podramos usar ActionController::Live de la
siguiente manera:
394
12- Streaming y descargas de archivos
def show
response.headers['Content-Type'] = 'text/event-stream'
song = Song.find(params[:id])
song.each do |line|
response.stream.write line.lyrics
sleep line.num_beats
end
ensure
response.stream.close
end
end
El cdigo anterior enva la siguiente lnea slo despus de que el cantante haya completado
la lnea anterior.
Cada flujo de respuesta crea un nuevo subproceso y copia sobre las variables locales
de subproceso del subproceso original. Tener demasiadas variables locales de
subproceso puede afectar negativamente el rendimiento. Del mismo modo, un gran
nmero de hilos tambin pueden dificultar el rendimiento.
Si no se cierra el flujo de respuesta se deja el socket correspondiente abierto para
siempre. Asegrese de llamar close cada vez que utilice un flujo de respuesta.
Los servidores WEBrick almacenan todas las respuestas, por lo que incluir
ActionController::Live no funcionar. Debe utilizar un servidor web que no almacena
395
13- Filtrado de logs
396
14- Rescue
14- Rescue
Lo ms probable es que su aplicacin va a contener errores o lanzar una excepcin que
debe tratarse. Por ejemplo, si el usuario sigue un vnculo a un recurso que ya no existe en
la base de datos, Active Record lanzar la excepcin ActiveRecord::RecordNotFound .
El control de excepciones por defecto de Rails muestra un mensaje "500 Server Error" para
todas las excepciones. Si la solicitud se realiz localmente, un buen rastreo y una cierta
informacin agregada se muestra para que pueda averiguar qu sali mal y tratar con l. Si
la solicitud era remota, Rails slo mostrar un simple mensaje de error "500 Server Error" al
usuario, o un "404 Not Found" si hubo un error de enrutamiento o un registro no se pudo
encontrar. A veces es posible que desee personalizar cmo se detectan estos errores y
cmo se muestran al usuario. Hay varios niveles de manejo de excepciones disponibles en
una aplicacin de Rails:
informacin adicional y estilos, pero recuerde que son HTML esttico; Es decir, no puede
utilizar ERB , SCSS , CoffeeScript o diseos para ellos.
14.2 rescue_from
Si quieres hacer algo ms elaborado al detectar errores, puedes usar rescue_from , que
maneja excepciones de cierto tipo (o varios tipos) en un controlador completo y sus
subclases.
Cuando se produce una excepcin que es detectada por una directiva rescue_from , el
objeto de excepcin se pasa al manejador (handler). El manejador (handler) puede ser un
mtodo o un objeto Proc pasado a la opcin :with . Tambin puede utilizar un bloque
directamente en lugar de un objeto Proc explcito.
A continuacin, le indicamos cmo puede utilizar rescue_from para interceptar todos los
errores de ActiveRecord::RecordNotFound y hacer algo con ellos.
397
14- Rescue
private
def record_not_found
render plain: "404 Not Found", status: 404
end
end
private
def user_not_authorized
flash[:error] = "You don't have access to this section."
redirect_back(fallback_location: root_path)
end
end
# Note how the actions don't have to worry about all the auth stuff.
def edit
@client = Client.find(params[:id])
end
private
398
14- Rescue
399
15- Forzar el protocolo HTTPS
class DinnerController
force_ssl
end
Al igual que los filtros, tambin podra pasar :only y :except para hacer cumplir la
conexin segura slo a acciones especficas:
class DinnerController
force_ssl only: :cheeseburger
# or
force_ssl except: :cheeseburger
end
400
XII- Enrutamiento en Rails
401
1- El Propsito del Enrutador de Rails
GET /patients/17
pide al router que coincida con una accin del controlador. Si la primera ruta coincidente es:
@patient = Patient.find(17)
402
1- El Propsito del Enrutador de Rails
403
2- Ruta resource: el valor predeterminado de Rails
DELETE /photos/17
Pide al enrutador que lo mande a una accin del controlador. Si la primera ruta coincidente
es:
resources :photos
Rails enviar esa solicitud a la accin destroy en el controlador de fotos con {id: '17'}
en params.
con una operacin CRUD especfica en una base de datos. Una sola entrada en el archivo
de enrutamiento, como por ejemplo:
resources :photos
404
2- Ruta resource: el valor predeterminado de Rails
Debido a que el enrutador usa el verbo HTTP y la URL para coincidir con las
solicitudes entrantes, cuatro direcciones URL asignan siete acciones diferentes.
Las rutas de Rails se emparejan en el orden en que se especifican, por lo que si tienes
resources :photos arriba de get 'photos/poll' la ruta de la accin show para la
lnea de resources coincidir antes de la lnea get . Para arreglar esto, mueva la
lnea get por encima de la lnea de resources para que coincida primero.
retorna /photos/10/edit )
photo_path(:id) retorna /photos/:id (por ejemplo, photo_path(10) retorna
/photos/10 )
ruta.
405
2- Ruta resource: el valor predeterminado de Rails
resources :photos
resources :books
resources :videos
resource :geocoder
406
2- Ruta resource: el valor predeterminado de Rails
Como es posible que desee utilizar el mismo controlador para una ruta singular ( /account )
y una ruta plural ( /accounts/45 ), los recursos singulares se asignan a controladores
mltiples. Por ejemplo, resource: photo y resources: photos crea rutas singulares y
plurales que se asignan al mismo controlador ( PhotosController ).
Al igual que con recursos en plural, los mismos helpers que terminan en _url tambin
incluirn el prefijo host, port y path.
Un error de larga data impide que form_for trabaje automticamente con recursos
singulares. Como solucin, especifique la URL del formulario directamente, de la siguiente
manera:
407
2- Ruta resource: el valor predeterminado de Rails
namespace :admin do
resources :articles, :comments
end
Esto crear una serie de rutas para cada uno de los controladores articles y comments .
Para Admin::ArticlesController , Rails crear:
O, en un solo caso:
scope '/admin' do
resources :articles, :comments
end
O, en un solo caso:
408
2- Ruta resource: el valor predeterminado de Rails
En cada uno de estos casos, las rutas nombradas siguen siendo las mismas que si no
utiliza el mbito. En el ltimo caso, las siguientes rutas mapean a ArticlesController :
Las rutas anidadas permiten capturar esta relacin en el enrutamiento. En este caso, puede
incluir esta declaracin de ruta:
resources :magazines do
resources :ads
end
Adems de las rutas para magazines, esta declaracin tambin enruta los anuncios a un
AdsController. Las URL de los ads requieren un magazine:
muestra una
409
2- Ruta resource: el valor predeterminado de Rails
lista de todos
GET /magazines/:magazine_id/ads ads#index los anuncios
de una
revista
especfica
devuelve un
formulario
HTML para
crear un
GET /magazines/:magazine_id/ads/new ads#new nuevo
anuncio
perteneciente
a una revista
especfica
crea un
nuevo
anuncio
POST /magazines/:magazine_id/ads ads#create
perteneciente
a una revista
especfica
muestra un
anuncio
especfico
GET /magazines/:magazine_id/ads/:id ads#show
perteneciente
a una revista
especfica
devuelve un
formulario
HTML para
editar un
GET /magazines/:magazine_id/ads/:id/edit ads#edit
anuncio
perteneciente
a una revista
especfica
actualiza un
anuncio
especfico
PATCH/PUT /magazines/:magazine_id/ads/:id ads#update
perteneciente
a una revista
especfica
elimina un
anuncio
especfico
DELETE /magazines/:magazine_id/ads/:id ads#destroy
perteneciente
a una revista
especfica
410
2- Ruta resource: el valor predeterminado de Rails
parmetro ( magazine_ads_url(@magazine) ).
resources :publishers do
resources :magazines do
resources :photos
end
end
/publishers/1/magazines/2/photos/3
resources :articles do
resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]
Esta idea establece un equilibrio entre las rutas descriptivas y el anidamiento profundo.
Existe sintaxis abreviada para lograr eso, a travs de la opcin :shallow :
411
2- Ruta resource: el valor predeterminado de Rails
resources :articles do
resources :comments, shallow: true
end
Esto generar exactamente las mismas rutas que el primer ejemplo. Tambin puede
especificar la opcin :shallow en el recurso padre, en cuyo caso todos los recursos
anidados sern superficiales ( shallow ):
El mtodo superficial ( shallow ) de la DSL crea un mbito dentro del cual cada anidado es
superficial. Esto genera las mismas rutas que el ejemplo anterior:
shallow do
resources :articles do
resources :comments
resources :quotes
resources :drafts
end
end
Existen dos opciones de mbito para personalizar rutas poco profundas. prefijos
:shallow_path del path miembro con el parmetro especificado:
412
2- Ruta resource: el valor predeterminado de Rails
413
2- Ruta resource: el valor predeterminado de Rails
concern :commentable do
resources :comments
end
concern :image_attachable do
resources :images, only: :index
end
Lo anterior es equivalente a:
resources :messages do
resources :comments
end
resources :articles do
resources :comments
resources :images, only: :index
end
Tambin puedes usarlos en cualquier lugar que quieras dentro de las rutas, por ejemplo en
una llamada de mbito o de espacio de nombres:
namespace :articles do
concerns :commentable
end
resources :magazines do
resources :ads
end
414
2- Ruta resource: el valor predeterminado de Rails
En este caso, Rails ver que @magazine es una revista y @ad es un anuncio y por lo tanto
utilizar el ayudante de magazine_ad_path . En helpers como link_to , puede especificar
slo el objeto en lugar de la llamada completa url_for :
Para otras acciones, slo tiene que insertar el nombre de la accin como el primer elemento
del array:
Esto le permite tratar instancias de sus modelos como URLs, y es una ventaja clave para
usar el estilo resource.
415
2- Ruta resource: el valor predeterminado de Rails
resources :photos do
member do
get 'preview'
end
end
Dentro del bloque de rutas member, cada nombre de ruta especifica que el verbo HTTP
ser reconocido. Puedes usar aqu get , patch , put , post o delete . Si no tiene
mltiples rutas member , tambin puede pasar :on a una ruta, eliminando el bloque:
resources :photos do
get 'preview', on: :member
end
Puede omitir la opcin :on , esto crear la misma ruta member , excepto que el valor id
del recurso estar disponible en params[:photo_id] en lugar de params[:id] .
resources :photos do
collection do
get 'search'
end
end
Esto permitir a Rails reconocer rutas como /photos/search con GET , y enruta a la accin
search de PhotosController . Tambin crear los helpers de bsqueda search_photos_url
y search_photos_path .
Al igual que con las rutas member , puede pasar :on a una ruta:
resources :photos do
get 'search', on: :collection
end
416
2- Ruta resource: el valor predeterminado de Rails
Para agregar una accin nueva alternativa se hace mediante el acceso directo :on
resources :comments do
get 'preview', on: :new
end
Esto permitir a Rails reconocer rutas como /comments/new/preview con GET , y enruta a la
accin preview de CommentsController . Tambin crear los auxiliares de ruta
preview_new_comment_url y preview_new_comment_path .
417
3- Rutas sin resources
Mientras que normalmente debe usar resources, todava hay muchos lugares donde el
enrutamiento simple es ms apropiado. No hay necesidad de intentar cazar cada pieza de
su aplicacin en un marco de recursos si no es un buen ajuste.
En particular, el enrutamiento sencillo facilita el mapeo de las URL heredadas a las nuevas
acciones de Rails.
Si una solicitud entrante a /photos/1 es procesada por esta ruta (porque no ha coincidido
con ninguna ruta anterior en el archivo), entonces el resultado ser invocar la accin de
visualizacin del PhotosController y hacer que el parmetro final " 1 " este disponible
como params[:id] . Esta ruta tambin encaminar la solicitud entrante de /photos a
PhotosController#display , ya que el :id es un parmetro opcional, indicado por
parntesis.
Una ruta entrante de /photos/1/2 ser enviada a la accin show del PhotosController .
params[: id] ser " 1 ", y params[:user_id] ser " 2 ".
418
3- Rutas sin resources
Esta ruta respondera a rutas como /photos/1/with_user/2 . En este caso, params sera {
controller: 'photos', action: 'show', id: '1', user_id: '2' } .
Una ruta entrante de /photos/1?user_id=2 ser enviada a la accin show del controlador
Photos . params ser { controller: 'photos', action: 'show', id: '1', user_id: '2' } .
Tambin puede utilizar valores predeterminados en un formato de bloque para definir los
valores predeterminados para varios elementos:
419
3- Rutas sin resources
Tambin puede utilizar esta opcin para anular mtodos de enrutamiento definidos por
recursos, como estos:
Esto definir un mtodo user_path que estar disponible en los controladores, ayudantes y
vistas que irn a una ruta como /bob . Dentro de la accin show de UsersController ,
params[:username] contendr el nombre de usuario para el usuario. cambie :username en
Puede hacer coincidir todos los verbos con una ruta particular usando via: :all
420
3- Rutas sin resources
El enrutamiento de las solicitudes GET y POST a una sola accin tiene implicaciones
de seguridad. En general, debe evitar enrutar todos los verbos a una accin a menos
que tenga una buena razn para hacerlo.
' GET ' en Rails no comprobar el token CSRF. Nunca debe escribir en la base de datos
desde solicitudes 'GET', para obtener ms informacin, consulte la gua de seguridad
sobre contramedidas CSRF.
Esta ruta coincidira con rutas como /photos/A12345, pero no /photos/893 . Puedes
expresar ms sucintamente la misma ruta de esta manera:
:constraints toma expresiones regulares con la restriccin de que los anchors con regexp
Sin embargo, tenga en cuenta que no es necesario utilizar anchors porque todas las rutas
estn ancladas al principio.
Por ejemplo, las siguientes rutas permitiran que los artculos con valores to_param como
1-hello-world que siempre empiecen con un nmero y los usuarios con valores to_param
como david que nunca empiecen con un nmero para compartir el espacio de nombres raz:
421
3- Rutas sin resources
namespace :admin do
constraints subdomain: 'admin' do
resources :photos
end
end
Sin embargo, puedes usar un lambda como en get 'foo' , las restricciones: lambda {|
req | Req.format ==: json} y la ruta slo coincidir con las solicitudes JSON explcitas.
422
3- Rutas sin resources
class BlacklistConstraint
def initialize
@ips = Blacklist.retrieve_ips
end
def matches?(request)
@ips.include?(request.remote_ip)
end
end
Rails.application.routes.draw do
get '*path', to: 'blacklist#index',
constraints: BlacklistConstraint.new
end
Rails.application.routes.draw do
get '*path', to: 'blacklist#index',
constraints: lambda { |request| Blacklist.retrieve_ips.include?(request.remote_ip)
}
end
Los segmentos comodn pueden ocurrir en cualquier lugar de una ruta. Por ejemplo:
423
3- Rutas sin resources
Sera igual a zoo/woo/foo/bar/baz con params[:a] igual a ' zoo/woo ', y params[:b] es
igual a 'bar/baz '.
Al solicitar ' /foo/bar.json' , sus params[:pages] sern iguales a 'foo/bar ' con el formato
de solicitud de JSON . Si desea que el antiguo comportamiento 3.0.x, puede proporcionar el
formato :false como este:
Si desea que el segmento de formato sea obligatorio, por lo que no se puede omitir, puede
proporcionar formato :true como este:
3.12 Redireccionamiento
Puede redirigir cualquier ruta a otra ruta utilizando el ayudante de redireccin en su
enrutador:
Tambin puede proporcionar un bloque para redirigir, que recibe los parmetros de ruta
simbolizados y el objeto de la peticin:
424
3- Rutas sin resources
Si especifica una aplicacin Rack como punto final para un matcher, recuerde que la ruta no
cambiar en la aplicacin receptora. Con la siguiente ruta, la aplicacin de Rack debe
esperar que la ruta sea ' /admin ':
Si prefiere que su aplicacin Rack reciba peticiones en la ruta raz, utilice mount :
425
3- Rutas sin resources
Debe poner la ruta raz en la parte superior del archivo, ya que es la ruta ms popular y
debe coincidir primero.
Tambin puede utilizar la ruta raz dentro de espacios de nombres y los mbitos. Por
ejemplo:
namespace :admin do
root to: "admin#index"
end
426
4- Personalizacin de rutas de recursos
Reconocern los paths entrantes que empiezan con /photos , pero la ruta al controlador de
imgenes:
Utilice photos_path , new_photo_path , etc. para generar rutas de acceso para este
recurso.
Para los controladores con espacios de nombres, puede utilizar la notacin de directorio.
Por ejemplo:
427
4- Personalizacin de rutas de recursos
Esta declaracin limita el parmetro :id para que coincida con la expresin regular
suministrada. Por lo tanto, en este caso, el enrutador ya no coincidira con esta ruta
/photos/1 . En su lugar coincidira con, /photos/RR27 .
Puede especificar una restriccin nica para aplicar a un nmero de rutas utilizando el
formulario de bloque:
constraints(id: /[A-Z][A-Z][0-9]+/) do
resources :photos
resources :accounts
end
Por supuesto, puede utilizar las limitaciones ms avanzadas disponibles en rutas sin-
resources en este contexto.
Reconocern las rutas entrantes que empiezan con /photos y enrutarn las solicitudes a
PhotosController , pero usarn el valor de la opcin :as para nombrar a los helpers.
428
4- Personalizacin de rutas de recursos
/photos/make
/photos/1/change
Esta opcin no cambia los nombres de los action reales. Los dos paths mostrados
seguiran la ruta hacia las acciones new y de edit .
Si desea cambiar esta opcin de manera uniforme para todas sus rutas, puede utilizar
un scope.
429
4- Personalizacin de rutas de recursos
scope 'admin' do
resources :photos, as: 'admin_photos'
end
resources :photos
scope ':username' do
resources :articles
end
430
4- Personalizacin de rutas de recursos
Ahora, una solicitud GET /photos tendra xito, pero una solicitud POST /photos (que
normalmente se encaminan a la accin create ) fallar.
La opcin :except especifica una ruta o lista de rutas que Rails no debe crear:
En este caso, Rails crear todas las rutas normales excepto la ruta para destruir (una
solicitud DELETE a /photos/:id ).
Si su aplicacin tiene muchas rutas RESTful, use :only y :except para generar slo las
rutas que realmente necesita puede reducir el uso de memoria y acelerar el proceso de
enrutamiento.
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'tooth', 'teeth'
end
431
4- Personalizacin de rutas de recursos
resources :magazines do
resources :ads, as: 'periodical_ads'
end
Video.find_by(identifier: params[:identifier])
432
5- Inspeccin y pruebas de las rutas
Ambos mtodos enumerarn todas sus rutas, en el mismo orden en que aparecen en
config/routes.rb . Para cada ruta, ver:
Por ejemplo, aqu hay una pequea seccin de las rutas de Rails de salida para una ruta
RESTful :
Puede buscar en sus rutas con la opcin grep: -g . Esto genera cualquier ruta que coincida
parcialmente con el nombre del mtodo de ayuda de URL, el verbo HTTP o la ruta de
acceso de URL.
Si slo desea ver las rutas que se asignan a un controlador especfico, existe la opcin -c .
433
5- Inspeccin y pruebas de las rutas
Usted encontrar que la salida de las rutas de Rails son mucho ms legibles si usted
ensancha su ventana terminal hasta que las lneas de la salida no envuelvan.
assert_generates
assert_recognizes
assert_routing
434
5- Inspeccin y pruebas de las rutas
435
XIII - Active Support Extensiones Core
Ofrece una lnea de fondo ms rica a nivel de idioma, dirigida tanto al desarrollo de
aplicaciones Rails, como al desarrollo de Ruby on Rails.
436
1- Cmo cargar las extensiones core
require 'active_support'
Para cada mtodo definido como una extensin del ncleo (core), esta gua tiene una nota
que indica dnde se define dicho mtodo. En el caso de blank? La nota dice:
Se define en active_support/core_ext/object/blank.rb.
require 'active_support'
require 'active_support/core_ext/object/blank'
Por lo tanto, para cargar todas las extensiones de objeto (incluyendo blank? ):
require 'active_support'
require 'active_support/core_ext/object'
437
1- Cmo cargar las extensiones core
require 'active_support'
require 'active_support/core_ext'
require 'active_support/all'
Que ni siquiera es necesario poner todo el active support en la memoria por adelantado, de
hecho algunas cosas se configuran a travs de la carga automtica, por lo que slo se
carga si se utiliza.
438
2- Extensiones a todos los objetos
nil y false ,
def set_conditional_cache_control!
return if self["Cache-Control"].present?
...
end
Se define en active_support/core_ext/object/blank.rb .
2.2 presence
439
2- Extensiones a todos los objetos
Se define en active_support/core_ext/object/blank.rb .
2.3 duplicable?
En Ruby 2.4 la mayora de los objetos pueden ser duplicados va dup o clone excepto los
mtodos y ciertos nmeros. Aunque Ruby 2.2 y 2.3 no pueden duplicar nil , false ,
true y smbolos, as como instancias de Float , Fixnum y Bignum .
As que en 2.4:
440
2- Extensiones a todos los objetos
2.4 deep_dup
El mtodo deep_dup devuelve una copia profunda de un objeto dado. Normalmente,
cuando se hace dup a un objeto que contiene otros objetos, Ruby no los duplica, por lo
que crea una copia poco profunda del objeto. Si tiene un array con una cadena, por
ejemplo, se ver as:
array = ['string']
duplicate = array.dup
duplicate.push 'another-string'
# the object was duplicated, so the element was added only to the duplicate
array # => ['string']
duplicate # => ['string', 'another-string']
duplicate.first.gsub!('string', 'foo')
Como se puede ver, despus de duplicar la instancia Array, tenemos otro objeto, por lo
tanto podemos modificarlo y el objeto original permanecer sin cambios. Sin embargo, esto
no es cierto para los elementos del array. Puesto que el dup no hace la copia profunda, la
secuencia dentro del arsenal sigue siendo el mismo objeto.
Si necesita una copia profunda de un objeto, debe utilizar deep_dup . Aqu hay un ejemplo:
441
2- Extensiones a todos los objetos
array = ['string']
duplicate = array.deep_dup
duplicate.first.gsub!('string', 'foo')
number = 1
duplicate = number.deep_dup
number.object_id == duplicate.object_id # => true
2.5 try
Cuando desea llamar a un mtodo en un objeto slo si no es nil , la forma ms sencilla de
lograrlo es con sentencias condicionales, aadiendo desorden innecesario. La alternativa es
usar try . try es como Object#send excepto que devuelve nil si se enva nil .
# without try
unless @number.nil?
@number.next
end
# with try
@number.try(:next)
innecesaria.
Esto es temario mas avanzado, donde voy a extender ciertas caracteristicas de rails
A corto plazo necesitamos mas informacion sobre otros temas avanzados pero mas
442
2- Extensiones a todos los objetos
443
XIV- API de Internacionalizacin de Rails (I18n)
Esta gua lo guiar a travs de la API I18n y contiene un tutorial sobre cmo
internacionalizar una aplicacin de Rails desde el principio.
444
XIV- API de Internacionalizacin de Rails (I18n)
445
1- Cmo funciona I18n en Ruby on Rails
Como parte de esta solucin, cada cadena esttica en el framework de Rails, por
ejemplo los mensajes de validacin de Active Record, y los formatos de fecha y hora, se
han internacionalizado . La localizacin (localization) de una aplicacin de Rails significa
La API pblica del framework i18n - un mdulo Ruby con mtodos pblicos que definen
cmo funciona la biblioteca
Un backend predeterminado (que se nombra intencionalmente Backend simple) que
implementa estos mtodos
Como usuario siempre debes acceder solo a los mtodos pblicos en el mdulo I18n, pero
es til conocer las capacidades del backend.
Estos tienen los alias #t y #l para que pueda utilizarlos de esta manera:
446
1- Cmo funciona I18n en Ruby on Rails
I18n.t 'store.title'
I18n.l Time.now
447
2- Configuracin de una aplicacin de Rails para la internacionalizacin
Rails aade todos los archivos .rb y .yml desde el directorio config/locales a la ruta
de carga de las traducciones, automticamente.
en:
hello: "Hello world"
Esto significa, que en el locale :en , la clave hello se asignar a la cadena Hello world.
Cada cadena dentro de Rails se internacionaliza de esta forma, consulte, por ejemplo, los
mensajes de validacin de Active Model en el archivo
activemodel/lib/active_model/locale/en.yml o los formatos de hora y fecha en el archivo
activesupport/lib/active_support/locale/en.yml . Puede usar YAML o el Ruby Hashes
estndar para almacenar las traducciones en el backend predeterminado (Simple).
448
2- Configuracin de una aplicacin de Rails para la internacionalizacin
Se debe especificar la ruta de carga antes de buscar las traducciones. Para cambiar la
configuracin regional predeterminada de un inicializador, se hace en
config/application.rb :
# config/initializers/locale.rb
449
2- Configuracin de una aplicacin de Rails para la internacionalizacin
Es probable que una aplicacin localizada necesite proporcionar soporte para varios
entornos locales. Para lograr esto, la configuracin regional se debe establecer al principio
de cada solicitud para que todas las cadenas se conviertan utilizando la configuracin
regional deseada durante la duracin de dicha solicitud.
before_action :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
Este ejemplo ilustra esto utilizando un parmetro de consulta URL para establecer el
entorno local (por ejemplo, http://example.com/books?locale=pt ). Con este enfoque,
http://localhost:3000?locale=pt renderiza la localizacin en portugus, mientras que
450
2- Configuracin de una aplicacin de Rails para la internacionalizacin
before_action :set_locale
def set_locale
I18n.locale = extract_locale_from_tld || I18n.default_locale
end
# Get locale from top-level domain or return +nil+ if such locale is not available
# You have to put something like:
# 127.0.0.1 application.com
# 127.0.0.1 application.it
# 127.0.0.1 application.pl
# in your /etc/hosts file to try this out locally
def extract_locale_from_tld
parsed_locale = request.host.split('.').last
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end
Si su aplicacin incluye un men para el cambio del locale , entonces tendra que hacer
algo como esto en el:
link_to("Deutsch", "#{APP_CONFIG[:deutsch_website_url]}#{request.env['PATH_INFO']}")
Esta solucin tiene las ventajas mencionadas, sin embargo, es posible que no pueda o no
desee proporcionar diferentes localizaciones ("versiones de idioma") en diferentes dominios.
La solucin ms obvia sera incluir el cdigo de configuracin regional en los parmetros de
URL (o ruta de peticin).
451
2- Configuracin de una aplicacin de Rails para la internacionalizacin
Rails contiene una infraestructura para "centralizar decisiones dinmicas sobre las URLs"
en su ApplicationController#default_url_options , lo cual es til precisamente en este
escenario: nos permite establecer "defaults" para url_for y los mtodos auxiliares
dependientes de l (mediante la implementacin o sobre-escritura de
default_url_options ).
# app/controllers/application_controller.rb
def default_url_options
{ locale: I18n.locale }
end
Cada mtodo helper dependiente de url_for (por ejemplo, ayudantes de rutas de nombre,
como root_path o root_url , rutas de resources como books_path o books_url , etc.)
ahora incluirn automticamente la configuracin regional en la cadena de consulta, de la
siguiente manera: http://localhost:3001?locale=ja .
Usted puede estar satisfecho con esto. Sin embargo, afecta a la legibilidad de las URL
cuando la configuracin regional se "pone" al final de cada URL de la aplicacin. Por otra
parte, desde el punto de vista arquitectnico, los locales suelen estar jerrquicamente por
encima de las otras partes del dominio de la aplicacin y las URL deben reflejar esto.
Es probable que desee que las URL se vean as: http://www.example.com/en/books (que
carga la configuracin regional en ingls) y http://www.example.com/nl/books (que carga la
configuracin regional holandesa) . Esto es posible con la estrategia de "over-riding
default_url_options " desde arriba: solo tienes que configurar tus rutas con el scope de
aplicacin:
452
2- Configuracin de una aplicacin de Rails para la internacionalizacin
# config/routes.rb
scope "/:locale" do
resources :books
end
Ahora, cuando llame al mtodo books_path , debe obtener " /en/books " (para la
configuracin regional predeterminada). Una URL como http://localhost:3001/nl/books
debe cargar la configuracin regional holandesa, y las siguientes llamadas a books_path
deben devolver " /nl/books " (porque cambi la configuracin regional).
Si no desea forzar el uso de una configuracin regional en sus rutas, puede utilizar un
mbito de ruta opcional (indicado por los parntesis) de la siguiente manera:
# config/routes.rb
scope "(:locale)", locale: /en|nl/ do
resources :books
end
Con este enfoque no obtendr un error de enrutamiento cuando acceda a sus recursos
como http://localhost:3001/books sin una configuracin regional. Esto es til si desea
utilizar la configuracin regional predeterminada cuando no se especifica.
Por supuesto, debe tener especial cuidado con la URL raz (generalmente "homepage" o
"dashboar") de su aplicacin. Una URL como http://localhost:3001/nl no funcionar
automticamente, porque la raz: " books#index " en la declaracin de routes.rb no toma el
locale en cuenta. (Y con razn: slo hay una URL " root ").
# config/routes.rb
get '/:locale' => 'dashboard#index'
Tenga especial cuidado con el orden de sus rutas, por lo que esta declaracin de ruta no
debe "comer" a los otros. (Es posible que desee aadirlo directamente antes de la
reclaracin a root )
453
2- Configuracin de una aplicacin de Rails para la internacionalizacin
Echa un vistazo a varias gemas que simplifican el trabajo con rutas: routing_filter, rails-
translate-routes, route_translator.
def set_locale
I18n.locale = current_user.try(:locale) || I18n.default_locale
end
def set_locale
logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"
I18n.locale = extract_locale_from_accept_language_header
logger.debug "* Locale set to '#{I18n.locale}'"
end
private
def extract_locale_from_accept_language_header
request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
end
454
2- Configuracin de una aplicacin de Rails para la internacionalizacin
La direccin IP del cliente que realiza la solicitud se puede utilizar para inferir la regin del
cliente y, por tanto, su entorno local. Servicios como GeoIP Lite Country o gemas como
geocoder pueden ser utilizados para implementar este enfoque.
En general, este enfoque es mucho menos fiable que el uso del encabezado de idioma y no
se recomienda para la mayora de las aplicaciones web.
455
3- Internacionalizacin y localizacin
3- Internacionalizacin y localizacin
Ok! Ahora ha inicializado la compatibilidad con I18n para su aplicacin de Ruby on Rails y
le ha indicado qu idioma usar y cmo preservarla entre las solicitudes.
# config/routes.rb
Rails.application.routes.draw do
root to: "home#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
end
# app/controllers/home_controller.rb
class HomeController < ApplicationController
def index
flash[:notice] = "Hello Flash"
end
end
# app/views/home/index.html.erb
<h1>Hello World</h1>
<p><%= flash[:notice] %></p>
456
3- Internacionalizacin y localizacin
# app/controllers/home_controller.rb
class HomeController < ApplicationController
def index
flash[:notice] = t(:hello_flash)
end
end
# app/views/home/index.html.erb
<h1><%=t :hello_world %></h1>
<p><%= flash[:notice] %></p>
Ahora, cuando se muestre esta vista, mostrar un mensaje de error que indica que faltan
las traducciones de las claves :hello_world y :hello_flash .
457
3- Internacionalizacin y localizacin
Rails aade un mtodo auxiliar t (translate) a sus vistas de modo que no necesite
deletrear I18n.t todo el tiempo. Adems, este ayudante capturar las traducciones
perdidas y envolver el mensaje de error resultante en un <span class =
"translation_missing"> .
# config/locales/en.yml
en:
hello_world: Hello world!
hello_flash: Hello flash!
# config/locales/pirate.yml
pirate:
hello_world: Ahoy World
hello_flash: Ahoy Flash
458
3- Internacionalizacin y localizacin
Puede utilizar archivos YAML ( .yml ) o Ruby ( .rb ) para almacenar sus traducciones en
SimpleStore. YAML es la opcin preferida entre los desarrolladores de Rails. Sin embargo,
tiene una gran desventaja. YAML es muy sensible a espacios en blanco y caracteres
especiales, por lo que la aplicacin no puede cargar su diccionario correctamente. Los
archivos Ruby bloquearn su aplicacin en la primera solicitud, por lo que puede encontrar
fcilmente lo que est mal. (Si encuentra algn "problema extrao" con los diccionarios
YAML, intente colocar la parte relevante de su diccionario en un archivo Ruby).
Si sus traducciones se almacenan en archivos YAML, ciertas claves deben escaparse. Son:
Ejemplos:
# config/locales/en.yml
en:
success:
'true': 'True!'
'on': 'On!'
'false': 'False!'
failure:
true: 'True!'
off: 'Off!'
false: 'False!'
459
3- Internacionalizacin y localizacin
# app/views/products/show.html.erb
<%= "#{t('currency')}#{@product.price}" %>
# config/locales/en.yml
en:
currency: "$"
# config/locales/es.yml
es:
currency: ""
Para crear una abstraccin adecuada, la gema I18n viene con una funcin llamada
interpolacin de variables que le permite utilizar variables en las definiciones de traduccin y
pasar los valores de estas variables al mtodo de traduccin.
# app/views/products/show.html.erb
<%= t('product_price', price: @product.price) %>
# config/locales/en.yml
en:
product_price: "$%{price}"
# config/locales/es.yml
es:
product_price: "%{price} "
460
3- Internacionalizacin y localizacin
Ok! Ahora vamos a agregar una marca de tiempo a la vista, por lo que tambin puede
mostrar la funcin de localizacin de fecha y hora. Para localizar el formato de hora, pasa el
objeto Time a I18n.l o (preferiblemente) usa el ayudante #l de Rails. Puede elegir un
formato pasando la opcin :format - por defecto se usa el formato :default .
# app/views/home/index.html.erb
<h1><%=t :hello_world %></h1>
<p><%= flash[:notice] %></p>
<p><%= l Time.now, format: :short %></p>
Y en nuestro archivo de traducciones piratas vamos a aadir un formato de hora (ya est
ah en los valores predeterminados de Rails en el ingls):
# config/locales/pirate.yml
pirate:
time:
formats:
short: "arrrround %H'ish"
En este caso puede que tenga que agregar algunos formatos ms de fecha/hora para
hacer que el backend I18n funcione como se esperaba (al menos para el escenario
"pirata"). Por supuesto, hay una gran posibilidad de que alguien ya haya hecho todo el
trabajo al traducir los valores predeterminados de Rails para su entorno. Consulte el
repositorio rails-i18n en GitHub para obtener un archivo de varios archivos de
configuracin regional. Cuando pones tal archivo(s) en el directorio config/locales/ ,
automticamente estarn listos para su uso.
461
3- Internacionalizacin y localizacin
predeterminado para especificar reglas adicionales para el ingls; Siga ese formato para
otras configuraciones regionales como mejor le parezca.
Puede utilizar esta funcin por ejemplo, cuando se trabaja con una gran cantidad de
contenido esttico, lo que sera torpe para poner dentro de los diccionarios YAML o Ruby.
Tenga en cuenta, sin embargo, que cualquier cambio que le gustara hacer ms tarde a la
plantilla debe propagarse a todos ellos.
462
3- Internacionalizacin y localizacin
|-defaults
|---es.rb
|---en.rb
|-models
|---book
|-----es.rb
|-----en.rb
|-views
|---defaults
|-----es.rb
|-----en.rb
|---books
|-----es.rb
|-----en.rb
|---users
|-----es.rb
|-----en.rb
|---navigation
|-----es.rb
|-----en.rb
De esta manera, puede separar los nombres de los atributos del modelo y el modelo de
texto dentro de vistas, y todo esto de los "valores por defecto" (por ejemplo, formatos de
fecha y hora). Otras stores para la biblioteca i18n podran proporcionar diferentes medios
para tal separacin.
# config/application.rb
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
463
4- Descripcin general de las funciones de la API I18n
Buscar traducciones
Interpolando datos en traducciones
Traducciones pluralizadas
Usando traducciones seguras de HTML (solo ver el mtodo auxiliar)
Localizacin de fechas, nmeros, moneda, etc.
I18n.t :message
I18n.t 'message'
El mtodo de traduccin tambin tiene una opcin :scope que puede contener una o ms
claves adicionales que se utilizarn para especificar un "espacio de nombres" o el alcance
para una clave de la traduccin:
Adems, tanto la clave como los mbitos pueden especificarse como claves separadas por
puntos como en:
464
4- Descripcin general de las funciones de la API I18n
I18n.translate "activerecord.errors.messages.record_invalid"
I18n.t 'activerecord.errors.messages.record_invalid'
I18n.t 'errors.messages.record_invalid', scope: :activerecord
I18n.t :record_invalid, scope: 'activerecord.errors.messages'
I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]
4.1.2 Default
devuelta:
Para buscar mltiples traducciones a la vez, se puede pasar una matriz de claves:
I18n.t 'activerecord.errors.messages'
# => {:inclusion=>"is not included in the list", :exclusion=> ... }
465
4- Descripcin general de las funciones de la API I18n
Rails implementa una forma conveniente de buscar la ubicacin dentro de las vistas.
Cuando tenga el siguiente diccionario:
es:
books:
index:
title: "Ttulo"
en:
books:
create:
success: Book created!
4.2 Pluralizacin
En ingls hay slo una forma singular y una plural para una cadena dada, por ejemplo. "1
mensaje" y "2 mensajes". Otros idiomas (rabe, japons, ruso y muchos ms) tienen
diferentes gramticas que tienen formas plurales adicionales o menos. Por lo tanto, la I18n
API proporciona una funcionalidad flexible de pluralizacin.
466
4- Descripcin general de las funciones de la API I18n
La traduccin denotada como :one se considera singular, y el otro se usa como plural. Si
el recuento es cero y una entrada cero est presente, entonces se utilizar :other en su
lugar.
I18n.locale = :de
I18n.t :foo
I18n.l Time.now
I18n.default_locale = :de
467
4- Descripcin general de las funciones de la API I18n
Las claves con un sufijo ' _html ' y las claves denominadas 'html' estn marcadas como
seguras para HTML. Cuando los uses en las vistas, el cdigo HTML no se escapar.
# config/locales/en.yml
en:
welcome: <b>welcome!</b>
hello_html: <b>hello!</b>
title:
html: <b>title!</b>
# app/views/home/index.html.erb
<div><%= t('welcome') %></div>
<div><%= raw t('welcome') %></div>
<div><%= t('hello_html') %></div>
<div><%= t('title.html') %></div>
Sin embargo, la interpolacin se escapa segn sea necesario. Por ejemplo, dado:
en:
welcome_html: "<b>Welcome %{username}!</b>"
Puede pasar con seguridad el nombre de usuario segn lo establecido por el usuario:
468
4- Descripcin general de las funciones de la API I18n
en:
activerecord:
models:
user: Dude
attributes:
user:
login: "Handle"
# will translate User attribute "login" as "Handle"
Tambin puede establecer una forma plural para los nombres de los modelos, agregandolos
como sigue:
en:
activerecord:
models:
user:
one: Dude
other: Dudes
en:
activerecord:
attributes:
user/gender:
female: "Female"
male: "Male"
anteriores.
469
4- Descripcin general de las funciones de la API I18n
Esto le da medios muy poderosos para ajustar con flexibilidad sus mensajes a las
necesidades de su aplicacin.
Considere un modelo de usuario con una validacin para el atributo de nombre como este:
La clave para el mensaje de error en este caso es :blank . Active Record buscar esta
clave en los espacios de nombres:
activerecord.errors.models.[model_name].attributes.[attribute_name]
activerecord.errors.models.[model_name]
activerecord.errors.messages
errors.attributes.[attribute_name]
errors.messages
As, en nuestro ejemplo probar las siguientes claves en este orden y devolver el primer
resultado:
activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank
Cuando sus modelos tambin estn usando la herencia entonces los mensajes se buscan
en la cadena de herencia.
470
4- Descripcin general de las funciones de la API I18n
activerecord.errors.models.admin.attributes.name.blank
activerecord.errors.models.admin.blank
activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
errors.messages.blank
De esta manera, puede proporcionar traducciones especiales para varios mensajes de error
en diferentes puntos de la cadena de herencia de los modelos y en los atributos, modelos o
mbitos predeterminados.
Por ejemplo, en lugar del mensaje de error predeterminado "cannot be blank", puede utilizar
el nombre de atributo como este: "Please fill in your %{attribute}".
471
4- Descripcin general de las funciones de la API I18n
absence - :present -
length :within, :in :too_short count
length :within, :in :too_long count
length :is :wrong_length count
associated - :invalid -
non-optional
- :required -
association
numericality - :not_a_number -
numericality :greater_than :greater_than count
numericality :greater_than_or_equal_to :greater_than_or_equal_to count
472
4- Descripcin general de las funciones de la API I18n
en:
activerecord:
errors:
template:
header:
one: "1 error prohibited this %{model} from being saved"
other: "%{count} errors prohibited this %{model} from being saved"
body: "There were problems with the following fields:"
Para usar este ayudante, debe instalar la gema DynamicForm aadiendo esta lnea a su
Gemfile: gem 'dynamic_form' .
# user_mailer.rb
class UserMailer < ActionMailer::Base
def welcome(user)
#...
end
end
en:
user_mailer:
welcome:
subject: "Welcome to Rails Guides!"
# user_mailer.rb
class UserMailer < ActionMailer::Base
def welcome(user)
mail(to: user.email, subject: default_i18n_subject(user: user.name))
end
end
en:
user_mailer:
welcome:
subject: "%{user}, welcome to Rails Guides!"
473
4- Descripcin general de las funciones de la API I18n
usando un separador que se buscar desde errors.format (y que por defecto es " %
{attribute} %{message} ").
474
5- Cmo almacenar sus traducciones personalizadas
Por ejemplo, un Ruby Hash que proporciona traducciones puede verse as:
{
pt: {
foo: {
bar: "baz"
}
}
}
pt:
foo:
bar: baz
Como puede ver, en ambos casos la clave de nivel superior es la configuracin regional.
:foo es una clave de espacio de nombres y :bar es la clave para la traduccin " baz ".
Este es un ejemplo "real" del archivo YAML de Active Support en.yml translations:
en:
date:
formats:
default: "%Y-%m-%d"
short: "%b %d"
long: "%B %d, %Y"
Por lo tanto, todas las siguientes consultas equivalentes devolvern el formato de fecha
:short " %b %d ":
I18n.t 'date.formats.short'
I18n.t 'formats.short', scope: :date
I18n.t :short, scope: 'date.formats'
I18n.t :short, scope: [:date, :formats]
475
5- Cmo almacenar sus traducciones personalizadas
Por lo general, recomendamos usar YAML como un formato para almacenar las
traducciones. Hay casos, sin embargo, donde desea almacenar lambdas de Ruby como
parte de sus datos de configuracin regional, por ejemplo para formatos de fechas
especiales.
476
6- Personaliza tu configuracin de I18n
Sin embargo, eso no significa que est atrapado con estas limitaciones. La gema Ruby I18n
hace que sea muy fcil intercambiar la implementacin simple de backend con algo ms
que se adapte mejor a sus necesidades. P.ej. Usted podra intercambiarlo con el backend
esttico de Globalize:
I18n.backend = Globalize::Backend::Static.new
Tambin puede utilizar el backend de cadena para encadenar mltiples backends juntos.
Esto es til cuando se desea usar traducciones estndar con un backend simple, pero
almacenar traducciones de aplicaciones personalizadas en una base de datos u otros
backends. Por ejemplo, puede utilizar el backend de Active Record y volver al backend
simple (por defecto):
477
6- Personaliza tu configuracin de I18n
La API I18n captura todas estas excepciones cuando se lanzan en el backend y las pasan
al mtodo default_exception_handler . Este mtodo volver a aumentar todas las
excepciones, excepto las excepciones de MissingTranslationData . Cuando se ha detectado
una excepcin MissingTranslationData , devolver la cadena de mensaje de error de la
excepcin que contiene la clave o el mbito que faltan.
La razn de esto es que durante el desarrollo en el que normalmente desea que sus vistas
se usen a pesar de que falte una traduccin.
Sin embargo, en otros contextos puede que desee cambiar este comportamiento. P.ej. La
manipulacin de excepciones por defecto no permite capturar fcilmente las traducciones
perdidas durante las pruebas automatizadas. Para este propsito se puede especificar un
manejador de excepciones diferente. El manejador de excepciones especificado debe ser
un mtodo en el mdulo I18n o una clase con el mtodo #call :
module I18n
class JustRaiseExceptionHandler < ExceptionHandler
def call(exception, locale, key, options)
if exception.is_a?(MissingTranslationData)
raise exception.to_exception
else
super
end
end
end
end
I18n.exception_handler = I18n::JustRaiseExceptionHandler.new
pluralizacin por defecto para el idioma Ingls . Para evitar esto, puede usar un chequeo
adicional para la clave de traduccin:
478
6- Personaliza tu configuracin de I18n
I18n.t :foo, raise: true # always re-raises exceptions from the backend
479
XV- Fundamentos de Action Mailer
480
1- Introduccin
1- Introduccin
Action Mailer le permite enviar mensajes de correo electrnico desde su aplicacin usando
clases de mailer y vistas. Los mailers trabajan muy similar a los controladores. Ellos
heredan de ActionMailer::Base y viven en app/mailers , y tienen vistas asociadas que
aparecen en app/views .
481
2- Envo de mensajes de correo electrnico
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
default from: "[email protected]"
layout 'mailer'
end
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
end
Como puede ver, puede generar correos electrnicos como si utilizara otros generadores
con Rails. Los mailers son conceptualmente similares a los controladores, y as recibimos
un mailer, un directorio para vistas y uno para pruebas.
482
2- Envo de mensajes de correo electrnico
Los mailers son muy similares a los controladores de Rails. Tambin tienen mtodos
llamados "acciones" y usan vistas para estructurar el contenido. Cuando un controlador
genera contenido como HTML para enviar de vuelta al cliente, un Mailer crea un mensaje
para ser entregado por correo electrnico.
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
mail(to: @user.email, subject: 'Welcome to My Awesome Site')
end
end
Aqu hay una explicacin rpida de los elementos presentados en el mtodo anterior. Para
obtener una lista completa de todas las opciones disponibles, por favor, eche un vistazo
ms abajo en la lista completa de Action Mailer user-settable atributos de seccin.
Al igual que los controladores, cualquier variable de instancia que definamos en el mtodo
estar disponible para su uso en las vistas.
483
2- Envo de mensajes de correo electrnico
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1>Welcome to example.com, <%= @user.name %></h1>
<p>
You have successfully signed up to example.com,
your username is: <%= @user.login %>.<br>
</p>
<p>
To login to the site, just follow this link: <%= @url %>.
</p>
<p>Thanks for joining and have a great day!</p>
</body>
</html>
Hagamos tambin una parte de texto para este correo electrnico. No todos los clientes
prefieren los correos electrnicos HTML, por lo que el envo de ambos es la mejor prctica.
Para ello, cree un archivo denominado welcome_email.text.erb en app/views/user_mailer/ :
To login to the site, just follow this link: <%= @url %>.
Cuando llame al mtodo de correo ahora, Action Mailer detectar las dos plantillas (texto y
HTML) y generar automticamente un correo electrnico de varias multipart/alternative .
484
2- Envo de mensajes de correo electrnico
Ahora que tenemos un modelo de usuario con el que jugar, solo editaremos
app/controllers/users_controller.rb para que instruya al UserMailer a entregar un correo
electrnico al usuario recin creado editando la accin create e insertando una llamada a
UserMailer.welcome_email Justo despus de que el usuario se guarde correctamente.
Action Mailer est muy bien integrado con Active Job para que pueda enviar correos
electrnicos fuera del ciclo de solicitud y respuesta, por lo que el usuario no tiene que
esperar:
respond_to do |format|
if @user.save
# Tell the UserMailer to send a welcome email after save
UserMailer.welcome_email(@user).deliver_later
Si quieres enviar correos electrnicos de inmediato (de un cronjob por ejemplo) slo tienes
que llamar a deliver_now :
485
2- Envo de mensajes de correo electrnico
class SendWeeklySummary
def run
User.find_each do |user|
UserMailer.weekly_summary(user).deliver_now
end
end
end
desea inspeccionar, alterar o hacer cualquier otra cosa con el objeto Mail::Message puede
acceder a l con el mtodo de mensaje en el objeto ActionMailer::MessageDelivery .
Pase el nombre y el contenido del archivo y Action Mailer y la gema mail automticamente
adivinarn el tipo mime, establecern la codificacin y crearn el archivo adjunto.
486
2- Envo de mensajes de correo electrnico
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
Cuando se active el mtodo de mail, enviar un correo electrnico multipart con un archivo
adjunto, correctamente anidado con el nivel superior que es multipart/mixed y la primera
parte es una multipart/alternative que contiene el texto sin formato y mensajes de correo
electrnico HTML.
Pase el nombre del archivo y especifique los encabezados y el contenido, y Action Mailer
and Mail usar la configuracin que le pase.
encoded_content = SpecialEncode(File.read('/path/to/filename.jpg'))
attachments['filename.jpg'] = {
mime_type: 'application/x-gzip',
encoding: 'SpecialEncoding',
content: encoded_content
}
Primero, para decirle a Mail que convierta un archivo adjunto en un archivo adjunto inline,
simplemente llame a #inline en el mtodo de archivos adjuntos dentro de su Mailer:
def welcome
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
end
A continuacin, en sus vistas, slo puede hacer referencia a los archivos adjuntos como un
hash y especificar qu adjunto desea mostrar, llamando a la url y luego pasando el
resultado al mtodo image_tag :
487
2- Envo de mensajes de correo electrnico
Como se trata de una llamada estndar a image_tag , puedes pasar un hash de opciones
despus de la URL del attachment como lo haras para cualquier otra imagen:
def new_registration(user)
@user = user
mail(subject: "New User Signup: #{@user.email}")
end
end
El mismo formato se puede utilizar para establecer "Con copia" (Cc :) y oculto (Bcc :),
utilizando las llaves :cc y :bcc respectivamente.
def welcome_email(user)
@user = user
email_with_name = %("#{@user.name}" <#{@user.email}>)
mail(to: email_with_name, subject: 'Welcome to My Awesome Site')
end
488
2- Envo de mensajes de correo electrnico
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
mail(to: @user.email,
subject: 'Welcome to My Awesome Site',
template_path: 'notifications',
template_name: 'another')
end
end
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
mail(to: @user.email,
subject: 'Welcome to My Awesome Site') do |format|
format.html { render 'another_template' }
format.text { render text: 'Render text' }
end
end
end
Esto har que la plantilla 'another_template.html.erb ' para la parte HTML y utilice el texto
representado para la parte de texto. El comando render es el mismo utilizado dentro de
Action Controller, por lo que puede utilizar todas las mismas opciones, tales como :text ,
:inline etc.
489
2- Envo de mensajes de correo electrnico
Y para poder utilizar esta funcin, necesitas configurar tu aplicacin con esto:
config.action_mailer.perform_caching = true
Al igual que con las vistas del controlador, utilice yield para representar la vista dentro del
layout.
Tambin puede pasar una opcin de layout: ' layout_name ' a la llamada de render dentro
del bloque de formato para especificar diferentes layouts para diferentes formatos:
490
2- Envo de mensajes de correo electrnico
Las previsualizaciones de Action Mailer proporcionan una forma de ver cmo se ven los
correos electrnicos visitando una URL especial que los procesa. En el ejemplo anterior, la
clase de vista previa para UserMailer debe llamarse UserMailerPreview y se encuentra en
test/mailers/previews/user_mailer_preview.rb . Para ver la vista previa de welcome_email ,
config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews"
Debido a este comportamiento no puede utilizar ninguno de los helpers *_path dentro de
un correo electrnico. En su lugar, necesitar utilizar el auxiliar asociado *_url . Por
ejemplo, en lugar de usar
491
2- Envo de mensajes de correo electrnico
Al usar la URL completa, sus vnculos funcionarn ahora en sus correos electrnicos.
config.action_mailer.asset_host = 'http://example.com'
492
2- Envo de mensajes de correo electrnico
Mailer enviar automticamente un correo electrnico multipart con las versiones de texto
HTML y texto como multipart.
El orden de las piezas que se insertan es determinado por el :parts_order dentro del
mtodo ActionMailer::Base.default .
493
2- Envo de mensajes de correo electrnico
494
3- Recibir correos electrnicos
Una vez que el mtodo receieve es llamado se define en cualquier mailer, Action Mailer
analizar el correo electrnico entrante sin procesar en un objeto, lo decodifica, lo instancia
en un nuevo mailer y pasa el objeto de mail al mtodo de la instancia de receieve del
cliente. He aqu un ejemplo:
if email.has_attachments?
email.attachments.each do |attachment|
page.attachments.create({
file: attachment,
description: email.subject
})
end
end
end
end
495
4- Action Mailer Callbacks
496
4- Action Mailer Callbacks
private
def set_delivery_options
# You have access to the mail instance,
# @business and @user instance variables here
if @business && @business.has_smtp_settings?
mail.delivery_method.settings.merge!(@business.smtp_settings)
end
end
def prevent_delivery_to_guests
if @user && @user.guest?
mail.perform_deliveries = false
end
end
def set_business_headers
if @business
headers["X-SMTPAPI-CATEGORY"] = @business.code
end
end
end
497
5- Uso de Helpers de Action Mailer
498
6- Configuracin de Action Mailer
Configuracin Descripcin
Genera informacin sobre la ejecucin del correo si est
logger
disponible. Se puede establecer en nil para no registrar.
Compatible con los registradores Logger y Log4r propios de
Ruby..
Allows detailed configuration for :smtp delivery
method: :address - Allows you to use a remote mail server.
Just change it from its default "localhost" setting. :port -
On the off chance that your mail server doesn't run on port
25, you can change it. :domain - If you need to specify a
HELO domain, you can do it here. :user_name - If your mail
server requires authentication, set the username in this
setting. :password - If your mail server requires
authentication, set the password in this
setting. :authentication - If your mail server requires
authentication, you need to specify the authentication type
smtp_settings
here. This is a symbol and one of :plain (will send the
password in the clear), :login (will send password Base64
encoded) or :cram_md5 (combines a Challenge/Response
mechanism to exchange information and a cryptographic
Message Digest 5 algorithm to hash important
information) :enable_starttls_auto - Detects if STARTTLS is
enabled in your SMTP server and starts to use it. Defaults
to true . :openssl_verify_mode - When using TLS, you can
set how OpenSSL checks the certificate. This is really useful
if you need to validate a self-signed and/or a wildcard
certificate. You can use the name of an OpenSSL verify
constant ('none' or 'peer') or directly the constant
( OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER ).
499
6- Configuracin de Action Mailer
default_options
Allows you to set default values for the mail method options
( :from , :reply_to , etc.).
config.action_mailer.delivery_method = :sendmail
# Defaults to:
# config.action_mailer.sendmail_settings = {
# location: '/usr/sbin/sendmail',
# arguments: '-i'
# }
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_options = {from: '[email protected]'}
500
6- Configuracin de Action Mailer
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
domain: 'example.com',
user_name: '<username>',
password: '<password>',
authentication: 'plain',
enable_starttls_auto: true }
Nota: A partir del 15 de julio de 2014, Google aument sus medidas de seguridad y ahora
bloquea los intentos de las aplicaciones que considera poco seguras. Puedes cambiar la
configuracin de Gmail aqu para permitir los intentos. Si su cuenta de Gmail tiene
habilitada la autenticacin de dos factores, deber establecer una contrasea de aplicacin
y usarla en lugar de su contrasea normal. Alternativamente, puede usar otro ESP para
enviar correo electrnico reemplazando ' smtp.gmail.com ' con la direccin de su proveedor.
501
7- Mailer Testing
7- Mailer Testing
Puede encontrar instrucciones detalladas sobre cmo probar sus correos en la gua de
pruebas.
502
8- Intercepcin de correos electrnicos
class SandboxEmailInterceptor
def self.delivering_email(message)
message.to = ['[email protected]']
end
end
Antes de que el interceptor pueda hacer su trabajo, necesita registrarlo con el framework de
Action Mailer. Puede hacerlo en un archivo de
inicializacin config/initializers/sandbox_email_interceptor.rb
if Rails.env.staging?
ActionMailer::Base.register_interceptor(SandboxEmailInterceptor)
end
503
XVI - Conceptos bsicos de Active Jobs
504
1- Introduccin
1- Introduccin
Active Jobs es un framework para declarar trabajos y hacer que funcionen en una variedad
de backends en cola. Estos trabajos pueden ser desde limpiezas programadas
regularmente, hasta cargos de facturacin, hasta envos por correo. Cualquier cosa que
pueda ser cortada en pequeas unidades de trabajo y correr en paralelo, en realidad.
505
2- El Propsito de Active Jobs
Rails viene de forma predeterminada con una implementacin de cola asncrona que
ejecuta trabajos con un grupo de subprocesos en proceso. Los trabajos se ejecutarn
de forma asncrona, pero cualquier trabajo de la cola se eliminar al reiniciar.
506
3- Creacin de un Job
3- Creacin de un Job
Esta seccin proporcionar una gua paso a paso para crear un job y ponerlo en cola.
Si no desea utilizar un generador, puede crear su propio archivo dentro de la app/ trabajos,
slo asegrese de que hereda de ApplicationJob .
As es como se ve un job:
def perform(*guests)
# Do something later
end
end
Tenga en cuenta que puede definir perform con tantos argumentos como desee.
# Encolara un job que se realizar tan pronto como el sistema de colas este libre
GuestsCleanupJob.perform_later guest
507
3- Creacin de un Job
Eso es todo!
508
4- Ejecucin del Job
4.1 Backends
Active Job tiene adaptadores integrados para mltiples backups de cola (Sidekiq, Resque,
Delayed Job y otros). Para obtener una lista actualizada de los adaptadores, consulte la
documentacin de la API para ActiveJob::QueueAdapters .
# config/application.rb
module YourApp
class Application < Rails::Application
# Asegrate de tener la gema del adaptador en tu Gemfile
# y siga la instalacin especfica del adaptador
# y las instrucciones de implementacin.
config.active_job.queue_adapter = :sidekiq
end
end
# Ahora su job utilizar `resque` ya que es el adaptador de cola de backend que sobre-
escribe lo que
# se ha configurado en `config.active_job.queue_adapter`.
509
4- Ejecucin del Job
Sidekiq
Resque
Sucker Punch
Queue Classic
510
5- Colas
5- Colas
La mayora de los adaptadores admiten varias colas. Con Active Job puede programar el
trabajo para que se ejecute en una cola especfica:
# config/application.rb
module YourApp
class Application < Rails::Application
config.active_job.queue_name_prefix = Rails.env
end
end
# app/jobs/guests_cleanup_job.rb
class GuestsCleanupJob < ApplicationJob
queue_as :low_priority
#....
end
El delimitador de prefijo de nombre de cola predeterminado es ' _ '. Esto se puede cambiar
configurando config.active_job.queue_name_delimiter en application.rb :
511
5- Colas
# config/application.rb
module YourApp
class Application < Rails::Application
config.active_job.queue_name_prefix = Rails.env
config.active_job.queue_name_delimiter = '.'
end
end
# app/jobs/guests_cleanup_job.rb
class GuestsCleanupJob < ApplicationJob
queue_as :low_priority
#....
end
Si desea ms control sobre en qu cola se ejecutar un trabajo, puede pasar una opcin
:queue a :#set :
MyJob.set(queue: :another_queue).perform_later(record)
Para controlar la cola desde el nivel del job, puede pasar un bloque a #queue_as . El bloque
se ejecutar en el contexto del job (para poder acceder a self.arguments ) y debe devolver
el nombre de la cola:
def perform(video)
# Do process video
end
end
ProcessVideoJob.perform_later(Video.last)
512
5- Colas
513
6- Callbacks
6- Callbacks
Trabajo activo proporciona hooks durante el ciclo de vida de un job. Las devoluciones de
llamada le permiten activar la lgica durante el ciclo de vida de un trabajo.
around_enqueue
after_enqueue
before_perform
around_perform
after_perform
6.2 Uso
before_enqueue do |job|
# Do something with the job instance
end
def perform
# Do something later
end
end
514
7- Action Mailer
7- Action Mailer
Uno de los trabajos ms comunes en una aplicacin web moderna es el envo de correos
electrnicos fuera del ciclo de solicitud y respuesta, por lo que el usuario no tiene que
esperar. Active Job se integra con Action Mailer para que pueda enviar correos electrnicos
de manera asincrnica:
# Si desea enviar el correo electrnico a travs del active job use #deliver_later
UserMailer.welcome(@user).deliver_later
515
8- Internacionalizacin
8- Internacionalizacin
Cada job utiliza el conjunto I18n.locale cuando se crea el trabajo. Es til si enva
mensajes de correo electrnico de forma asncrona:
I18n.locale = :eo
516
9- GlobalID
9- GlobalID
Active Job admite GlobalID para los parmetros. Esto hace posible pasar los objetos vivos
de Active Record a su job en vez de los pares de class/id, que entonces usted tendra que
deserializar manualmente. Antes, los jobs se vean as:
Esto funciona con cualquier clase que se mezcla en GlobalID::Identification , que por
defecto se ha mezclado en las clases Active Record.
517
10- Excepciones
10- Excepciones
Active Job proporciona una forma de detectar excepciones generadas durante la ejecucin
del job:
rescue_from(ActiveRecord::RecordNotFound) do |exception|
# Do something with the exception
end
def perform
# Do something later
end
end
10.1 Deserializacin
GlobalID permite serializar los objetos Active Record completos pasados a #perform .
Si se elimina un registro pasado despus de que se encola el job pero antes de que el
mtodo #perform es llamado , Active Job generar una excepcin
ActiveJob::DeserializationError .
518
11- Job Testing
519
XVII - Testing de aplicaciones Rails
520
1- Por qu escribir pruebas para sus aplicaciones Rails?
Las pruebas de Rails tambin pueden simular solicitudes de navegador y, por tanto, puede
probar la respuesta de su aplicacin sin tener que probarla a travs de su navegador.
521
2- Introduccin a las pruebas
$ ls -F test
controllers/ helpers/
mailers/ system/ test_helper.rb
fixtures/ integration/
models/ application_system_test_case.rb
Los helpers, los mailers y los directorios de los modelos estn destinados a realizar pruebas
para los ayudantes de la vista, los mailers y los modelos, respectivamente. El directorio de
controladores est destinado a realizar pruebas para controladores, rutas y vistas. El
directorio de integracin est destinado a realizar pruebas de interacciones entre
controladores.
El directorio de prueba del sistema contiene pruebas del sistema, que se utilizan para la
prueba completa del navegador de su aplicacin. Las pruebas del sistema le permiten
probar su aplicacin de la misma manera que sus usuarios la experimentan y tambin
ayudarle a probar su JavaScript. Las pruebas del sistema heredan de Capybara y realizan
pruebas de navegador para su aplicacin.
Los fixtures son una manera de organizar los datos de la prueba; Residen en el directorio
fixtures .
522
2- Introduccin a las pruebas
require 'test_helper'
Un examen lnea por lnea de este archivo le ayudar a orientarlo a las pruebas cdigo con
Rails y la terminologa.
require 'test_helper'
523
2- Introduccin a las pruebas
nos brinda.
Rails tambin agrega un mtodo de prueba que toma un nombre de test y un bloque.
Genera una prueba normal de Minitest::Unit con nombres de mtodos prefijados con
test_ . As que no tienes que preocuparte por nombrar los mtodos, y puedes escribir algo
como:
def test_the_truth
assert true
end
assert true
Una asercin es una lnea de cdigo que evala un objeto (o expresin) para los resultados
esperados. Por ejemplo, una asercin puede comprobar:
524
2- Introduccin a las pruebas
Cada prueba puede contener una o ms aserciones, sin restriccin en cuanto a cuntas
aserciones se permiten. Slo cuando todas las aserciones sean exitosas, la prueba pasar.
Vamos a ejecutar esta prueba recin agregada (donde 6 es el nmero de lnea donde se
define la prueba).
# Running:
Failure:
ArticleTest#test_should_not_save_article_without_title [/path/to/blog/test/models/arti
cle_test.rb:6]:
Expected true to be nil or false
525
2- Introduccin a las pruebas
suficiente informacin para ayudar a identificar el error. Para que el mensaje de fallo de
asercin sea ms legible, cada asercin proporciona un parmetro de mensaje opcional,
como se muestra aqu:
Failure:
ArticleTest#test_should_not_save_article_without_title [/path/to/blog/test/models/arti
cle_test.rb:6]:
Saved the article without a title
Ahora para pasar esta prueba podemos agregar una validacin de nivel de modelo para el
campo de ttulo.
# Running:
Ahora, si te fijaste, primero escribimos una prueba que falla para una funcionalidad
deseada, luego escribimos algn cdigo que agrega la funcionalidad y finalmente nos
aseguramos de que nuestra prueba pase. Este enfoque para el desarrollo de software se
conoce como Test-Driven Development (TDD).
526
2- Introduccin a las pruebas
# Running:
.E
Error:
ArticleTest#test_should_report_error:
NameError: undefined local variable or method 'some_undefined_variable' for #<ArticleT
est:0x007fee3aa71798>
test/models/article_test.rb:11:in 'block in <class:ArticleTest>'
pruebas.
527
2- Introduccin a las pruebas
Si queremos que pase esta prueba, podemos modificarla para usar assert_raises as:
He aqu un extracto de las aserciones que puede utilizar con Minitest, la biblioteca de
pruebas predeterminada utilizada por Rails. El parmetro [msg] es un mensaje de cadena
opcional que puede especificar para que los mensajes de error de prueba sean ms claros.
Assertion Purpose
assert( test, [msg] ) Se asegura que test es true.
assert_not( test, [msg] ) Ensures that test es false.
assert_equal( expected,
actual, [msg] ) Se asegura que expected == actual es true.
assert_not_equal( expected,
actual, [msg] ) Se asegura que expected != actual es true.
assert_same( expected,
actual, [msg] ) Se asegura que expected.equal?(actual) es true.
assert_not_same( expected,
actual, [msg] ) Se asegura que expected.equal?(actual) es false.
528
2- Introduccin a las pruebas
assert_not_includes(
collection, obj, [msg] ) Se asegura que obj no esta en collection .
assert_in_delta( expected, Se asegura que los numeros expected and actual are
actual, [delta], [msg] ) within delta of each other.
assert_not_in_delta(
expected, actual, [delta],
Se asegura que the numbers expected and actual are
[msg] ) not within delta of each other.
assert_throws( symbol,
[msg] ) { block } Se asegura que el bloque dado lanza un simbolo
assert_operator( obj1,
operator, [obj2], [msg] ) Se asegura que obj1.operator(obj2) es true.
assert_not_operator( obj1,
operator, [obj2], [msg] ) Se asegura que obj1.operator(obj2) es false.
flunk( [msg] )
Se asegura que sea failure. Esto es til para marcar
explcitamente una prueba que an no ha terminado.
Lo anterior es un subconjunto de afirmaciones que admite minitest. Para obtener una lista
exhaustiva y actualizada, consulte la documentacin de la API de Minitest, especficamente
Minitest::Assertions.
Debido a la naturaleza modular del framework de testing, es posible crear sus propias
aserciones. De hecho, eso es exactamente lo que hace Rails. Incluye algunas aserciones
especializadas para hacer su vida ms fcil.
Crear sus propias aserciones es un tema avanzado que no cubriremos en este tutorial.
529
2- Introduccin a las pruebas
530
2- Introduccin a las pruebas
Assertion Purpose
assert_nothing_raised { block }
Asegura que el bloque dado no plantea ninguna
excepcin.
Afirma que el enrutamiento de la ruta de acceso
dada se ha manejado correctamente y que las
assert_recognizes(expected_options, opciones analizadas (dadas en el hash
path, extras={}, message=nil) expected_options) coinciden con la ruta.
Bsicamente, afirma que Rails reconoce la ruta
dada por expected_options.
Afirma que las opciones proporcionadas
pueden usarse para generar la ruta de acceso
proporcionada. Este es el inverso de
assert_recognizes. El parmetro extras se
assert_generates(expected_path,
options, defaults={}, extras = {},
utiliza para indicar a la solicitud los nombres y
message=nil) valores de los parmetros de peticin
adicionales que estaran en una cadena de
consulta. El parmetro de mensaje le permite
especificar un mensaje de error personalizado
para los fallos de asercin.
Afirma que la respuesta viene con un cdigo de
estado especfico. Puede especificar :success
para indicar 200-299, :redirect para indicar 300-
399, :missing para indicar 404, o :errorpara
assert_response(type, message =
nil) coincidir con el rango 500-599. Tambin puede
pasar un nmero de estado explcito o su
equivalente simblico. Para obtener ms
informacin, consulte la lista completa de los
cdigos de estado y cmo.
531
2- Introduccin a las pruebas
ActiveSupport::TestCase
ActionMailer::TestCase
ActionView::TestCase
ActionDispatch::IntegrationTest
ActiveJob::TestCase
ActionDispatch::SystemTestCase
Cada una de estas clases incluye Minitest::Assertions , lo que nos permite usar todas las
aserciones bsicas en nuestras pruebas.
O podemos ejecutar un solo archivo de prueba pasando el comando bin / rails test al
nombre de archivo que contiene los casos de prueba.
# Running:
..
532
2- Introduccin a las pruebas
# Running:
Tambin puede ejecutar una prueba en una lnea especfica proporcionando el nmero de
lnea.
El corredor de prueba tambin proporciona muchas otras caractersticas como failing fast,
diferir la salida de la prueba al final de la prueba, y as sucesivamente. Compruebe la
documentacin del test runner de la siguiente manera:
533
2- Introduccin a las pruebas
$ bin/rails test -h
minitest options:
-h, --help Display this help.
-s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake
-v, --verbose Verbose. Show progress processing files.
-n, --name PATTERN Filter run on /regexp/ or string.
--exclude PATTERN Exclude /regexp/ or string from run.
You can run multiple files and directories at the same time:
By default test failures and errors are reported inline during a run.
Rails options:
-e, --environment ENV Run tests in the ENV environment
-b, --backtrace Show the complete backtrace
-d, --defer-output Output test failures and errors after the test ru
n
-f, --fail-fast Abort test run on first failure or error
-c, --[no-]color Enable color in the output
534
3- Base de datos del testing
Por defecto, cada aplicacin de Rails tiene tres entornos: desarrollo, testing y produccin.
La base de datos para cada uno de ellos se configura en config/database.yml .
Una base de datos de pruebas dedicada le permite configurar e interactuar con datos de
prueba de forma aislada. De esta manera sus pruebas pueden manipular datos de prueba
con confianza, sin preocuparse por los datos en las bases de datos de desarrollo o
produccin.
535
3- Base de datos del testing
Los fixtures no estn diseados para crear todos los objetos que sus pruebas
necesitan, y se administran mejor cuando se utilizan slo para datos predeterminados
que se pueden aplicar al caso comn.
este directorio.
3.2.2 YAML
Los fixtures con formato YAML son una manera amigable para el usuario de describir sus
datos de muestra. Estos tipos de fixtures tienen la extensin .yml (como en users.yml ).
steve:
name: Steve Ross Kellock
birthday: 1974-09-27
profession: guy with keyboard
A cada fixture se le asigna un nombre seguido por una lista identada de llave/valor
separados por dos puntos. Los registros suelen estar separados por una lnea en blanco.
Puede colocar comentarios en un archivo de fixtures se hace usando el carcter # en la
primera columna.
Si est trabajando con asociaciones, simplemente puede definir un nodo de referencia entre
dos fixtures diferentes. He aqu un ejemplo con una asociacin belongs_to / has_many :
# In fixtures/categories.yml
about:
name: About
# In fixtures/articles.yml
first:
title: Welcome to Rails!
body: Hello world!
category: about
536
3- Base de datos del testing
Para que las asociaciones se refieran entre s por nombres, puede utilizar el nombre
del fixture en lugar de especificar el atributo :id en los fixtures asociados. Rails
asignar automticamente una clave primaria para que sea consistente entre las
ejecuciones. Para obtener ms informacin sobre este comportamiento de la
asociacin, lea la documentacin de la API de Fixtures.
3.2.3 ERB'in It Up
ERB le permite incrustar cdigo Ruby dentro de plantillas. El formato de fixtures YAML se
pre-procesa con ERB cuando Rails carga los fixtures. Esto le permite utilizar Ruby para
ayudarle a generar algunos datos de ejemplo. Por ejemplo, el cdigo siguiente genera un
millar de usuarios:
Para eliminar los datos existentes de la base de datos, Rails intenta deshabilitar los
disparadores de integridad referencial (como claves externas y restricciones de
comprobacin). Si est recibiendo errores de permisos molestos en las pruebas en
ejecucin, asegrese de que el usuario de la base de datos tenga privilegios para
desactivar estos disparadores en el entorno de prueba. (En PostgreSQL, slo los
superusuarios pueden deshabilitar todos los disparadores.) Ms informacin sobre los
permisos de PostgreSQL aqu).
537
3- Base de datos del testing
Los fixtures son instancias de Active Record. Como se menciona en el punto # 3 anterior,
puede acceder directamente al objeto porque est disponible automticamente como un
mtodo cuyo mbito es local es el caso de prueba. Por ejemplo:
# this will return the User object for the fixture named david
users(:david)
Para obtener varios fixtures a la vez, puede pasar una lista de nombres de los fixtures. Por
ejemplo:
# this will return an array containing the fixtures david and steve
users(:david, :steve)
538
4- Pruebas de modelos
4- Pruebas de modelos
Las pruebas del modelo se utilizan para probar varios modelos de su aplicacin.
539
5- Pruebas del sistema
Para crear las pruebas del sistema Rails, utilice el directorio test/system de su aplicacin.
Rails proporciona un generador para crear un esqueleto de prueba del sistema por usted.
require "application_system_test_case"
De forma predeterminada, las pruebas del sistema se ejecutan con el controlador Selenium,
mediante el navegador Chrome y un tamao de pantalla de 1400x1400. La siguiente
seccin explica cmo cambiar la configuracin predeterminada.
540
5- Pruebas del sistema
require "test_helper"
require "capybara/poltergeist"
require "test_helper"
541
5- Pruebas del sistema
Si utiliz el scaffold, un esqueleto de test del sistema se cre automticamente por usted. Si
no us el scaffold, comience creando un esqueleto de prueba del sistema.
Debera haber creado un marcador de archivo de prueba por nosotros. Con la salida del
comando anterior debera ver:
invoke test_unit
create test/system/articles_test.rb
require "application_system_test_case"
bin/rails test:system
542
5- Pruebas del sistema
Entonces click_on "New Article" encontrar el botn "New Article" en la pgina index. Esto
redireccionar el navegador a /articles/new .
A continuacin, la prueba rellenar el ttulo y el cuerpo del artculo con el texto especificado.
Una vez rellenados los campos, se hace clic en "Crete Article" en el que se enviar una
solicitud POST para crear el nuevo artculo en la base de datos.
5.3.2 Haciendo ms
La belleza de las pruebas del sistema es que es similar a las pruebas de integracin, ya que
prueba la interaccin del usuario con su controlador, modelo y vista, pero las pruebas del
sistema son mucho ms robustas y, de hecho, prueban su aplicacin como si un usuario
real la estuviera utilizando. A continuacin, puede probar cualquier cosa que el propio
usuario pueda hacer en su aplicacin, como comentar, eliminar artculos, publicar artculos
de borrador, etc.
543
6- Pruebas de integracin
6- Pruebas de integracin
Las pruebas de integracin se utilizan para probar cmo interactan varias partes de su
aplicacin. Generalmente se utilizan para probar flujos de trabajo importantes dentro de
nuestra aplicacin.
require 'test_helper'
escribir las pruebas de integracin. Vamos a presentar brevemente a las tres categoras de
helpers que podemos elegir.
544
6- Pruebas de integracin
Debera haber creado un marcador de archivo de prueba para nosotros. Con la salida del
comando anterior deberamos ver:
invoke test_unit
create test/integration/blog_flow_test.rb
require 'test_helper'
545
6- Pruebas de integracin
post "/articles",
params: { article: { title: "can create", body: "article successfully." } }
assert_response :redirect
follow_redirect!
assert_response :success
assert_select "p", "Title:\n can create"
end
Despus de esto hacemos una solicitud de post a la accin :create de nuestro controlador
de artculos:
post "/articles",
params: { article: { title: "can create", body: "article successfully." } }
assert_response :redirect
follow_redirect!
Las dos lneas que siguen a la peticin son para manejar la redireccin que configuramos al
crear un nuevo artculo.
Finalmente podemos afirmar(assert) que nuestra respuesta fue exitosa y nuestro nuevo
artculo es legible en la pgina.
546
7- Pruebas funcionales para sus controladores
Si ya tiene un controlador y slo desea generar el cdigo scaffold de prueba para cada una
de las siete acciones predeterminadas, puede utilizar el siguiente comando:
547
7- Pruebas funcionales para sus controladores
# articles_controller_test.rb
class ArticlesControllerTest < ActionDispatch::IntegrationTest
test "should get index" do
get articles_url
assert_response :success
end
end
El mtodo get inicia la solicitud web y rellena los resultados en @response . Puede aceptar
hasta 6 argumentos:
La URI de la accin del controlador que est solicitando. Esto puede tener la forma de una
cadena o un helper de ruta (por ejemplo, articles_url ).
La opcion params: con un hash de parmetros de peticin para pasar a la accin (por
ejemplo, parmetros de cadena de consulta o variables de artculo).
headers: para establecer los encabezados que se pasarn con la solicitud.
xhr: si la solicitud es Ajax o no. Se puede establecer en true para marcar la solicitud
como Ajax.
as: para codificar la solicitud con diferentes tipos de contenido. Soporta :json por
defecto.
548
7- Pruebas funcionales para sus controladores
Otro ejemplo: Llamar a la accin :update , pasando un id de 12 como params como una
solicitud de Ajax.
assert_redirected_to article_path(Article.last)
end
Si sigui los pasos de la seccin de autenticacin bsica, tendr que agregar lo siguiente al
bloque de instalacin para hacer que todas las pruebas pasen:
request.headers['Authorization'] = ActionController::HttpAuthentication::Basic.
encode_credentials('dhh', 'secret')
get
post
patch
put
head
delete
Todos los tipos de solicitud tienen mtodos equivalentes que puede utilizar. En una tpica
aplicacin C.R.U.D. va a utilizar get , post , put y delete ms a menudo.
549
7- Pruebas funcionales para sus controladores
Como ocurre con los objetos Hash normales, puede acceder a los valores haciendo
referencia a las claves por cadena. Tambin puede hacer referencia a ellos por nombre de
smbolo. Por ejemplo:
flash["gordon"] flash[:gordon]
session["shmession"] session[:shmession]
cookies["are_good_for_u"] cookies[:are_good_for_u]
550
7- Pruebas funcionales para sus controladores
Queremos agregar un mensaje flash a nuestra aplicacin de blog cada vez que alguien
crea con xito un nuevo artculo.
assert_redirected_to article_path(Article.last)
assert_equal 'Article was successfully created.', flash[:notice]
end
551
7- Pruebas funcionales para sus controladores
# Running:
1) Failure:
ArticlesControllerTest#test_should_create_article [/test/controllers/articles_controll
er_test.rb:16]:
--- expected
+++ actual
@@ -1 +1 @@
-"Article was successfully created."
+nil
def create
@article = Article.new(article_params)
if @article.save
flash[:notice] = 'Article was successfully created.'
redirect_to @article
else
render 'new'
end
end
# Running:
552
7- Pruebas funcionales para sus controladores
7.8 Juntndolo
En este punto, nuestro controlador de artculos testea las acciones :index , as como
:new y :create . Qu pasa con los datos existentes?
Recuerde nuestra discusin anterior en los fixtures, donde el mtodo de los articles()
nos dar acceso a nuestros fixtures de los articles.
assert_redirected_to articles_path
end
assert_redirected_to article_path(article)
# Reload association to fetch updated data and assert that title is updated.
article.reload
assert_equal "updated", article.title
end
Tenga en cuenta que estamos empezando a ver alguna duplicacin en estas tres pruebas,
ambos tienen acceso a los mismos datos del fixture del artculo. Podemos usar la filosofa
D.R.Y. Esto mediante el uso de los mtodos de configuracin y desmontaje proporcionados
por ActiveSupport::Callbacks .
553
7- Pruebas funcionales para sus controladores
Nuestra prueba ahora debe ser algo como lo que sigue. Ignore las otras pruebas por ahora,
las dejamos por brevedad.
require 'test_helper'
assert_redirected_to articles_path
end
assert_redirected_to article_path(@article)
# Reload association to fetch updated data and assert that title is updated.
@article.reload
assert_equal "updated", @article.title
end
end
554
7- Pruebas funcionales para sus controladores
# test/test_helper.rb
module SignInHelper
def sign_in_as(user)
post sign_in_url(email: user.email, password: user.password)
end
end
class ActionDispatch::IntegrationTest
include SignInHelper
end
require 'test_helper'
get profile_url
assert_response :success
end
end
555
8- Testeo de Rutas
8- Testeo de Rutas
Como todo lo dems en su aplicacin de Rails, puede probar sus rutas. Las pruebas de ruta
residen en las test/controllers/ o hacen parte de las pruebas del controlador.
Si su aplicacin tiene rutas complejas, Rails proporciona una serie de ayudantes tiles
para probarlos.
556
9- Testeo de las Vistas
cumpla en los elementos seleccionados a travs del selector. El selector puede ser una
expresin de selector CSS (String) o una expresin con valores de sustitucin.
igualdad se cumpla en todos los elementos seleccionados a travs del selector a partir del
elemento (instancia de Nokogiri::XML::Node o Nokogiri::XML::NodeSet ) y sus
descendientes.
Por ejemplo, puede verificar el contenido del elemento de ttulo en su respuesta con:
assert_select 'ul.navigation' do
assert_select 'li.menu_item'
end
Una coleccin de elementos seleccionados se puede iterar a travs de ella de modo que
assert_select puede ser llamado por separado en cada elemento.
Por ejemplo, si la respuesta contiene dos listas ordenadas, cada una con cuatro elementos
de lista anidados, se pasarn las siguientes pruebas.
557
9- Testeo de las Vistas
assert_select "ol" do
assert_select "li", 8
end
Assertion Purpose
assert_select_email
Le permite hacer aserciones en el
cuerpo de un e-mail..
Le permite hacer aserciones sobre
HTML codificado. Esto lo hace
assert_select_encoded
descodificando el contenido de cada
elemento y luego llamando al bloque
con todos los elementos no
codificados.
Devuelve un array de todos los
elementos seleccionados por el
selector. En la segunda variante
css_select(selector) or css_select(element, coincide primero con el elemento de
selector) base e intenta igualar esta expresin
de seleccin a cualquiera de sus hijos.
Si no hay coincidencias, ambas
variantes devuelven un array vaco.
assert_select_email do
assert_select 'small', 'Please click the "Unsubscribe" link if you want to opt-out.'
end
558
10- Testeo de los Helpers
Para probar los helpers, todo lo que necesitas hacer es comprobar que la salida del mtodo
del helper coincide con lo que esperas. Las pruebas relacionadas con los helpers se
encuentran en el directorio test/helpers .
module UserHelper
def link_to_user(user)
link_to "#{user.first_name} #{user.last_name}", user
end
end
559
11- Testeo de los Mailers
560
11- Testeo de los Mailers
dentro de test/fixtures corresponde directamente al nombre del mailer. Por lo tanto, para
un mailer llamado UserMailer , los fixtures deben residir en el directorio
test/fixtures/user_mailer.
Cuando gener su mailer, el generador crea fixtures de stub para cada una de las acciones
de los remitentes. Si no us el generador, tendr que crear esos archivos usted mismo.
require 'test_helper'
email.body.to_s est presente cuando slo hay una parte (HTML o texto) presente. Si el
mailer proporciona ambos, puede probar su fixture contra partes especficas con
email.text_part.body.to_s o email.html_part.body.to_s .
561
11- Testeo de los Mailers
Cheers!
el correo electrnico no se entregue realmente (til para evitar el spam de sus usuarios
durante la prueba), sino que se anexar a una matriz ( ActionMailer::Base.deliveries ).
require 'test_helper'
562
11- Testeo de los Mailers
563
12- Testeo de los Jobs
require 'test_helper'
Esta prueba es bastante simple y slo afirma que el job obtenga el trabajo realizado como
se esperaba.
Es una buena prctica asegurarse de que sus jobs se pongan en cola correctamente o se
realicen dondequiera que los invoque (por ejemplo, dentro de sus controladores). Esto es
precisamente donde las aserciones personalizadas proporcionadas por Active Job son
bastante tiles. Por ejemplo, dentro de un modelo:
564
12- Testeo de los Jobs
require 'test_helper'
565
13- Recursos Adicionales de Pruebas
# Lets say that a user is eligible for gifting a month after they register.
user = User.create(name: 'Gaurish', activation_date: Date.new(2004, 10, 24))
assert_not user.applicable_for_gifting?
travel_to Date.new(2004, 11, 24) do
assert_equal Date.new(2004, 10, 24), user.activation_date # inside the `travel_to` b
lock `Date.current` is mocked
assert user.applicable_for_gifting?
end
assert_equal Date.new(2004, 10, 24), user.activation_date # The change was visible onl
y inside the `travel_to` block.
566
XVIII - Seguridad de las aplicaciones de Rails
567
1- Introduccin
1- Introduccin
Los frameworks de aplicaciones Web se hacen para ayudar a los desarrolladores a crear
aplicaciones web. Algunos de ellos tambin le ayudan con la seguridad de la aplicacin
web. De hecho, un framework no es ms seguro que otro: si lo usa correctamente, podr
crear aplicaciones seguras con muchos frameworks. Ruby on Rails tiene algunos mtodos
auxiliares inteligentes, por ejemplo contra la inyeccin de SQL, de modo que esto no es un
problema.
En general no hay tal cosa como la seguridad plug-n-play. La seguridad depende de las
personas que utilizan el framework, y a veces en el mtodo de desarrollo. Y depende de
todas las capas de un entorno de la aplicacin web: el backend, el servidor web y la propia
aplicacin web (y posiblemente otras capas o aplicaciones).
El Gartner Group, sin embargo, estima que el 75% de los ataques estn en la capa de
aplicacin web, y descubri que "de los 300 sitios auditados, el 97% son vulnerables al
ataque". Esto es porque las aplicaciones web son relativamente fciles de atacar, ya que
son fciles de entender y manipular, incluso por una persona laica.
Las amenazas contra las aplicaciones web incluyen el secuestro de cuentas de usuario, el
desvo del control de acceso, la lectura o modificacin de datos confidenciales o la
presentacin de contenido fraudulento. O un atacante podra ser capaz de instalar un
programa de caballo de Troya o software de envo de correo electrnico no solicitado,
apuntar a enriquecimiento financiero o causar dao a la marca mediante la modificacin de
los recursos de la empresa. Con el fin de prevenir ataques, minimizar su impacto y eliminar
puntos de ataque, en primer lugar, usted tiene que entender completamente los mtodos de
ataque con el fin de encontrar las contramedidas correctas. Eso es lo que pretende esta
gua.
Con el fin de desarrollar aplicaciones web seguras tiene que mantenerse al da en todas las
capas y conocer a sus enemigos. Para mantenerse al da, suscrbase a las listas de correo
de seguridad, lea los blogs de seguridad y haga de la actualizacin y los controles de
seguridad un hbito (consulte el captulo Recursos adicionales). Se hace manualmente
porque as es como se encuentran los desagradables problemas de lgica de seguridad .
568
2- Sesiones
2- Sesiones
Un buen lugar para empezar a mirar la seguridad es en las sesiones, que pueden ser
vulnerables a los ataques en particular.
session[:user_id] = @current_user.id
User.find(session[:user_id])
2.2 ID de sesin
El identificador de sesin es una cadena hexadecimal aleatoria de 32 caracteres.
569
2- Sesiones
Por lo tanto, la cookie sirve como autenticacin temporal para la aplicacin web. Cualquier
persona que se apodera de una cookie de otra persona, puede utilizar la aplicacin web
como este usuario - con posibles consecuencias graves. Aqu hay algunas maneras de
secuestrar una sesin, y sus contramedidas:
Olfatea la cookie en una red insegura. Una LAN inalmbrica puede ser un ejemplo de
tal red. En una LAN inalmbrica sin cifrar, es especialmente fcil escuchar el trfico de
todos los clientes conectados. Para el generador de aplicaciones web, esto significa
proporcionar una conexin segura a travs de SSL. En Rails 3.1 y posteriores, esto
podra lograrse forzando siempre la conexin SSL en el archivo de configuracin de la
aplicacin:
config.force_ssl = true
El objetivo principal de la mayora de los atacantes es ganar dinero. Los precios en el bajo
mundo para las cuentas robadas de acceso a bancos van de $10 - $1000 (dependiendo de
la cantidad disponible de fondos), de $0.40- $20 para nmeros de tarjeta de crdito, $1- $8
para las cuentas en lnea de un sitio de subasta y $4- $30 para las contraseas de email,
segn el Informe de amenazas de Symantec Global Internet Security.
570
2- Sesiones
Las cookies implican un lmite de tamao estricto de 4kB. Esto est bien, ya que no
debe almacenar grandes cantidades de datos en una sesin de todos modos, como se
describi anteriormente. Almacenar el ID de la base de datos del usuario actual en una
sesin es normalmente aceptable.
El cliente puede ver todo lo que almacena en una sesin, ya que se almacena en texto
claro (en realidad codificado en Base64, no cifrado). As que, por supuesto, usted no
quiere guardar ningn secreto aqu. Para evitar la manipulacin de hash de sesin, se
calcula un digest a partir de la sesin con un secreto de servidor (secrets.secret_token)
e insertado en el final de la cookie.
que el usuario acceda y altere el contenido de la cookie. Por lo tanto, la sesin se convierte
en un lugar ms seguro para almacenar datos. El cifrado se realiza mediante una clave
secreta del servidor secrets.secret_key_base almacenada en config/secrets.yml .
571
2- Sesiones
secrets.secret_key_base se utiliza para especificar una clave que permite que las sesiones
de la aplicacin se verifiquen frente a una clave segura conocida para evitar la manipulacin
indebida. Las aplicaciones obtienen secrets.secret_key_base inicializado a una clave
aleatoria presente en config/secrets.yml , por ejemplo:
development:
secret_key_base: a75d...
test:
secret_key_base: 492f...
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
Las versiones anteriores de Rails utilizan CookieStore, que utiliza secret_token en lugar de
secret_key_base que es utilizado por EncryptedCookieStore . Lea la documentacin de
Si ha recibido una aplicacin en la que se descubri el secret (por ejemplo, una aplicacin
cuyo cdigo fuente se comparti), considere seriamente cambiar el secret.
Funciona as:
Un usuario recibe crditos, la cantidad se almacena en una sesin (que es una mala
idea de todos modos, pero lo haremos para propsitos de demostracin).
El usuario compra algo.
El nuevo valor de crdito ajustado se almacena en la sesin.
El usuario toma la cookie del primer paso (que previamente copi) y reemplaza la
cookie actual en el navegador.
El usuario tiene su crdito original de nuevo.
Incluir un nonce (un valor aleatorio) en la sesin resuelve ataques de repeticin. Un nonce
es vlido slo una vez, y el servidor tiene que hacer un seguimiento de todos los nonces
vlidos. Se vuelve an ms complicado si tiene varios servidores de aplicaciones.
Almacenar nonces en una tabla de la base de datos anulara el propsito entero de
CookieStore (evitar el acceso a la base de datos).
572
2- Sesiones
La mejor solucin en contra es no almacenar este tipo de datos en una sesin, sino en la
base de datos. En este caso, guarde el crdito en la base de datos y en el
session_in_user_id en la sesin.
Este ataque se centra en la fijacin de un ID de sesin del usuario conocido por el atacante,
y obligando al navegador del usuario a utilizar este ID. Por lo tanto, no es necesario que el
atacante robe el ID de sesin despus. As es como funciona este ataque:
573
2- Sesiones
ms adelante.
reset_session
574
2- Sesiones
Las sesiones que nunca caducan prolongan el marco de tiempo para ataques como la
falsificacin de solicitudes entre sitios (CSRF), el secuestro de sesin y la fijacin de
sesin.
de 20 minutos.
La seccin sobre "la fijacin de la sesin" introdujo el problema de las sesiones mantenidas.
Un atacante que mantiene una sesin cada cinco minutos puede mantener la sesin viva
para siempre, aunque est expirando las sesiones. Una solucin simple para esto sera
agregar una columna created_at a la tabla de sesiones. Ahora puede eliminar las sesiones
que se crearon hace mucho tiempo. Utilice esta lnea en el mtodo de barrido anterior:
575
3- Falsificacin de solicitudes entre sitios (CSRF)
Bob navega por un tablero de mensajes y ve una entrada de un hacker donde hay un
elemento de imagen HTML creado. El elemento hace referencia a un comando en la
576
3- Falsificacin de solicitudes entre sitios (CSRF)
Es importante notar que la imagen real o el enlace no necesariamente tiene que estar
situado en el dominio de la aplicacin web, puede estar en cualquier lugar, en un foro, una
publicacin de blog o un correo electrnico.
CSRF aparece muy raramente en CVE (Common Vulnerabilities and Exposures) - menos
del 0,1% en 2006 - pero es realmente un "gigante dormido" [Grossman]. Esto contrasta
fuertemente con los resultados en muchos contratos de seguridad - CSRF es un importante
problema de seguridad.
La interaccin se parece ms a una pregunta (es decir, es una operacin segura como
una consulta, una operacin de lectura o una bsqueda).
577
3- Falsificacin de solicitudes entre sitios (CSRF)
Hay muchas otras posibilidades, como usar una etiqueta <script> para hacer una solicitud
entre sitios a una URL con una respuesta JSONP o JavaScript. La respuesta es cdigo
ejecutable en el que el atacante puede encontrar una manera de ejecutar, posiblemente
extrayendo datos sensibles. Para protegerse contra esta fuga de datos, debemos rechazar
las etiquetas <script> entre sitios. Las solicitudes de Ajax, sin embargo, obedecen la
poltica del mismo origen del navegador (solo su propio sitio puede iniciar XmlHttpRequest )
para que podamos permitirles devolver respuestas JavaScript de forma segura.
Nota: no podemos distinguir el origen de una etiqueta <script> , ya sea una etiqueta en su
propio sitio o en otro sitio malicioso, por lo que debemos bloquear todos los <script> en el
board, aunque sea realmente un origen seguro, como el Script de su propio sitio. En estos
casos, omita explcitamente la proteccin CSRF en las acciones que sirven JavaScript
destinado a una etiqueta <script> .
578
3- Falsificacin de solicitudes entre sitios (CSRF)
para obtener esta informacin, debe manejar lo que debe hacer con ella:
Tenga en cuenta que las vulnerabilidades de XSS (cross-site scripting) pasan por alto todas
las protecciones CSRF. XSS proporciona al atacante acceso a todos los elementos de una
pgina, para que puedan leer el token de seguridad CSRF desde un formulario o enviar
directamente el formulario. Ms informacin sobre XSS ms adelante.
579
4- Redireccin y archivos
4- Redireccin y archivos
Otra clase de vulnerabilidades de seguridad rodea el uso de la redireccin y los archivos en
las aplicaciones web.
4.1 Redireccin
La redireccin en una aplicacin web es una herramienta de cracker subestimada: no
slo el atacante puede enviar al usuario a un sitio web falso, sino que tambin puede
crear un ataque autnomo.
Siempre que se permite al usuario pasar (partes de) la URL para la redireccin, es
posiblemente vulnerable. El ataque ms obvio sera redirigir a los usuarios a una aplicacin
web falsa que se ve y se siente exactamente como la original. Este llamado ataque phishing
funciona enviando un enlace no sospechoso en un correo electrnico a los usuarios,
inyectando el enlace por XSS en la aplicacin web o poniendo el enlace en un sitio externo.
Es poco sospechoso, porque el enlace comienza con la URL de la aplicacin web y la
direccin URL del sitio malintencionado est oculta en el parmetro de redireccin:
http://www.example.com/site/redirect?to=www.attacker.com . He aqu un ejemplo de una
accin heredada:
def legacy
redirect_to(params.update(action:'main'))
end
http://www.example.com/site/legacy?param1=xy¶m2=23&host=www.attacker.com
accin heredada (de nuevo un enfoque de lista blanca, en lugar de eliminar parmetros
inesperados). Y si rediriges a una URL, comprubala con una lista blanca o una expresin
regular.
580
4- Redireccin y archivos
data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K
Muchas aplicaciones web permiten a los usuarios cargar archivos. Los nombres de archivo,
que el usuario puede elegir (en parte), siempre deben ser filtrados, ya que un atacante
podra usar un nombre de archivo malicioso para sobrescribir cualquier archivo del servidor.
Si almacena subidas de archivos en /var/www/uploads y el usuario introduce un nombre de
archivo como " ../../../etc/passwd ", puede sobrescribir un archivo importante. Por
supuesto, el intrprete de Ruby necesitara los permisos apropiados para hacerlo - una
razn ms para ejecutar servidores web, servidores de bases de datos y otros programas
como un usuario Unix menos privilegiado.
Al filtrar los nombres de los archivos de entrada del usuario, no intente eliminar partes
malintencionadas. Piense en una situacin en la que la aplicacin web quita todo el " ../ "
en un nombre de archivo y un atacante utiliza una cadena como " .... // " - el resultado
ser " ../ ". Lo mejor es utilizar un enfoque de lista blanca, que comprueba la validez de un
nombre de archivo con un conjunto de caracteres aceptados. Esto se opone a un enfoque
de lista negra que intenta eliminar caracteres no permitidos. En caso de que no sea un
nombre de archivo vlido, rechcelo (o reemplace los caracteres no aceptados), pero no los
elimine. Aqu est el nombre de archivo sanitizer del plugin attachment_fu :
def sanitize_filename(filename)
filename.strip.tap do |name|
# NOTE: File.basename doesn't work right with Windows paths on Unix
# get only the filename, not the whole path
name.sub! /\A.*(\\|\/)/, ''
# Finally, replace all non alphanumeric, underscore
# or periods with underscore
name.gsub! /[^\w\.\-]/, '_'
end
end
581
4- Redireccin y archivos
Una desventaja significativa del procesamiento sncrono de subidas de archivos (como con
el plugin attachment_fu que puede subir imgenes), es su vulnerabilidad a los ataques de
denegacin de servicio. Un atacante puede iniciar de forma sincronizada cargas de archivos
de imagen desde muchas computadoras, lo que aumenta la carga del servidor y
eventualmente se bloquea o bloquea el servidor.
La solucin a esto es mejor procesar los archivos de medios de forma asncrona: Guarde el
archivo de medios y programe una solicitud de procesamiento en la base de datos. Un
segundo proceso manejar el proceso del archivo en el background.
El popular servidor web Apache tiene una opcin denominada DocumentRoot . Este es el
directorio de inicio del sitio web, todo en este rbol de directorio ser servido por el servidor
web. Si hay archivos con una extensin de nombre de archivo determinada, el cdigo en
ella se ejecutar cuando se solicite (podra requerir algunas opciones para establecer).
Ejemplos de esto son archivos PHP y CGI . Ahora piensa en una situacin en la que un
atacante carga un archivo " file.cgi " con cdigo en l, que se ejecutar cuando alguien
descargue el archivo.
Del mismo modo que tiene que filtrar los nombres de archivo para las subidas, tiene que
hacerlo para las descargas. El mtodo send_file() enva archivos desde el servidor al
cliente. Si utiliza un nombre de archivo, que el usuario ingres, sin filtrar, el puede descargar
cualquier archivo:
send_file('/var/www/uploads/' + params[:filename])
Simplemente pase un nombre de archivo como este " ../../../etc/passwd " para descargar
la informacin de inicio de sesin del servidor. Una solucin simple contra esto es
comprobar que el archivo solicitado est en el directorio esperado:
582
4- Redireccin y archivos
583
5- Intranet y seguridad del administrador
En 2007 se produjo el primer troyano hecho a la medida que rob informacin de una
intranet, a saber, el sitio web Monster para empleadores de Monster.com, una aplicacin
web de reclutamiento en lnea. Troyanos hechos a la medida son muy raros, hasta ahora, y
el riesgo es bastante bajo, pero sin duda es una posibilidad y un ejemplo de cmo la
seguridad del cliente de acogida es importante, tambin. Sin embargo, la mayor amenaza
para las aplicaciones Intranet y Admin son XSS y CSRF.
CSRF. Cross-Site Request Forgery (CSRF), tambin conocido como Cross-Site Reference
Forgery (XSRF), es un mtodo de ataque gigantesco, que permite al atacante hacer todo lo
que el administrador o usuario de Intranet puede hacer. Como ya has visto anteriormente, la
CSRF funciona, aqu hay algunos ejemplos de lo que los atacantes pueden hacer en la
Intranet o en la interfaz de administracin.
Un ejemplo del mundo real es una reconfiguracin del enrutador por CSRF. Los atacantes
enviaron un correo electrnico malicioso, con CSRF en l, a los usuarios mexicanos. El e-
mail afirmaba que haba una tarjeta electrnica esperando al usuario, pero tambin contena
una etiqueta de imagen que result en una solicitud HTTP-GET para reconfigurar el
enrutador del usuario (que es un modelo popular en Mxico). La solicitud cambi los ajustes
de DNS para que las solicitudes a un sitio bancario con sede en Mxico se asignaran al sitio
del atacante. Todos los que accedieron al sitio de la banca a travs de ese enrutador vieron
el sitio web falso del atacante y se les robaron sus credenciales.
584
5- Intranet y seguridad del administrador
Otro ataque popular es el spam de su aplicacin web, su blog o foro para propagar XSS
malicioso. Por supuesto, el atacante tiene que conocer la estructura de URL, pero la
mayora de las URLs de Rails son bastante sencillas o sern fciles de averiguar, si se trata
de una interfaz de administracin de aplicacin abierta. El atacante puede incluso hacer
1.000 suposiciones con suerte, incluyendo las etiquetas maliciosas IMG que prueban todas
las posibles combinaciones.
Para las contramedidas contra CSRF en interfaces de administracin e intranet, consulte las
contramedidas en la seccin CSRF.
administracin de usuarios. Esto hace que robar una cookie de administracin del
dominio habitual, www.application.com , sea imposible. Esto se debe a la misma poltica
de origen en su navegador: Un script inyectado (XSS) en www.application.com no
puede leer la cookie para admin.application.com y viceversa.
585
5- Intranet y seguridad del administrador
586
6- Gestin de usuarios
6- Gestin de usuarios
Casi todas las aplicaciones web tienen que lidiar con la autorizacin y la autenticacin.
En lugar de hacer su propio cdigo, es aconsejable utilizar plug-ins comunes. Pero
tambin, mantenerlos al da. Algunas precauciones adicionales pueden hacer que su
aplicacin sea an ms segura.
Existen varios complementos de autenticacin disponibles para Rails. Los buenos, como
devise y authlogic , almacenan slo contraseas encriptadas, no contraseas de texto
sin formato. En Rails 3.1 puede utilizar el mtodo has_secure_password incorporado que
tiene caractersticas similares.
Cada nuevo usuario recibe un cdigo de activacin para activar su cuenta cuando recibe un
correo electrnico con un enlace. Despus de activar la cuenta, las columnas
activation_code se establecern en NULL en la base de datos. Si alguien solicit una URL
como sta, se registrara como el primer usuario activado que se encuentre en la base de
datos (y es probable que se trate del administrador):
http://localhost:3006/user/activate
http://localhost:3006/user/activate?id=
User.find_by_activation_code(params[:id])
587
6- Gestin de usuarios
Los ataques de fuerza bruta en las cuentas son ataques de prueba y error en las
credenciales de inicio de sesin. Abandonarlos con mensajes de error ms genricos y
posiblemente necesite introducir un CAPTCHA.
Una lista de nombres de usuario para su aplicacin web puede ser mal utilizada para forzar
las contraseas, porque la mayora de la gente no usa contraseas sofisticadas. La mayora
de las contraseas son una combinacin de palabras del diccionario y posiblemente
nmeros. As armado con una lista de nombres de usuario y un diccionario, un programa
automtico puede encontrar la contrasea correcta en cuestin de minutos.
Debido a esto, la mayora de las aplicaciones web mostrar un mensaje de error genrico
"nombre de usuario o contrasea no correcta", si una de ellas no es correcta. Si dice que
"no se ha encontrado el nombre de usuario que ha introducido", un atacante podra compilar
automticamente una lista de nombres de usuario.
Sin embargo, lo que la mayora de los diseadores de aplicaciones web descuidan, son las
pginas de "olvid mi contrasea". Estas pginas admiten a menudo que el nombre de
usuario introducido o la direccin de correo electrnico no se ha encontrado. Esto permite a
un atacante compilar una lista de nombres de usuario y forzar las cuentas.
Con el fin de mitigar estos ataques, mostrar un mensaje de error genrico en las pginas de
"olvid mi contrasea", tambin. Adems, puede requerir introducir un CAPTCHA despus
de un nmero de inicios de sesin fallidos de una determinada direccin IP. Tenga en
cuenta, sin embargo, que esto no es una solucin a prueba de balas contra programas
automticos, porque estos programas pueden cambiar su direccin IP a menudo. Sin
embargo, levanta la barrera de un ataque.
6.2.1 Contraseas
Piense en una situacin en la que un atacante ha robado la cookie de sesin de un usuario
y, por lo tanto, puede usar la aplicacin conjuntamente. Si es fcil cambiar la contrasea, el
atacante secuestrar la cuenta con unos pocos clics. O si el formulario de cambio de
contrasea es vulnerable a CSRF, el atacante podr cambiar la contrasea de la vctima
atrayndolas a una pgina web donde hay una etiqueta IMG que hace la CSRF. Como
contramedida, haga que los fomularios de cambio de contrasea sean seguras contra
CSRF, por supuesto. Y requiera que el usuario introduzca la contrasea antigua al
cambiarla.
588
6- Gestin de usuarios
6.2.2 E-Mail
Sin embargo, el atacante tambin puede hacerse cargo de la cuenta cambiando la direccin
de correo electrnico. Despus de que lo cambien, irn a la pgina de contrasea olvidada
y la (posiblemente nueva) contrasea ser enviada a la direccin de correo electrnico del
atacante. Como contramedida tambin debes requerir que el usuario introduzca la
contrasea al cambiar la direccin de correo electrnico.
6.2.3 Otros
Dependiendo de su aplicacin web, puede haber ms maneras de secuestrar la cuenta del
usuario. En muchos casos CSRF y XSS ayudarn a hacerlo. Por ejemplo, como en una
vulnerabilidad de CSRF en Gmail. En este ataque de prueba de concepto, la vctima habra
sido atrada a un sitio web controlado por el atacante. En ese sitio hay una etiqueta IMG
elaborada que da como resultado una solicitud HTTP GET que cambia la configuracin del
filtro de Google Mail. Si la vctima inici sesin en Google Mail, el atacante cambiara los
filtros para reenviar todos los correos electrnicos a su direccin de correo electrnico. Esto
es casi tan daino como secuestrar toda la cuenta. Como contramedida, revise la lgica de
su aplicacin y elimine todas las vulnerabilidades de XSS y CSRF.
6.3 CAPTCHAs
Un CAPTCHA es una prueba de desafo-respuesta para determinar que la respuesta
no es generada por una computadora. Se utiliza a menudo para proteger los
formularios de registro de los atacantes y los formularios de comentarios de los robots
de spam automticos pidiendo al usuario que escriba las letras de una imagen
distorsionada. Este es el CAPTCHA positivo, pero tambin hay el CAPTCHA negativo.
La idea de un CAPTCHA negativo no es para un usuario probar que son humanos,
pero revelan que un robot es un robot.
Una popular API CAPTCHA positiva es reCAPTCHA que muestra dos imgenes
distorsionadas de palabras de libros antiguos. Tambin aade una lnea angulada, en lugar
de un fondo distorsionado y altos niveles de deformacin en el texto como anteriores
CAPTCHAs, porque estos ltimos se rompieron. Como bonificacin, el uso de reCAPTCHA
ayuda a digitalizar libros antiguos. ReCAPTCHA es tambin un complemento Rails con el
mismo nombre que la API.
Obtendr dos claves de la API, una clave pblica y una privada, que debe poner en su
entorno de Rails. Despus de eso, puede utilizar el mtodo recaptcha_tags en la vista y el
mtodo verify_recaptcha en el controlador. verify_recaptcha devolver false si la
validacin falla. El problema con CAPTCHAs es que tienen un impacto negativo en la
589
6- Gestin de usuarios
experiencia del usuario. Adems, algunos usuarios con discapacidades visuales han
encontrado ciertos tipos de CAPTCHA distorsionados difciles de leer. Sin embargo, los
CAPTCHA positivos son uno de los mejores mtodos para evitar que todo tipo de bots
enven formularios.
La mayora de los bots son realmente tontos. Ellos rastrean la web y ponen su spam en el
campo de todos los formularios que pueden encontrar. Los CAPTCHA negativos se
aprovechan de eso e incluyen un campo " honeypot " en el formulario que se oculta del
usuario humano por CSS o JavaScript.
Tenga en cuenta que los CAPTCHA negativos slo son eficaces contra bots mudos y no
ser suficiente para proteger las aplicaciones crticas de los bots seleccionados. Sin
embargo, los CAPTCHA negativos y positivos pueden combinarse para aumentar el
rendimiento, por ejemplo, si el campo " honeypot " no est vaco (bot detectado), no
necesitar verificar el CAPTCHA positivo, lo que requerira una solicitud HTTPS a Google
ReCaptcha antes de calcular la respuesta.
Aqu estn algunas ideas sobre cmo ocultar los campos del honeypot por JavaScript y/o
CSS:
Incluya un campo con el sello de hora UTC actual y comprubelo en el servidor. Si est
demasiado lejos en el pasado, o si es en el futuro, el formulario no es vlido.
Aleatorizar los nombres de los campos
Incluir ms de un campo de honeypot de todos los tipos, incluidos los botones de envo.
Tenga en cuenta que esto slo lo protege de los bots automticos, bots hechos a medida no
puede ser detenido por esto. As que los CAPTCHA negativos podran no ser buenos para
proteger los formularios de inicio de sesin.
6.4 Logging
Dgale a Rails que no ponga contraseas en los archivos de registro.
590
6- Gestin de usuarios
De forma predeterminada, Rails "loguea" (hace logs) todas las solicitudes que se realizan
en la aplicacin web. Pero los archivos de logs pueden ser un problema de seguridad
enorme, ya que pueden contener credenciales de inicio de sesin, nmeros de tarjetas de
crdito y otros. Al disear un concepto de seguridad de aplicaciones web, tambin debe
pensar en lo que suceder si un atacante tiene acceso (completo) al servidor web. Cifrar los
secrets y contraseas en la base de datos ser bastante intil, si los archivos de logs los
enuncian en texto claro. Puede filtrar ciertos parmetros de solicitud de sus archivos de logs
agregndolos a config.filter_parameters en la configuracin de la aplicacin. Estos
parmetros se marcarn [FILTERED] en el log.
Es interesante que slo el 4% de estas contraseas eran palabras del diccionario y la gran
mayora es en realidad alfanumrica. Sin embargo, los diccionarios de "crackeo" de
contraseas contienen un gran nmero de contraseas de hoy, y prueban todo tipo de
combinaciones (alfanumricas). Si un atacante conoce su nombre de usuario y utiliza una
contrasea dbil, su cuenta se romper fcilmente.
Una buena contrasea es una larga combinacin alfanumrica de casos mixtos. Como esto
es muy difcil de recordar, es aconsejable introducir slo las primeras letras de una oracin
que pueda recordar fcilmente. Por ejemplo "El zorro marrn rpido salta sobre el perro
591
6- Gestin de usuarios
perezoso" ser "Tqbfjotld". Tenga en cuenta que esto es slo un ejemplo, no debe utilizar
frases bien conocidas como estas, ya que pueden aparecer en los diccionarios cracker,
tambin.
Ruby utiliza un enfoque ligeramente diferente a muchos otros lenguajes para coincidir con el
comienzo y el final de un string. Es por eso que incluso muchos libros de Ruby y Rails se
equivocan. Entonces, cmo es esto una amenaza de seguridad? Digamos que quera
validar un campo de URL de manera flexible y utiliz una expresin regular simple como
sta:
/^https?:\/\/[^\n]+$/i
Esto puede funcionar bien en algunos lenguajes. Sin embargo, en Ruby ^ y $ coinciden con
el principio de la lnea y el final de la lnea. Y as una URL como sta pasa el filtro sin
problemas:
javascript:exploit_code();/*
http://hi.com
*/
Esta URL pasa el filtro porque la expresin regular coincide - la segunda lnea, el resto no
importa. Ahora imagine que tenamos una vista que mostraba la URL como esta:
El enlace parece inocente para los visitantes, pero cuando se hace clic en l, se ejecutar la
funcin JavaScript " exploit_code " o cualquier otro JavaScript que el atacante proporciona.
/\Ahttps?:\/\/[^\n]+\z/i
592
6- Gestin de usuarios
Tenga en cuenta que esto slo lo protege contra el error ms comn al usar el validador de
formato - siempre debe tener en cuenta que ^ y $ coinciden con el principio de la lnea y el
final de la lnea en Ruby, y no el principio y el final de una cadena.
@project = Project.find(params[:id])
Esto est bien para algunas aplicaciones web, pero ciertamente no si el usuario no est
autorizado a ver todos los proyectos. Si el usuario cambia el ID a 42, y no se les permite
ver esa informacin, tendrn acceso a ella de todos modos. En su lugar, consulte los
derechos de acceso del usuario:
@project = @current_user.projects.find(params[:id])
No se deje engaar por la seguridad por ofuscacin y por la seguridad de JavaScript. Las
herramientas para desarrolladores le permiten revisar y cambiar los campos ocultos de
cada formulario. JavaScript se puede utilizar para validar datos de entrada del usuario, pero
ciertamente no para evitar que los atacantes enven peticiones maliciosas con valores
inesperados. El complemento Firebug para Mozilla Firefox registra todas las solicitudes y
puede repetirlas y cambiarlas. Es una manera fcil de evitar cualquier validacin de
JavaScript. Y hay incluso los proxies del lado del cliente que permiten que usted intercepte
cualquier peticin y respuesta de y al Internet.
593
7- Injection
7- Injection
PD: este capitulo no tiene todo el cdigo completo, dado que tiene sentencias de
inyeccin SQL, y Gitbook lo analiza como tal, y lo evita para no generar
vulnerabilidades. Asi que debes leerlo con cuidado y dirigirte a la documentacin
oficial en ingls.
La inyeccin es muy complicada, porque el mismo cdigo o parmetro puede ser malicioso
en un contexto, pero totalmente inofensivo en otro. Un contexto puede ser un lenguaje de
programacin, consulta o de programacin, el shell o un mtodo Ruby / Rails. Las
secciones siguientes cubrirn todos los contextos importantes donde pueden ocurrir
ataques de inyeccin. La primera seccin, sin embargo, cubre una decisin arquitectnica
en relacin con la inyeccin.
Una lista negra puede ser una lista de direcciones de correo electrnico incorrectas,
acciones no pblicas o etiquetas HTML incorrectas. Esto se opone a una lista blanca que
enumera las buenas direcciones de correo electrnico, acciones pblicas, buenas etiquetas
HTML y as sucesivamente. Aunque a veces no es posible crear una lista blanca (en un
filtro SPAM, por ejemplo), prefiera utilizar enfoques de listas blancas:
Utilice before_action except: [...] instead of only: [...] para acciones relacionadas
con la seguridad. De esta manera, no olvide activar las comprobaciones de seguridad
de las acciones aadidas recientemente.
Permitir <strong> en lugar de eliminar <script> contra Cross-Site Scripting (XSS). Vea a
abajo para ms detalles
594
7- Injection
Las listas blancas son tambin un buen enfoque contra el factor humano de olvidar algo en
la lista negra.
7.2.1 Introduccin
Los ataques de inyeccin SQL apuntan a influenciar las consultas de la base de datos
mediante la manipulacin de los parmetros de la aplicacin web. Un objetivo popular de
los ataques de inyeccin de SQL es evitar la autorizacin. Otro objetivo es realizar la
manipulacin de datos o leer datos arbitrarios. A continuacin se muestra un ejemplo de
cmo no utilizar datos de entrada del usuario en una consulta:
Project.where("name = '#{params[:name]}'")
Esto podra estar en un action llamado search y el usuario puede introducir el nombre de
un proyecto que desea encontrar. Si un usuario malintencionado introduce 'OR 1 -- , la
consulta SQL resultante ser:
Los dos guiones empiezan un comentario ignorando todo despus de l. Por lo tanto, la
consulta devuelve todos los registros de la tabla de proyectos, incluidos los ocultos para el
usuario. Esto se debe a que la condicin es true para todos los registros.
595
7- Injection
Si un atacante introduce ' OR '1'='1 como nombre y ' OR '2'>'1 como contrasea, la consulta
SQL resultante ser:
SELECT * FROM users WHERE login = '' OR '1'='1' AND password = '' OR '2'>'1' LIMIT 1
Project.where("name = '#{params[:name]}'")
El resultado no ser una lista de proyectos (porque no hay un proyecto con un nombre
vaco), sino una lista de nombres de usuario y su contrasea. As que esperamos que haya
encriptado las contraseas en la base de datos! El nico problema para el atacante es que
el nmero de columnas tiene que ser el mismo en ambas consultas. Es por eso que la
segunda consulta incluye una lista de unos (1), que ser siempre el valor 1, con el fin de
coincidir con el nmero de columnas en la primera consulta.
7.2.4 Contramedidas
Ruby on Rails tiene un filtro incorporado para caracteres especiales de SQL, que escapar
",", caracteres NULL y saltos de lnea.Utilizando Model.find(id) o
Model.find_by_something(something) aplica automticamente esta contramedida. Para
596
7- Injection
En lugar de pasar una cadena a la opcin de condiciones, puede pasar una matriz para
desinfectar cadenas viciadas as:
Como puede ver, la primera parte de la matriz es un fragmento de SQL con signos de
interrogacin. Las versiones desinfectadas de las variables de la segunda parte de la matriz
sustituyen a los signos de interrogacin. O puede pasar un hash para el mismo resultado:
La matriz o hash de los formularios slo est disponible en instancias de modelo. Puedes
intentar el sanitize_sql() en otro lugar. Haga un hbito pensar en las consecuencias de
seguridad cuando se utiliza una cadena externa en SQL.
Los puntos de entrada ms comunes son los mensajes de los post, los comentarios de los
usuarios y los libros de visitas, pero los ttulos de los proyectos, los nombres de los
documentos y las pginas de resultados de bsqueda tambin han sido vulnerables. Pero la
entrada no necesariamente tiene que venir de cuadros de entrada en sitios web, puede
estar en cualquier parmetro de URL - obvio, oculto o interno. Recuerde que el usuario
puede interceptar cualquier trfico. Las aplicaciones o los proxies de cliente-sitio facilitan el
cambio de solicitudes. Tambin hay otros vectores de ataque como anuncios de banner.
Los ataques XSS funcionan de la siguiente manera: Un atacante inyecta algn cdigo, la
aplicacin web lo guarda y lo muestra en una pgina, presentado posteriormente a una
vctima. La mayora de los ejemplos XSS simplemente muestran un cuadro de alerta, pero
es ms potente que eso. XSS puede robar la cookie, secuestrar la sesin, redirigir a la
597
7- Injection
vctima a un sitio web falso, mostrar anuncios para beneficio del atacante, cambiar
elementos en el sitio web para obtener informacin confidencial o instalar software
malicioso a travs de agujeros de seguridad en el navegador web.
Este cdigo JavaScript simplemente mostrar un cuadro de alerta. Los siguientes ejemplos
hacen exactamente lo mismo, slo que en lugares muy poco comunes:
Estos ejemplos no causan ningn dao hasta ahora, as que veamos cmo un atacante
puede robar la cookie del usuario (y as secuestrar la sesin del usuario). En JavaScript
puede utilizar la propiedad document.cookie para leer y escribir la cookie del documento.
JavaScript aplica la misma poltica de origen, lo que significa que un script de un dominio no
puede acceder a las cookies de otro dominio. La propiedad document.cookie contiene la
cookie del servidor web de origen. Sin embargo, puede leer y escribir esta propiedad si
inserta el cdigo directamente en el documento HTML (como sucede con XSS). Inyecte
esto en cualquier parte de su aplicacin web para ver su propia cookie en la pgina de
resultados:
598
7- Injection
Para un atacante, por supuesto, esto no es til, ya que la vctima ver su propia cookie. El
siguiente ejemplo intentar cargar una imagen desde la URL
http://www.attacker.com/ adems de la cookie. Por supuesto, esta URL no existe, por lo
que el navegador no muestra nada. Pero el atacante puede revisar los archivos de registro
de acceso de su servidor web para ver la cookie de la vctima.
Usted puede mitigar estos ataques (de la manera obvia) agregando la flag de httpOnly a las
cookies, de modo que document.cookie no pueda ser ledo por el Javascript. Slo se
pueden utilizar cookies HTTP de IE v6.SP1, Firefox v2.0.0.5, Opera 9.5, Safari 4 y Chrome
1.0.154. Pero otros navegadores antiguos (como WebTV e IE 5.5 en Mac) pueden causar
que la pgina no se cargue. Sin embargo, tenga en cuenta que las cookies seguirn siendo
visibles usando Ajax.
7.3.2.2 Destruccin
Con la degradacin de pginas web, un atacante puede hacer muchas cosas, por ejemplo,
presentar informacin falsa o atraer a la vctima en el sitio web de los atacantes para robar
la cookie, credenciales de inicio de sesin u otros datos confidenciales. La forma ms
popular es incluir cdigo de fuentes externas por iframes:
Esto carga HTML y/o JavaScript arbitrario de una fuente externa y lo incrusta como parte
del sitio. Este iframe se toma de un ataque real a sitios italianos legtimos usando el marco
de ataque de Mpack. Mpack intenta instalar software malicioso a travs de agujeros de
seguridad en el navegador web - con mucho xito, el 50% de los ataques tienen xito.
599
7- Injection
Los ataques de inyeccin reflejados son aquellos en los que la carga til no se almacena
para presentarla a la vctima posteriormente, pero se incluye en la URL. Especialmente los
formularios de bsqueda no pueden escapar de la cadena de bsqueda. El siguiente enlace
presentaba una pgina en la que se deca que "George Bush design a un nio de 9 aos
para que fuera el presidente ...":
7.3.2.3 Contramedidas
Especialmente para XSS, es importante hacer filtrado de entrada de lista blanca en lugar de
lista negra. El filtrado de listas blancas indica los valores permitidos en oposicin a los
valores no permitidos. Las listas negras nunca estn completas.
Imagine que una lista negra elimina "script" de la entrada del usuario. Ahora el atacante
inyecta "<scrscriptipt>", y despus del filtro, "<script>" permanece. Las versiones anteriores
de Rails utilizaron un enfoque de lista negra para el mtodo strip_tags() , strip_links()
y sanitize() . As que este tipo de inyeccin era posible:
Esto devolvi "algunos <script>alert ('hello')</ script> ", lo que hace que un ataque
funcione. Es por eso que un enfoque de lista blanca es mejor, utilizando el mtodo
actualizado de Rails 2 sanitize() :
Esto permite slo las etiquetas dadas y hace un buen trabajo, incluso contra todo tipo de
trucos y etiquetas mal formadas.
600
7- Injection
Como segundo paso, es una buena prctica escapar de toda la salida de la aplicacin,
especialmente cuando vuelve a mostrar la entrada del usuario, que no ha sido filtrada por el
input (como en el ejemplo del formulario de bsqueda anterior). Utilice el mtodo
escapeHTML() o su mtodo alias h() para reemplazar los caracteres de entrada HTML &,
", <y> por sus representaciones no interpretadas en HTML ( &, ", <, and
> ).
El trfico de la red se basa sobre todo en el alfabeto occidental limitado, as que las nuevas
codificaciones de carcter, tales como Unicode, emergieron, para transmitir caracteres en
otros idiomas. Sin embargo, esto tambin es una amenaza para las aplicaciones web, ya
que el cdigo malicioso se puede ocultar en diferentes codificaciones que el navegador
puede procesar, pero la aplicacin web no. Aqu est un vector de ataque en codificacin
UTF-8:
Este ejemplo muestra un cuadro de mensaje. Sin embargo, ser reconocido por el filtro
sanitize() anterior. Una gran herramienta para ofuscar y codificar cadenas, y as "conocer
Lo que sigue es un extracto del Js.Yamanner@m Yahoo! Gusano del correo. Apareci el 11
de junio de 2006 y fue el primer gusano de interfaz webmail:
601
7- Injection
Otro gusano de webmail de prueba de concepto es Nduja, un gusano entre dominios para
cuatro servicios de webmail italianos. Encuentre ms detalles sobre el trabajo de Rosario
Valotta. Ambos gusanos webmail tienen el objetivo de recolectar direcciones de correo
electrnico, algo con lo que un hacker criminal podra ganar dinero.
La injection de CSS se explica mejor con el conocido gusano Samy de MySpace. Este
gusano envi automticamente una solicitud de amistad a Samy (el atacante) simplemente
visitando su perfil. Dentro de varias horas tuvo ms de un milln de solicitudes de amigos, lo
que cre tanto trfico que MySpace qued fuera de lnea. La siguiente es una explicacin
tcnica de ese gusano.
MySpace bloque muchas etiquetas, pero permiti CSS. As el autor del gusano puso
JavaScript en un CSS como este:
As que la carga til est en el atributo de estilo. Pero no hay cotizaciones permitidas en la
carga til, ya que las comillas simples y dobles ya se han utilizado. Pero JavaScript tiene
una til funcin eval() que ejecuta cualquier cadena como cdigo.
La funcin eval() es una pesadilla para los filtros de entrada de la lista negra, ya que
permite que el atributo de estilo oculte la palabra " innerHTML ":
602
7- Injection
El siguiente problema para MySpace fue filtrar la palabra "javascript", por lo que el autor
utiliz " java <NEWLINE> script " para evitar esto:
Otro problema para el autor del gusano fueron las fichas de seguridad CSRF. Sin ellos no
pudo enviar una solicitud de amistad a travs de POST. Lo consigui enviando un GET a la
pgina justo antes de agregar un usuario y analizar el resultado del token CSRF.
La propiedad CSS de moz-binding result ser otra forma de introducir JavaScript en CSS en
navegadores basados en Gecko (Firefox, por ejemplo).
7.4.1 Contramedidas
Este ejemplo, otra vez, demostr que un filtro de la lista negra nunca esta completo. Sin
embargo, como el CSS personalizado en aplicaciones web es una caracterstica bastante
rara, puede ser difcil encontrar un buen filtro CSS de lista blanca. Si desea permitir colores
o imgenes personalizadas, puede permitir que el usuario las elija y cree el CSS en la
aplicacin web. Utilice el mtodo sanitize() de Rails como modelo para un filtro CSS de
lista blanca, si realmente necesita uno.
Por ejemplo, RedCloth traduce _test_ a <em> test <em> , lo que hace que el texto sea en
cursiva. Sin embargo, hasta la versin actual 3.0.4, sigue siendo vulnerable a XSS. Obtenga
la nueva versin 4 que elimin los errores graves. Sin embargo, incluso esa versin tiene
algunos errores de seguridad, por lo que las contramedidas siguen aplicndose. Aqu hay
un ejemplo para la versin 3.0.4:
Utilice la opcin :filter_html para eliminar HTML que no fue creado por el procesador
Textile.
603
7- Injection
Sin embargo, esto no filtra todo el HTML, se dejarn algunas etiquetas (por diseo), por
ejemplo <a> :
7.5.1 Contramedidas
Se recomienda utilizar RedCloth en combinacin con un filtro de entrada de lista blanca,
como se describe en las contramedidas contra la seccin XSS.
Una contramedida es usar el mtodo del system(command, parameters) que pasa los
parmetros de la lnea de comandos de forma segura.
604
7- Injection
Adems de eso, es importante saber lo que est haciendo al crear cabeceras de respuesta
en parte basadas en la entrada del usuario. Por ejemplo, desea redirigir al usuario de nuevo
a una pgina especfica. Para ello, introdujo un campo "referer" en un formulario para
redirigir a la direccin dada:
Lo que ocurre es que Rails pone la cadena en el campo de encabezado Location y enva un
estado 302 (redirect) al navegador. Lo primero que hara un usuario malintencionado es:
Tenga en cuenta que "%0d%0a" est codificado en URL para " r n", que es un retorno de
carro y un avance de lnea (CRLF) en Ruby. Por lo tanto, el encabezado HTTP resultante
del segundo ejemplo ser el siguiente, porque el segundo campo de encabezado Location
sobrescribe el primero.
Por lo tanto, los vectores de ataque para Header Injection se basan en la inyeccin de
caracteres CRLF en un campo de encabezado. Y qu podra hacer un atacante con una
redireccin falsa? Pueden redirigir a un sitio de phishing que se ve igual que el tuyo, pero
pide volver a iniciar sesin (y enva las credenciales de inicio de sesin al atacante). O
podran instalar software malicioso a travs de los agujeros de seguridad del navegador en
ese sitio. Rails 2.1.2 escapa de estos caracteres para el campo Location en el mtodo
redirect_to . Asegrese de hacerlo usted mismo cuando cree otros campos de
605
7- Injection
606
8- Generacin de consultas inseguras
Un ejemplo de cdigo vulnerable que podra ser utilizado por el atacante, si deep_munge no
se realiz es:
unless params[:token].nil?
user = User.find_by_token(params[:token])
user.reset_password!
end
Cuando params[:token] es uno de: [nil], [nil, nil, ...] o ['foo', nil] se omitir la
prueba de nil , pero IS NULL o IN ( 'foo', NULL ) Donde las clusulas todava se
agregarn a la consulta SQL.
JSON Parameters
{ "person": null } { :person => nil }
config.action_dispatch.perform_deep_munge = false
607
9- Encabezados predeterminados
9- Encabezados predeterminados
Cada respuesta HTTP de su aplicacin Rails recibe los siguientes encabezados de
seguridad predeterminados.
config.action_dispatch.default_headers = {
'X-Frame-Options' => 'SAMEORIGIN',
'X-XSS-Protection' => '1; mode=block',
'X-Content-Type-Options' => 'nosniff'
}
config.action_dispatch.default_headers = {
'Header-Name' => 'Header-Value',
'X-Frame-Options' => 'DENY'
}
config.action_dispatch.default_headers.clear
608
9- Encabezados predeterminados
609
XIX- Debugging de aplicaciones Rails
El propsito de la depuracin.
Cmo detectar problemas e issues en su aplicacin que sus pruebas no estn
identificando.
Las diferentes formas de depuracin.
Cmo analizar el stack trace
610
1- Helpers de las Vistas para depurar
debug
to_yaml
inspect
1.1 debug
El helper debug devolver una etiqueta <pre> que procese el objeto utilizando el formato
YAML . Esto generar datos legibles desde cualquier objeto. Por ejemplo, si tiene este
1.2 to_yaml
Alternativamente, llamar to_yaml a cualquier objeto lo convierte en YAML. Puede pasar
este objeto convertido al mtodo simple_format helper para dar formato a la salida. As es
como debug hace su magia.
611
1- Helpers de las Vistas para depurar
1.3 inspect
Otro mtodo til para mostrar valores de objeto es inspeccionar, especialmente cuando se
trabaja con arrays o hashes. Esto imprimir el valor del objeto como una cadena. Por
ejemplo:
renderizara:
[1, 2, 3, 4, 5]
612
2- El Logger
2- El Logger
Tambin puede ser til guardar informacin en archivos log en tiempo de ejecucin. Rails
mantiene un archivo log separado para cada entorno de tiempo de ejecucin.
2.1 Qu es el logger?
Rails hace uso de la clase ActiveSupport::Logger para escribir informacin de los logs.
Otros logger, como Log4r , tambin pueden ser sustituidos.
config.logger = Logger.new(STDOUT)
config.logger = Log4r::Logger.new("Application Log")
Rails.logger = Logger.new(STDOUT)
Rails.logger = Log4r::Logger.new("Application Log")
Los niveles de log disponibles son: :debug , :info , : warn , :error, :fatal , y
:unknown , correspondiente a los nmeros de nivel de log de 0 a 5, respectivamente. Para
Esto es til cuando desea iniciar sesin bajo develpment o staging sin inundar su log de
produccin con informacin innecesaria.
613
2- El Logger
def create
@article = Article.new(params[:article])
logger.debug "New article: #{@article.attributes.inspect}"
logger.debug "Article should be valid: #{@article.valid?}"
if @article.save
flash[:notice] = 'Article was successfully created.'
logger.debug "The article was saved and now the user is going to be redirected..
."
redirect_to(@article)
else
render action: "new"
end
end
# ...
end
A continuacin se muestra un ejemplo del log generado cuando se ejecuta esta accin del
controlador:
614
2- El Logger
La adicin de logs como ste hace que sea fcil buscar un comportamiento inesperado o
inusual en sus logs. Si agrega extra logs, asegrese de hacer un uso razonable de los
niveles de logs para evitar llenar sus logs de produccin con trivialidades intiles.
logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
logger.tagged("BCX") { logger.info "Stuff" } # Logs "[BCX]
Stuff"
logger.tagged("BCX", "Jason") { logger.info "Stuff" } # Logs "[BCX]
[Jason] Stuff"
logger.tagged("BCX") { logger.tagged("Jason") { logger.info "Stuff" } } # Logs "[BCX]
[Jason] Stuff"
615
2- El Logger
El uso del nivel de :debug tendr una penalizacin de rendimiento mayor que :fatal , ya
que se est evaluando y escribiendo un nmero mucho mayor de cadenas en la salida del
log (por ejemplo, disco).
El contenido del bloque, y por lo tanto la interpolacin de cadena, slo se evalan si debug
est habilitado. Este ahorro de rendimiento slo se nota realmente con grandes cantidades
de logs, pero es una buena prctica por emplear.
616
3- Debugging con la gema byebug
El depurador tambin puede ayudarte si quieres aprender sobre el cdigo fuente de Rails
pero no sabes por dnde empezar. Slo tiene que depurar cualquier solicitud de su
aplicacin y utilizar esta gua para aprender a moverse en el cdigo que ha escrito en el
cdigo Rails subyacente.
3.1 Configuracin
Puede usar la gema byebug para establecer puntos de interrupcin (breakpoints) y pasar a
travs del cdigo en vivo en Rails. Para instalarlo, ejecute:
He aqu un ejemplo:
3.2 El Shell
Tan pronto como su aplicacin llame al mtodo byebug, el debugger se iniciar en una shell
de debbug dentro de la ventana de terminal donde lanz su servidor de aplicaciones, y se
colocar en el prompt del debugger (byebug). Antes de la solicitud, se mostrar el cdigo
alrededor de la lnea que est a punto de ejecutarse y la lnea actual se marcar con ' => ',
as:
617
3- Debugging con la gema byebug
(byebug)
Si llegaste all por una solicitud del navegador, la pestaa del navegador que contiene la
solicitud se congelar hasta que el depurador haya terminado y el trace haya terminado de
procesar toda la solicitud.
Por ejemplo:
618
3- Debugging con la gema byebug
(byebug) help
(byebug)
Para ver las diez lneas anteriores debe escribir list- (or l-).
619
3- Debugging con la gema byebug
(byebug) l-
De esta manera puede moverse dentro del archivo y ver el cdigo por encima de la lnea
donde agreg la llamada byebug. Por ltimo, para ver dnde se encuentra en el cdigo de
nuevo se puede escribir list=
(byebug) list=
3.3 El contexto
Cuando inicie la depuracin de la aplicacin, se colocar en diferentes contextos a medida
que vaya a travs de las diferentes partes del stack.
620
3- Debugging con la gema byebug
(byebug) where
--> #0 ArticlesController.index
at /PathToProject/app/controllers/articles_controller.rb:8
#1 ActionController::BasicImplicitRender.send_action(method#String, *args#Array)
at /PathToGems/actionpack-5.1.0/lib/action_controller/metal/basic_implicit_rende
r.rb:4
#2 AbstractController::Base.process_action(action#NilClass, *args#Array)
at /PathToGems/actionpack-5.1.0/lib/abstract_controller/base.rb:181
#3 ActionController::Rendering.process_action(action, *args)
at /PathToGems/actionpack-5.1.0/lib/action_controller/metal/rendering.rb:30
...
El frame actual est marcado con --> . Puede moverse a cualquier lugar que desee en
este trace (cambiando as el contexto) utilizando el comando frame n , donde n es el
nmero del frame especificado. Si lo hace, byebug mostrar su nuevo contexto.
(byebug) frame 2
Las variables disponibles son las mismas que si estuviera ejecutando el cdigo lnea por
lnea. Despus de todo, eso es lo que es la depuracin.
Tambin puede utilizar los comandos [n] y down [n] para cambiar el contexto n cuadros
hacia arriba o hacia abajo del stack, respectivamente. N por defecto es uno. Up en este
caso es hacia cuadros de stack de numeracin superior, y hacia abajo es hacia el stack de
nmero inferior.
621
3- Debugging con la gema byebug
thread list : se utiliza para enumerar todos los hilos y sus estados. El hilo actual est
Este comando es muy til cuando est depurando subprocesos simultneos y necesita
verificar que no hay condiciones de competencia en su cdigo.
En este ejemplo se muestra cmo se pueden imprimir las variables de instancia definidas
en el contexto actual:
(byebug) instance_variables
[:@_action_has_layout, :@_routes, :@_request, :@_response, :@_lookup_context,
:@_action_name, :@_response_body, :@marked_for_same_origin_verification,
:@_config]
Como se habr dado cuenta, se muestran todas las variables a las que puede acceder
desde un controlador. Esta lista se actualiza dinmicamente a medida que ejecuta el cdigo.
Por ejemplo, ejecute la siguiente lnea usando next (aprender ms sobre este comando
ms adelante en esta gua).
622
3- Debugging con la gema byebug
(byebug) next
(byebug) instance_variables
[:@_action_has_layout, :@_routes, :@_request, :@_response, :@_lookup_context,
:@_action_name, :@_response_body, :@marked_for_same_origin_verification,
:@_config, :@articles]
Ahora @articles se incluye en las variables de instancia, porque la lnea que lo define se
ejecut.
Tambin puede entrar en el modo irb con el comando irb (por supuesto!). Esto
iniciar una sesin irb dentro del contexto en el que la invoc.
[v]ar <subcommand>
623
3- Debugging con la gema byebug
Esta es una excelente forma de inspeccionar los valores de las variables de contexto
actuales. Por ejemplo, para comprobar que no tenemos variables locales definidas
actualmente:
Tambin puede utilizar la pantalla para comenzar a ver las variables. Esta es una buena
forma de rastrear los valores de una variable mientras la ejecucin contina.
Las variables dentro de la lista mostrada se imprimirn con sus valores despus de moverlo
en el stack. Para detener la visualizacin de una variable use undisplay n donde n es el
nmero de variable (1 en el ltimo ejemplo).
624
3- Debugging con la gema byebug
[1, 6] in /PathToProject/app/models/article.rb
1: class Article < ApplicationRecord
2: def self.find_recent(limit = 10)
3: byebug
=> 4: where('created_at > ?', 1.week.ago).limit(limit)
5: end
6: end
(byebug)
(byebug) next
[4, 13] in /PathToProject/app/controllers/articles_controller.rb
4: # GET /articles
5: # GET /articles.json
6: def index
7: @articles = Article.find_recent
8:
=> 9: respond_to do |format|
10: format.html # index.html.erb
11: format.json { render json: @articles }
12: end
13: end
(byebug)
625
3- Debugging con la gema byebug
(byebug) step
actual.
break file:n [if expression] : establece el punto de interrupcin en el nmero de
lnea n dentro del archivo named file. Si se da una expresin se debe evaluar a true
para encender el depurador.
break class(.|\#)method [if expression] : define el punto de interrupcin en el mtodo
626
3- Debugging con la gema byebug
(byebug) break 11
Successfully created breakpoint with id 1
Para eliminar puntos de interrupcin: utilice el comando delete n para quitar el nmero de
punto de interrupcin n. Si no se especifica ningn nmero, elimina todos los puntos de
interrupcin que estn actualmente activos.
(byebug) delete 1
(byebug) info breakpoints
No breakpoints.
627
3- Debugging con la gema byebug
3.10 Edicin
Dos comandos le permiten abrir cdigo desde el depurador en un editor:
edit [file:n] : editar el archivo con el nombre del archivo utilizando el editor especificado
por la variable de entorno EDITOR. Tambin se puede dar una lnea especfica n.
3.11 Quitting
Para salir del depurador, utilice el comando quit (abreviado a q ). O, escriba q! Para
evitar el "Really quit? (y/n)" y salir sin condiciones.
Un simple abandono intenta terminar todos los threads en efecto. Por lo tanto su servidor
ser parado y usted tendr que comenzarlo otra vez.
3.12 Configuracin
Byebug tiene algunas opciones disponibles para ajustar su comportamiento:
628
3- Debugging con la gema byebug
Boolean values take "on", "off", "true", "false", "1" or "0". If you
don't specify a value, the boolean setting will be enabled. Conversely,
you can use "set no<setting>" to disable them.
You can see these environment settings with the "show" command.
629
4- Depuracin con la gema web-console
4.1 Consola
Dentro de cualquier accin o vista del controlador, puede invocar la consola llamando al
mtodo console .
O en una vista:
<h2>New Post</h2>
Esto har que se renderice console dentro de su vista. No necesita preocuparse por la
ubicacin de la llamada a la consola; No se renderizar en el lugar de su invocacin sino
junto a su contenido HTML.
La consola ejecuta cdigo Ruby puro: Puede definir e instanciar clases personalizadas,
crear nuevos modelos e inspeccionar variables.
630
4- Depuracin con la gema web-console
4.3 Ajustes
config.web_console.whitelisted_ips : Lista autorizada de direcciones y redes IPv4 o
Dado que console-web evala el cdigo Ruby en forma remota en el servidor, no intente
utilizarlo en produccin.
631
5- Depuracin de fugas de memoria
En esta seccin, aprender cmo encontrar y corregir dichas filtraciones utilizando una
herramienta como Valgrind .
5.1 Valgrind
Valgrind es una aplicacin para detectar fugas de memoria basadas en C y condiciones de
carrera.
Para obtener ms informacin sobre cmo instalar Valgrind y utilizarla con Ruby, consulte
Valgrind y Ruby por Evan Weaver.
632
6- Plugins para Depurar
Footnotes Cada pgina de Rails tiene notas a pie de pgina que proporcionan
informacin de solicitud y enlace a su fuente a travs de TextMate.
Query Trace Aade el rastreo de origen de consultas a sus logs.
Query Reviewer Este plugin de Rails no slo ejecuta "EXPLAIN" antes de cada una de
sus consultas selectas en desarrollo, sino que proporciona un DIV pequeo en la salida
renderizada de cada pgina con el resumen de advertencias para cada consulta que
analiz.
Exception Notifier Proporciona un objeto de correo y un conjunto predeterminado de
plantillas para enviar notificaciones de correo electrnico cuando se producen errores
en una aplicacin de Rails.
Better Errors Reemplaza la pgina de error de Rails estndar con una nueva que
contiene ms informacin contextual, como el cdigo fuente y la inspeccin de
variables.
RailsPanel Extensin de Chrome para el desarrollo de Rails que pondr fin a su
seguimiento de development.log . Tenga toda la informacin sobre las solicitudes de la
aplicacin Rails en el navegador, en el panel de Herramientas para desarrolladores.
Proporciona informacin sobre db/rendering/total times, lista de parmetros, vistas
renderizadas y ms.
Pry Una alternativa de IRB y una consola de desarrollador de tiempo de ejecucin.
633
XX- Configuracin de aplicaciones de Rails
634
XXI- La lnea de comandos de Rails
635
1- Conceptos bsicos de la lnea de comandos
rails console
rails server
bin/rails
rails generate
rails dbconsole
Todos los comandos pueden ejecutarse con -h o --help para obtener ms informacin.
Vamos a crear una aplicacin Rails simple para pasar a travs de cada uno de estos
comandos en el contexto.
Usted puede instalar la gema de rails escribiendo gem install rails , si usted no la
tiene ya.
Rails te preparar con lo que parece una enorme cantidad de cosas para un comando tan
pequeo! Ahora tiene toda la estructura de directorios de Rails con todo el cdigo que
necesita para ejecutar nuestra aplicacin sencilla justo despus de la caja.
636
1- Conceptos bsicos de la lnea de comandos
Sin ms trabajo, el servidor de rails ejecutar nuestra nueva aplicacin de Rails as:
$ cd commandsapp
$ bin/rails server
=> Booting Puma
=> Rails 5.1.0 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.0.2 (ruby 2.3.0-p0), codename: Plethora of Penguin Pinatas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
Con slo tres rdenes que digit ya tiene a un servidor Rails escuchando en el puerto 3000.
Vaya a su navegador y abra http://localhost:3000 , ver una aplicacin bsica de Rails en
ejecucin.
Tambin puede utilizar el alias " s " para iniciar el servidor: rails s.
Tambin puede usar el alias " g " para invocar el comando del generador: rails g .
637
1- Conceptos bsicos de la lnea de comandos
$ bin/rails generate
Usage: rails generate GENERATOR [args] [options]
...
...
Rails:
assets
controller
generator
...
...
Todas las utilidades de la consola de Rails tienen texto de ayuda. Como con la mayora de
las utilidades de *nix , puede intentar agregar --help o -h al final, por ejemplo, rails
server --help .$ bin/rails generate controller
...
...
Description:
...
To create a controller within a module, specify the controller name as a path like
'parent_module/controller_name'.
...
Example:
`rails generate controller CreditCards open debit credit close`
638
1- Conceptos bsicos de la lnea de comandos
$ bin/rails server
=> Booting Puma...
639
1- Conceptos bsicos de la lnea de comandos
Con una aplicacin Rails normal, las URL seguirn generalmente el patrn
http://(host)/(controller)/(action) , y una URL como http://(host)/(controller\)
...
...
Description:
Create rails files for model generator.
Para obtener una lista de tipos de campos disponibles para el parmetro type ,
consulte la documentacin del API para el mtodo add_column del mdulo
SchemaStatements . El parmetro index genera un ndice correspondiente para la
columna.
640
1- Conceptos bsicos de la lnea de comandos
La migracin requiere que migremos, es decir, ejecutar algn cdigo Ruby (viviendo en aqui
20130717151933_create_high_scores.rb ) para modificar el esquema de nuestra base de
datos. Qu base de datos? La base de datos SQLite3 que Rails crear para usted cuando
ejecute el comando bin/rails db:migrate . Hablaremos ms acerca de bin/rails en
profundidad ms abajo.
641
1- Conceptos bsicos de la lnea de comandos
$ bin/rails db:migrate
== CreateHighScores: migrating ===============================================
-- create_table(:high_scores)
-> 0.0017s
== CreateHighScores: migrated (0.0019s) ======================================
Hablemos de las pruebas unitarias. Las pruebas unitarias son cdigo que prueba y
hace afirmaciones sobre el cdigo. En las pruebas unitarias, tomamos una pequea
parte del cdigo, digamos un mtodo de un modelo, y probamos sus entradas y
salidas. Las pruebas unitarias son tus amigas. Cuanto antes se haga la paz con el
hecho de que su calidad de vida aumentar drsticamente cuando pruebe
unitariamente su cdigo, mejor. Seriamente. Por favor visite la gua de pruebas para
una mirada en profundidad a las pruebas unitarias.
$ bin/rails server
Tambin puede usar el alias " c " para invocar la consola: rails c .
Si desea probar algn cdigo sin cambiar ningn dato, puede hacerlo invocando rails
console --sandobx
642
1- Conceptos bsicos de la lnea de comandos
Con el mtodo app puede acceder a url y los ayudantes de ruta, as como hacer las
solicitudes.
>> app.root_path
=> "/"
>> app.get _
Started GET "/" for 127.0.0.1 at 2014-06-19 10:41:57 -0300
...
>> helper.my_custom_helper
=> "my custom helper"
lnea de comandos que uses con ella (y calcula los parmetros de la lnea de comandos
para darle tambin!). Soporta MySQL (incluyendo MariaDB), PostgreSQL y SQLite3.
Tambin puede utilizar el alias " db " para invocar la dbconsole: rails db .
Tambin puede utilizar el alias " r " para invocar al corredor: rails r .
643
1- Conceptos bsicos de la lnea de comandos
Tambin puede usar el alias " d " para invocar el comando destroy: rails d .
644
2- bin/rails
2- bin/rails
Dado que Rails 5.0+ tiene comandos rake incorporados en los ejecutables, bin/rails es el
nuevo valor predeterminado para ejecutar comandos.
Puede obtener una lista de tareas de bin/rails disponibles, que a menudo dependen de
su directorio actual, escribiendo bin/rails --help . Cada tarea tiene una descripcin, y
debera ayudarle a encontrar lo que necesita.
$ bin/rails --help
Usage: rails COMMAND [ARGS]
All commands can be run with -h (or --help) for more information.
2.1 about
645
2- bin/rails
$ bin/rails about
About your application's environment
Rails version 5.1.0
Ruby version 2.2.2 (x86_64-linux)
RubyGems version 2.4.6
Rack version 2.0.1
JavaScript Runtime Node.js (V8)
Middleware: Rack::Sendfile, ActionDispatch::Static, ActionDispatch::Exec
utor, ActiveSupport::Cache::Strategy::LocalCache::Middleware, Rack::Runtime, Rack::Met
hodOverride, ActionDispatch::RequestId, ActionDispatch::RemoteIp, Sprockets::Rails::Qu
ietAssets, Rails::Rack::Logger, ActionDispatch::ShowExceptions, WebConsole::Middleware
, ActionDispatch::DebugExceptions, ActionDispatch::Reloader, ActionDispatch::Callbacks
, ActiveRecord::Migration::CheckPending, ActionDispatch::Cookies, ActionDispatch::Sess
ion::CookieStore, ActionDispatch::Flash, Rack::Head, Rack::ConditionalGet, Rack::ETag
Application root /home/foobar/commandsapp
Environment development
Database adapter sqlite3
Database schema version 20110805173523
2.2 assets
Puede precompilar los activos en app/assets utilizando los recursos bin/rails
assets:precompile y eliminar los recursos compilados ms antiguos utilizando los recursos
Si desea borrar completamente los elementos public/assets , puede utilizar los recursos
bin/rails assets:clobber .
2.3 db
Las tareas ms comunes del espacio de nombres db : bin / rails son migrate y create , y
vale la pena probar todas las tareas de bin / rails de migracin ( up, down, redo, reset ).
bin / rails db:version es til cuando se soluciona el problema, dicindole la versin
646
2- bin/rails
2.4 notes
bin/rails notes buscar en tu cdigo los comentarios que comiencen con FIXME,
personalizadas.
$ bin/rails notes
(in /home/foobar/commandsapp)
app/controllers/admin/users_controller.rb:
* [ 20] [TODO] any other way to do this?
* [132] [FIXME] high priority for next deploy
app/models/school.rb:
* [ 13] [OPTIMIZE] refactor this code to make it faster
* [ 17] [FIXME]
Si est buscando una anotacin especfica, diga FIXME, puede utilizar bin/rails
notes:fixme . Tenga en cuenta que debe ser en minscula el nombre de la anotacin.
$ bin/rails notes:fixme
(in /home/foobar/commandsapp)
app/controllers/admin/users_controller.rb:
* [132] high priority for next deploy
app/models/school.rb:
* [ 17]
647
2- bin/rails
De forma predeterminada, las notas de rails se vern en los directorios app, config, db,
lib y test . Si desea buscar en otros directorios, puede configurarlos mediante la opcin
config.annotations.register_directories .
config.annotations.register_directories("spec", "vendor")
Tambin puede proporcionarlos como una lista separada por comas en la variable de
entorno SOURCE_ANNOTATION_DIRECTORIES.
$ export SOURCE_ANNOTATION_DIRECTORIES='spec,vendor'
$ bin/rails notes
(in /home/foobar/commandsapp)
app/models/user.rb:
* [ 35] [FIXME] User should have a subscription at this point
spec/models/user_spec.rb:
* [122] [TODO] Verify the user that has a subscription works
2.5 routes
Las rutas de rails mostrarn todas las rutas definidas, lo que es til para rastrear problemas
de enrutamiento en su aplicacin o para darle una buena visin general de las URL de una
aplicacin con la que est tratando de familiarizarse.
2.6 test
Una buena descripcin de las pruebas unitarias en Rails se proporciona en la Gua
para testing para aplicaciones de Rails
Rails viene con una suite de pruebas llamada Minitest. Rails debe su estabilidad al uso de
testing. Las tareas disponibles en el espacio de nombres test: ayudan a ejecutar las
diferentes pruebas que esperamos escribir.
2.7 tmp
El directorio Rails.root/tmp es, al igual que el directorio * nix/tmp , es el lugar de
almacenamiento de los archivos temporales como archivos de id de proceso y acciones
en cach.
648
2- bin/rails
rails tmp:create crea los directorios tmp para el cach, sockets y pids.
2.8 Miscellaneous
rails stats es ideal para ver las estadsticas de su cdigo, mostrando cosas como
rails time:zones:all lista todas las zonas horarias que Rails conoce.
namespace :db do
desc "This task does nothing"
task :nothing do
# Seriously, nothing
end
end
649
2- bin/rails
$ bin/rails task_name
$ bin/rails "task_name[value 1]" # entire argument string should be quoted
$ bin/rails db:nothing
650
3- La Lnea de Comando Avanzada de Rails
Vamos a ver lo que una opcin --git y una opcin --database=postgresql har por
nosotros:
$ mkdir gitapp
$ cd gitapp
$ git init
Initialized empty Git repository in .git/
$ rails new . --git --database=postgresql
exists
create app/controllers
create app/helpers
...
...
create tmp/cache
create tmp/pids
create Rakefile
add 'Rakefile'
create README.md
add 'README.md'
create app/controllers/application_controller.rb
add 'app/controllers/application_controller.rb'
create app/helpers/application_helper.rb
...
create log/test.log
add 'log/test.log'
Tuvimos que crear el directorio gitapp e inicializar un repositorio git vaco antes de que Rails
agregara los archivos creados a nuestro repositorio. Veamos lo que poner en nuestra
configuracin de base de datos:
651
3- La Lnea de Comando Avanzada de Rails
$ cat config/database.yml
# PostgreSQL. Versions 9.1 and up are supported.
#
# Install the pg driver:
# gem install pg
# On OS X with Homebrew:
# gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On OS X with MacPorts:
# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
# gem install pg
# Choose the win32 build.
# Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem 'pg'
#
development:
adapter: postgresql
encoding: unicode
database: gitapp_development
pool: 5
username: gitapp
password:
...
...
La nica captura con el uso de las opciones de SCM es que usted tiene que hacer
primero el directorio de su aplicacin, luego inicializar su SCM, entonces puede
ejecutar el comando rails new para generar la base de su aplicacin.
652
XXII- La Canalizacin de Recursos
653
1- Qu es la Canalizacin de Recursos?
1- Qu es el la Canalizacin de
Recursos?
La canalizacin de recursos proporciona un framework para concatenar y minificar o
comprimir los recursos de JavaScript y CSS. Tambin aade la capacidad de escribir estos
recursos en otros lenguajes y preprocesadores como CoffeeScript, Sass y ERB. Permite
que los recursos de su aplicacin se combinen automticamente con recursos de otras
gemas. Por ejemplo, jquery-rails incluye una copia de jquery.js y habilita las funciones
de AJAX en Rails.
gem 'sass-rails'
gem 'uglifier'
gem 'coffee-rails'
El uso de la opcin --skip-sprockets evitar que Rails los agregue a su Gemfile, por lo que
si posteriormente desea habilitar la canalizacin de los recursos, tendr que agregar esas
gemas a su Gemfile. Adems, la creacin de una aplicacin con la opcin --skip-
sprockets generar un archivo config/application.rb ligeramente diferente, con una
instruccin require para el railtie de los sprockets que estar comentado. Tendr que
quitar el operador de comentario en esa lnea para habilitar ms tarde la canalizacin de los
recursos:
# require "sprockets/railtie"
654
1- Qu es la Canalizacin de Recursos?
config.assets.css_compressor = :yui
config.assets.js_compressor = :uglifier
Sprockets concatena todos los archivos JavaScript en un archivo master .js y todos los
archivos CSS en un archivo master .css . Como veremos ms adelante en esta gua,
puede personalizar esta estrategia para agrupar archivos de la forma que desee. En
produccin, Rails inserta una huella digital SHA256 en cada nombre de archivo para que el
archivo sea almacenado en cach por el navegador web. Puede invalidar la memoria cach
alterando esta huella digital, que ocurre automticamente cada vez que cambia el contenido
del archivo.
655
1- Qu es la Canalizacin de Recursos?
La tcnica Sprockets usada para la huella dactilar es insertar un hash del contenido en el
nombre, generalmente al final. Por ejemplo, un archivo CSS global.css
global-908e25f4bf641868d8683022a5b62f54.css
La vieja estrategia de Rails era aadir un query string basado en la fecha de cada recurso
vinculado con un helper incorporado. La fuente del cdigo generado se vea as:
/stylesheets/global.css?1309495796
La huella dactilar soluciona estos problemas evitando los query string y asegurando que los
nombres de archivo sean consistentes en funcin de su contenido.
656
1- Qu es la Canalizacin de Recursos?
La huella dactilar est habilitada de forma predeterminada para los entornos de desarrollo y
produccin. Puede habilitarlo o deshabilitarlo en su configuracin mediante la opcin
config.assets.digest .
Ms lectura:
Optimize catching
Revving Filenames: don't use querystring
657
2- Cmo utilizar el canalizador de recursos
ubicacin preferida para estos recursos es ahora el directorio app/assets . Los archivos en
este directorio son servidos por el middleware Sprockets.
para archivos que deben someterse a algn pre-procesamiento antes de que se sirvan.
En la produccin, Rails precompila estos archivos en public/assets por defecto. Las copias
precompiladas son servidas como recursos estticos por el servidor web. Los archivos de
app/assets nunca se sirven directamente en produccin.
De forma predeterminada, estos archivos estarn listos para ser utilizados por su aplicacin
inmediatamente usando la directiva require_tree . Vea Manifest Files and Directives para
obtener ms detalles sobre require_tree .
Tambin puede optar por incluir hojas de estilo especficas del controlador y archivos
JavaScript slo en sus respectivos controladores utilizando lo siguiente:
658
2- Cmo utilizar el canalizador de recursos
Debe tener un tiempo de ejecucin soportado por ExecJS para poder utilizar
CoffeeScript. Si est utilizando macOS o Windows, tiene un tiempo de ejecucin de
JavaScript instalado en su sistema operativo. Consulte la documentacin de ExecJS
para conocer todos los tiempos de ejecucin de JavaScript admitidos.
config.generators do |g|
g.assets false
end
Si se est actualizando desde Rails 3, tenga en cuenta que los activos de lib/assets
o vendor/assets estn disponibles para su inclusin a travs de los manifiestos de la
aplicacin, pero ya no forman parte de la matriz de precompilacin. Consulte
Precompilacin de activos para obtener orientacin.
659
2- Cmo utilizar el canalizador de recursos
app/assets/javascripts/home.js
lib/assets/javascripts/moovinator.js
vendor/assets/javascripts/slider.js
vendor/assets/somepackage/phonebox.js
app/assets/javascripts/sub/something.js
es referenciado como:
Adems de los paths assets/* estndar, se pueden agregar rutas adicionales (totalmente
calificadas) a la canalizacin en config/application.rb . Por ejemplo:
660
2- Cmo utilizar el canalizador de recursos
Es importante tener en cuenta que los recursos a los que desea hacer referencia fuera
de un manifiesto deben agregarse a la matriz de precompilacin o no estarn
disponibles en el entorno de produccin.
Por ejemplo, si tiene una biblioteca jQuery con muchos mdulos, que se almacena en
lib/assets/javascripts/library_name , el archivo
archivos de esta biblioteca. Este archivo podra incluir una lista de todos los archivos
necesarios en orden, o una simple directiva require_tree .
Esto simplifica el mantenimiento y mantiene las cosas limpias permitiendo que el cdigo
relacionado se agrupe antes de su inclusin en otro lugar.
661
2- Cmo utilizar el canalizador de recursos
se trata de la misma va. La forma en que se generan estos hashes se trata en la seccin in
Development ms adelante en esta gua.
Esto escribe la ruta del recurso particular al que se est haciendo referencia. En este
ejemplo, tendra sentido tener una imagen en una de las rutas de carga de activos, como
app/assets/images/image.png , que se referenciara aqu. Si esta imagen ya est disponible
Si desea utilizar una URI de datos, un mtodo para incrustar los datos de imagen
directamente en el archivo CSS, puede utilizar el asistente asset_data_uri .
662
2- Cmo utilizar el canalizador de recursos
Tenga en cuenta que la etiqueta de cierre no puede ser del estilo -%> .
Esto escribe la ruta del recurso particular al que se est haciendo referencia.
Del mismo modo, puede utilizar el helper asset_path en archivos CoffeeScript con
extensin erb (por ejemplo, application.coffee.erb ):
663
2- Cmo utilizar el canalizador de recursos
// ...
//= require jquery
//= require jquery_ujs
//= require_tree .
En los archivos JavaScript, las directivas Sprockets comienzan con //= . En el caso
anterior, el archivo utiliza las directivas require y require_tree . La directiva require se
utiliza para decirle a Sprockets los archivos que desea requerir. Aqu, se requieren los
archivos jquery.js y jquery_ujs.js que estn disponibles en algn lugar de la ruta de
bsqueda de Sprockets. No es necesario proporcionar las extensiones explcitamente.
Sprockets asume que est requiriendo un archivo .js cuando se hace desde dentro de un
archivo .js .
Las directivas se procesan de arriba a abajo, pero no se especifica el orden en que los
archivos estn incluidos en require_tree . Usted no debera confiar en cualquier orden
particular entre ellos. Si necesita asegurarse de que algn JavaScript en particular se
encuentre encima de otro en el archivo concatenado, necesitar requerir primero el archivo
previo en el manifiesto. Tenga en cuenta que la familia de directivas require impide que
los archivos se incluyan dos veces en la salida.
/* ...
*= require_self
*= require_tree .
*/
664
2- Cmo utilizar el canalizador de recursos
sprockets se usa al crear una nueva aplicacin de Rails. Esto es as ya que usted puede
Las directivas que funcionan en archivos JavaScript tambin funcionan en las hojas de
estilo (aunque obviamente incluyen hojas de estilo en lugar de archivos JavaScript). La
directiva require_tree en un manifiesto CSS que funciona de la misma forma que con
JavaScript, requiriendo todas las hojas de estilo del directorio actual.
En este ejemplo, require_self se utiliza. Esto coloca el CSS contenido en el archivo (si lo
hay) en la ubicacin exacta de la llamada require_self .
Si desea utilizar varios archivos Sass, debe utilizar la regla Sass @import en lugar de
estas directivas Sprockets. Cuando se utilizan directivas Sprockets, los archivos Sass
existen dentro de su propio mbito, haciendo que las variables o mixins slo estn
disponibles dentro del documento en el que se definieron.
Usted puede hacer el archivo globbing usando tambin @import "*" , e @import "** / *"
para agregar el rbol entero que es equivalente a cmo trabaja require_tree . Revise la
documentacin de sass-rails para obtener ms informacin y advertencias importantes.
Puede tener tantos archivos de manifiesto como necesite. Por ejemplo, el manifiesto
admin.css y admin.js podra contener los archivos JS y CSS que se utilizan para la
/* ...
*= require reset
*= require layout
*= require chrome
*/
2.5 Preprocesamiento
Las extensiones de archivo utilizadas en un recurso determinan qu pre-procesamiento se
aplica. Cuando se genera un controlador o un scaffold con el gemset de Rails
predeterminado, se genera un archivo CoffeeScript y un archivo SCSS en lugar de un
archivo normal de JavaScript y de CSS. El ejemplo utilizado anteriormente era un
665
2- Cmo utilizar el canalizador de recursos
app/assets/stylesheets/projects.scss .
666
3- In Development
3- In Development
En el modo de desarrollo, los recursos se sirven como archivos separados en el orden en
que se especifican en el archivo de manifiesto.
<script src="/assets/core.js?body=1"></script>
<script src="/assets/projects.js?body=1"></script>
<script src="/assets/tickets.js?body=1"></script>
config.assets.raise_runtime_errors = false
Cuando esta opcin es true , la canalizacin de los recursos comprobar si todos los
recursos cargados en su aplicacin estn incluidos en la lista config.assets.precompile . Si
config.assets.digest tambin es true , la canalizacin de recursos requerir que todas
config.assets.unknown_asset_fallback = false
667
3- In Development
config.assets.digest = false
Cuando esta opcin es true , se generarn los digest para las URL de los recursos.
config.assets.debug = false
<script src="/assets/application.js"></script>
Si alguno de los archivos del manifiesto ha cambiado entre las solicitudes, el servidor
responde con un nuevo archivo compilado.
668
3- In Development
669
4- In Production
4- In Production
En el entorno de produccin, Sprockets utiliza el esquema de huellas dactilares descrito
anteriormente. Por defecto, Rails asume que los recursos se han precompilado y sern
servidos como recursos estticos por su servidor web.
Por ejemplo:
<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js"></script>
<link href="/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css" media="screen" r
el="stylesheet" />
670
4- In Production
Puede llamar a esta tarea en el servidor durante la implementacin para crear versiones
compiladas de sus recursos directamente en el servidor. Consulte la siguiente seccin para
obtener informacin sobre cmo compilar localmente.
La tarea es:
Capistrano (v2.15.1 y superior) incluye una receta para manejar esto en el despliegue.
Agregue la siguiente lnea a Capfile :
load 'deploy/assets'
Es importante que esta carpeta se comparta entre implementaciones para que las pginas
remitidas remotamente que hacen referencia a los recursos compilados antiguos funcionen
durante la vida de la pgina almacenada en cach.
Si tiene otros manifiestos u hojas de estilo individuales y archivos de JavaScript para incluir,
puede agregarlos a la matriz de precompilacin en config/initializers/assets.rb :
Siempre especifique un nombre de archivo compilado esperado que termine con .js
o .css , incluso si desea agregar archivos Sass o CoffeeScript al array de
precompilacin.
671
4- In Production
{"files":{"application-aee4be71f1288037ae78b997df388332edfd246471b533dcedaa8f9fe156442
b.js":{"logical_path":"application.js","mtime":"2016-12-23T20:12:03-05:00","size":4123
83,
"digest":"aee4be71f1288037ae78b997df388332edfd246471b533dcedaa8f9fe156442b","integrity"
:"sha256-ruS+cfEogDeueLmX3ziDMu39JGRxtTPc7aqPn+FWRCs="},
"application-86a292b5070793c37e2c0e5f39f73bb387644eaeada7f96e6fc040a028b16c18.css":{"l
ogical_path":"application.css","mtime":"2016-12-23T19:12:20-05:00","size":2994,
"digest":"86a292b5070793c37e2c0e5f39f73bb387644eaeada7f96e6fc040a028b16c18","integrity"
:"sha256-hqKStQcHk8N+LA5fOfc7s4dkTq6tp/lub8BAoCixbBg="},
"favicon-8d2387b8d4d32cecd93fa3900df0e9ff89d01aacd84f50e780c17c9f6b3d0eda.ico":{"logic
al_path":"favicon.ico","mtime":"2016-12-23T20:11:00-05:00","size":8629,
"digest":"8d2387b8d4d32cecd93fa3900df0e9ff89d01aacd84f50e780c17c9f6b3d0eda","integrity"
:"sha256-jSOHuNTTLOzZP6OQDfDp/4nQGqzYT1DngMF8n2s9Dto="},
"my_image-f4028156fd7eca03584d5f2fc0470df1e0dbc7369eaae638b2ff033f988ec493.png":{"logi
cal_path":"my_image.png","mtime":"2016-12-23T20:10:54-05:00","size":23414,
"digest":"f4028156fd7eca03584d5f2fc0470df1e0dbc7369eaae638b2ff033f988ec493","integrity"
:"sha256-9AKBVv1+ygNYTV8vwEcN8eDbxzaequY4sv8DP5iOxJM="}},
"assets":{"application.js":"application-aee4be71f1288037ae78b997df388332edfd246471b533
dcedaa8f9fe156442b.js",
"application.css":"application-86a292b5070793c37e2c0e5f39f73bb387644eaeada7f96e6fc040a
028b16c18.css",
"favicon.ico":"favicon-8d2387b8d4d32cecd93fa3900df0e9ff89d01aacd84f50e780c17c9f6b3d0ed
a.ico",
"my_image.png":"my_image-f4028156fd7eca03584d5f2fc0470df1e0dbc7369eaae638b2ff033f988ec
493.png"}}
Para Apache:
672
4- In Production
Para NGINX:
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
La compilacin local le permite asignar los archivos compilados al control de cdigo fuente e
implementarlos de forma normal.
config.assets.prefix = "/dev-assets"
673
4- In Production
El cambio de prefix hace que los Sprockets usen una URL diferente para servir recurso
en modo de desarrollo y pasen todas las solicitudes a los Sprockets. El prefijo todava est
establecido en /assets en el entorno de produccin. Sin este cambio, la aplicacin servira
los recursos precompilados de /assets en desarrollo y no vera ningn cambio local hasta
que compile los recursos de nuevo.
config.assets.compile = true
group :production do
gem 'therubyracer'
end
4.4 CDNs
674
4- In Production
config.action_controller.asset_host = 'mycdnsubdomain.fictional-cdn.com'
675
4- In Production
Tambin puede establecer este valor a travs de una variable de entorno para facilitar la
ejecucin de una copia provisional de su sitio:
config.action_controller.asset_host = ENV['CDN_HOST']
Una vez que haya configurado su servidor y su CDN cuando sirva una pgina web que
tenga un recurso:
En lugar de devolver una ruta tal como /assets/smile.png (los resmenes se dejan fuera
para facilitar la lectura). La URL generada tendr la ruta completa a su CDN.
http://mycdnsubdomain.fictional-cdn.com/assets/smile.png
Si desea servir slo algunos recursos de su CDN, puede utilizar la opcin personalizada
:host , su helper de recursos, que sobrescribe el valor establecido en
config.action_controller.asset_host .
676
4- In Production
$ curl -I http://www.example/assets/application-
d0e099e021c95eb0de3615fd1d8c4d83.css
HTTP/1.1 200 OK
Server: Cowboy
Date: Sun, 24 Aug 2014 20:27:50 GMT
Connection: keep-alive
Last-Modified: Thu, 08 May 2014 01:24:14 GMT
Content-Type: text/css
Cache-Control: public, max-age=2592000
Content-Length: 126560
Via: 1.1 vegur
$ curl -I http://mycdnsubdomain.fictional-cdn.com/application-
d0e099e021c95eb0de3615fd1d8c4d83.css
HTTP/1.1 200 OK Server: Cowboy Last-
Modified: Thu, 08 May 2014 01:24:14 GMT Content-Type: text/css
Cache-Control:
public, max-age=2592000
Via: 1.1 vegur
Content-Length: 126560
Accept-Ranges:
bytes
Date: Sun, 24 Aug 2014 20:28:45 GMT
Via: 1.1 varnish
Age: 885814
Connection: keep-alive
X-Served-By: cache-dfw1828-DFW
X-Cache: HIT
X-Cache-Hits:
68
X-Timer: S1408912125.211638212,VS0,VE0
677
4- In Production
Compruebe su documentacin del CDN para cualquier informacin adicional que pueden
proporcionar como X-Cache o para cualquier encabezado adicional que puede agregar.
El encabezado de control es una especificacin de la W3C que describe cmo una solicitud
se puede almacenar en cach. Cuando no se utiliza n CDN, un navegador utilizar esta
informacin para almacenar en cach el contenido. Esto es muy til para los recursos que
no se modifican y que un navegador no necesita volver a descargar el CSS de un sitio web
o JavaScript en cada solicitud. Generalmente queremos que nuestro servidor de Rails diga
a nuestro CDN (y navegador) que el recurso es "pblico", lo que significa que cualquier
cach puede almacenar la solicitud. Tambin comnmente queremos establecer max-age ,
que es la cantidad de tiempo que el cach almacenar el objeto antes de invalidar el cach.
El valor max-age se establece en segundos con un valor mximo posible de 31536000 que
es de un ao. Puede hacerlo en su aplicacin Rails estableciendo
config.public_file_server.headers = {
'Cache-Control' => 'public, max-age=31536000'
}
http://mycdnsubdomain.fictional-cdn.com/assets/smile-123.png
http://mycdnsubdomain.fictional-cdn.com/assets/smile.png
678
4- In Production
nombre de archivo diferente cuando se cambie. De esta manera no tendr que invalidar
manualmente ningn elemento de su cach. Al utilizar un nombre de recurso nico y
diferente, sus usuarios obtienen el ltimo recurso.
679
5- Personalizacin del Canalizador
config.assets.css_compressor = :yui
config.assets.css_compressor = :sass
compressor respectivamente.
El Gemfile por defecto incluye uglifier . Esta gema envuelve UglifyJS (escrito para
NodeJS) en Ruby. Se comprime el cdigo mediante la eliminacin de espacios en blanco y
comentarios, acortando los nombres de las variables locales, y la realizacin de otras micro-
optimizaciones, como el cambio de las declaraciones if y else a los operadores
ternarios siempre que sea posible.
config.assets.js_compressor = :uglifier
Necesitar un tiempo de ejecucin soportado por ExecJS para poder usar uglifier .
Si est utilizando macOS o Windows, tiene un tiempo de ejecucin de JavaScript
instalado en su sistema operativo.
680
5- Personalizacin del Canalizador
class Transformer
def compress(string)
do_something_returning_a_string(string)
end
end
config.assets.css_compressor = Transformer.new
config.assets.prefix = "/some_other_path"
Esta es una opcin prctica si est actualizando un proyecto anterior que no se utiliz a la
canalizacin de recursos y ya utiliza esta ruta o desea utilizar esta ruta de acceso para un
recurso nuevo.
681
5- Personalizacin del Canalizador
682
6- Almacn de cach de recursos
config.assets.configure do |env|
env.cache = ActiveSupport::Cache.lookup_store(:memory_store,
{ size: 32.megabytes })
end
config.assets.configure do |env|
env.cache = ActiveSupport::Cache.lookup_store(:null_store)
end
683
7- Agregar recursos a sus gemas
Un buen ejemplo de esto es la gema jquery-rails que viene con Rails como la gema de
biblioteca JavaScript estndar. Esta gema contiene una clase de motor que hereda de
Rails::Engine . Haciendo esto, Rails es informado de que el directorio para esta gema
684
8- Hacer de su libreria o gema un preprocesador
module AddComment
def self.call(input)
{ data: input[:data] + "/* Hello From my sprockets extension */" }
end
end
Ahora que tiene un mdulo que modifica los datos de entrada, es el momento de registrarlo
como un preprocesador para su mime type.
685
9- Actualizacin de versiones antiguas de Rails
En application.rb :
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
# Change the path that assets are served from config.assets.prefix = "/assets"
En development.rb :
Y en production.rb :
686
9- Actualizacin de versiones antiguas de Rails
config.assets.digest = false .
687
XXIII - Trabajar con JavaScript en Rails
688
1- Una introduccin a Ajax
Rails se enva con CoffeeScript de forma predeterminada y, por lo tanto, el resto de los
ejemplos de esta gua aparecern en CoffeeScript. Todas estas lecciones, por supuesto, se
aplican a la JavaScript vanila tambin.
Como ejemplo, he aqu un cdigo de CoffeeScript que hace una solicitud de Ajax usando la
biblioteca jQuery:
Este cdigo recupera los datos de " /test ", y luego agrega el resultado al div con un id
results .
Rails proporciona un poco de soporte incorporado para la construccin de pginas web con
esta tcnica. Rara vez tiene que escribir este cdigo usted mismo. El resto de esta gua le
mostrar cmo Rails puede ayudarle a escribir sitios web de esta manera, pero todo se
basa en esta tcnica bastante simple.
689
2- JavaScript no intrusivo.
2- JavaScript no intrusivo.
Rails utiliza una tcnica llamada "JavaScript no intrusivo" para manejar la accin de adjuntar
JavaScript al DOM. Esto generalmente se considera una mejor prctica dentro de la
comunidad frontend, pero ocasionalmente puede leer tutoriales que muestran otras
maneras de hacerlo.
Esta es la forma ms sencilla de escribir JavaScript. Usted puede ver que esto se conoce
como "JavaScript inline":
Cuando se hace clic, el fondo del enlace se volver rojo. Aqu est el problema: qu ocurre
cuando tenemos un montn de JavaScript que queremos ejecutar en un clic?
Eso es un poco mejor, pero qu pasa si tenemos mltiples enlaces que tienen el mismo
efecto?
690
2- JavaScript no intrusivo.
No muy DRY, eh? Podemos arreglar esto usando los eventos en su lugar. Agregaremos un
atributo data-* a nuestro enlace y, a continuacin, enlazaremos un manejador al evento
click de cada enlace que tenga ese atributo:
$ ->
$("a[data-background-color]").click (e) ->
e.preventDefault()
backgroundColor = $(this).data("background-color")
textColor = $(this).data("text-color")
paintIt(this, backgroundColor, textColor)
691
3- Helpers integrados
3- Helpers integrados
3.1 Elementos remotos
Rails proporciona un montn de mtodos helpers de vista escritos en Ruby para ayudarle a
generar HTML. A veces, usted quiere agregar un poco de Ajax a esos elementos, y Rails le
ayuda en esos casos.
Debido al JavaScript no intrusivo, los "Ajax helpers" de Rails se dividen en dos partes: mitad
JavaScript y mitad Ruby.
Puede leer a continuacin sobre los diferentes eventos que se disparan tratando con
elementos remotos dentro de su aplicacin.
3.1.1 form_with
form_with es un helper que ayuda con la escritura de los formularios. De forma
predeterminada, form_with asume que su formulario utilizar Ajax. Puede inhabilitar este
comportamiento pasando la opcin local :form_with .
Tenga en cuenta el data-remote="true" . Ahora, el formulario ser enviado por Ajax en lugar
de por el mecanismo de envio normal del navegador.
Es probable que no quiera sentarse all con un <form> lleno, sin embargo. Es probable que
desee hacer algo despus de un envo exitosa. Para ello, vincule al evento ajax:success .
En caso de error, utilice ajax:error . Echale un vistazo:
692
3- Helpers integrados
$(document).ready ->
$("#new_article").on("ajax:success", (e, data, status, xhr) ->
$("#new_article").append xhr.responseText
).on "ajax:error", (e, xhr, status, error) ->
$("#new_article").append "<p>ERROR</p>"
Obviamente, usted querr ser un poco ms sofisticado que eso, pero es un comienzo.
3.1.2 link_to
link_to es un helper que ayuda a generar enlaces. Tiene una opcin :remote que
Que genera
Puede vincular los mismos eventos de Ajax como lo hicimos con form_with . He aqu un
ejemplo. Supongamos que tenemos una lista de artculos que se pueden eliminar con un
solo clic. Generaramos un HTML como este:
<%= link_to "Delete article", @article, remote: true, method: :delete %>
$ ->
$("a[data-remote]").on "ajax:success", (e, data, status, xhr) ->
alert "The article was deleted."
3.1.3 button_to
button_to es un helper que te ayuda a crear botones. Tienes una opcin remote que
Esto genera
693
3- Helpers integrados
Dado que es slo un <form> , toda la informacin sobre form_with tambin se aplica.
3.2.1 data-method
Activar hipervnculos siempre da como resultado una solicitud HTTP GET. Sin embargo, si
su aplicacin es RESTful, algunos enlaces son de hecho acciones que cambian datos en el
servidor y deben realizarse con solicitudes que no sean GET. Este atributo permite marcar
tales enlaces con un mtodo explcito como " post ", " put " o " delete ".
La forma en que funciona es que, cuando se activa el enlace, construye un formulario oculto
en el documento con el atributo " action " correspondiente al valor " href " del enlace y el
mtodo correspondiente al valor del data-method y el envio del formulario.
Debido a que el envo de formularios con mtodos HTTP distintos de GET y POST no
es ampliamente aceptado en los navegadores, todos los dems mtodos HTTP se
envan realmente a travs de POST con el mtodo indicado en el parmetro _method .
Rails detecta y compensa automticamente esto.
Esto puede ser til para activar una accin en los check-boxes, por ejemplo:
3.2.3 data-type
694
3- Helpers integrados
3.3 Confirmaciones
Puede solicitar una confirmacin adicional del usuario agregando un atributo de
confirmacin de datos en los vnculos y los formularios. Se mostrar al usuario un dilogo
de confirmacin de JavaScript() que contiene el texto del atributo. Si el usuario decide
cancelar, la accin no tiene lugar.
La adicin de este atributo en los enlaces activar el dilogo al hacer clic y su adicin en los
formularios lo activar al enviar. Por ejemplo:
Esto genera:
Por ejemplo:
695
3- Helpers integrados
696
4- Tratamiento de eventos Ajax
Todos los manejadores vinculados a estos eventos siempre pasan el objeto de evento como
el primer argumento. La siguiente tabla describe los parmetros adicionales que se pasan
despus del argumento del evento. Por ejemplo, si los parmetros adicionales se enumeran
como xhr , settings , entonces para acceder a ellos, se define su manejador con funcin
( event , xhr , settings )
Extra
Event name Fired
parameters
ajax:before
Antes de todo el negocio ajax, aborta si se
detiene.
Antes de enviar la solicitud, se interrumpe si se
ajax:beforeSend xhr, options
detiene.
ajax:send xhr Cuando se enva la solicitud.
ajax:success
xhr, status, Despus de la finalizacin, si la respuesta fue un
err xito.
ajax:error
xhr, status, Despus de la finalizacin, si la respuesta fue un
err error.
Despus de que la solicitud se ha completado,
ajax:complete xhr, status
no importa el resultado.
Si hay entradas de archivo non-blank, se
ajax:aborted:file elements
interrumpe si se detiene.
697
4- Tratamiento de eventos Ajax
698
5- Problemas con el servidor
<b>Users</b>
<ul id="users">
<%= render @users %>
</ul>
<br>
La parte superior de la pgina index muestra los usuarios. La parte inferior proporciona un
formulario para crear un nuevo usuario.
699
5- Problemas con el servidor
UsersController como una solicitud de Ajax, buscando JavaScript. Con el fin de atender a
# app/controllers/users_controller.rb
# ......
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
format.html { redirect_to @user, notice: 'User was successfully created.' }
format.js
format.json { render json: @user, status: :created, location: @user }
else
format.html { render action: "new" }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
700
6- Turbolinks
6- Turbolinks
Rails se suministra con la biblioteca Turbolinks, que utiliza Ajax para acelerar el
procesamiento de pginas en la mayora de las aplicaciones.
Lo nico que tienes que hacer para activar Turbolinks es tenerlo en tu Gemfile, y poner //=
require turbolinks en tu manifiesto de JavaScript, que usualmente es
app/assets/javascripts/application.js .
$(document).ready ->
alert "page has loaded!"
Sin embargo, como Turbolinks anula el proceso normal de carga de pgina, el evento en el
que se basa no se disparar. Si tiene un cdigo similar, debe cambiar el cdigo para
hacerlo:
Para ms detalles, incluyendo otros eventos a los que puedes enlazar, consulta el README
de Turbolinks.
701
6- Turbolinks
702
7- Otros Recursos
7- Otros Recursos
Aqu hay algunos enlaces tiles para ayudarle a aprender an ms:
jquery-ujs wiki
jquery-ujs list of external articles
Rails 3 Remote Links and Forms: A Definitive Guide
Railscasts: Unobtrusive JavaScrip
Railscasts: Turbolinks
703
XXIV- El proceso de inicializacin de Rails
704
XXV- Carga Automatica y recarga de Constantes
705
XXVI- Almacenamiento en cach con Rails: una visin general
706
XXVII- Instrumentacin de Active Support
707
XXVIII- Una gua para perfilar aplicaciones Rails
708
XXIX- Uso de Rails para aplicaciones API-only
709
1 Qu es una aplicacin API?
Por ejemplo, Twitter utiliza su API pblica en su aplicacin web, que se construye como un
sitio esttico que consume recursos JSON.
En lugar de usar Rails para generar HTML que se comunica con el servidor a travs de
formularios y enlaces, muchos desarrolladores estn tratando su aplicacin web como un
cliente API entregado como HTML con JavaScript que consume una API JSON.
Esta gua cubre la creacin de una aplicacin de Rails que sirve recursos JSON a un cliente
de API, incluidos los frameworks del lado del cliente.
710
2 Por qu utilizar Rails para las API de JSON?
Para APIs muy simples, esto puede ser cierto. Sin embargo, incluso en aplicaciones muy
pesadas en HTML, la mayora de la lgica de una aplicacin vive fuera de la capa de la
vista.
La razn por la que la mayora de la gente utiliza Rails es que proporciona un conjunto de
valores predeterminados que permite a los desarrolladores ponerse en marcha
rpidamente, sin tener que tomar muchas decisiones triviales.
Echemos un vistazo a algunas de las cosas que Rails ofrece fuera de la caja que siguen
siendo aplicables a las aplicaciones API.
711
2 Por qu utilizar Rails para las API de JSON?
Si bien obviamente podra construir esto en trminos de middleware de rack existentes, esta
lista demuestra que el stack de middleware de Rails predeterminado proporciona mucho
valor, incluso si est "generando JSON".
Enrutamiento Resourceful: si est creando una API JSON RESTful, desea utilizar el
enrutador de Rails. El mapeo limpio y convencional de HTTP a controladores significa
no tener que pasar tiempo pensando en cmo modelar su API en trminos de HTTP.
Generacin de URLs: La otra cara del enrutamiento es la generacin de las URLs. Una
buena API basada en HTTP incluye URLs (consulte el GitHub Gist API para ver un
ejemplo).
Encabezado y Redireccin de Respuestas: head: no_content y redirect_to
user_url(current_user) vienen a mano. Claro, puede aadir manualmente los
712
2 Por qu utilizar Rails para las API de JSON?
Por supuesto, el proceso de arranque de Rails tambin encola todos los componentes
registrados. Por ejemplo, el proceso de arranque de Rails utiliza su archivo
config/database.yml al configurar Active Record.
La versin corta es: es posible que no haya pensado en qu partes de Rails siguen siendo
aplicables incluso si se elimina la capa de vista, pero la respuesta resulta ser la mayor
parte.
713
3- La configuracin bsica
3- La configuracin bsica
Si est creando una aplicacin de Rails que ser un servidor API en primer lugar, puede
comenzar con un subconjunto ms limitado de Rails y agregar funciones segn sea
necesario.
config.api_only = true
Para renderizar una pgina HTML con informacin de depuracin, utilice el valor :default .
714
3- La configuracin bsica
config.debug_exception_response_format = :default
config.debug_exception_response_format = :api
hacer:
715
4- Eleccin de middleware
4- Eleccin de middleware
Una aplicacin de API viene con el siguiente middleware de forma predeterminada:
Rack::Sendfile
ActionDispatch::Static
ActionDispatch::Executor
ActiveSupport::Cache::Strategy::LocalCache::Middleware
Rack::Runtime
ActionDispatch::RequestId
ActionDispatch::RemoteIp
Rails::Rack::Logger
ActionDispatch::ShowExceptions
ActionDispatch::DebugExceptions
ActionDispatch::Reloader
ActionDispatch::Callbacks
ActiveRecord::Migration::CheckPending
Rack::Head
Rack::ConditionalGet
Rack::ETag
MyApi::Application::Routes
Puede obtener una lista de todos los middleware en su aplicacin a travs de:
$ rails middleware
716
4- Eleccin de middleware
def show
@post = Post.find(params[:id])
if stale?(last_modified: @post.updated_at)
render json: @post
end
end
Normalmente, este mecanismo se utiliza en una base por cliente. El middleware de cach
nos permite compartir este mecanismo de almacenamiento en cach entre los clientes.
Podemos habilitar el almacenamiento en cach de varios clientes en la llamada para
stale? :
def show
@post = Post.find(params[:id])
Esto significa que el middleware de cach almacenar el valor Last-Modified para una
URL en la cach de Rails y agregar un encabezado If-Modified-Since a cualquier
solicitud de entrada posterior para la misma URL.
Puede configurar el nombre del encabezado que utiliza su servidor front-end con este fin
utilizando config.action_dispatch.x_sendfile_header en el archivo de configuracin del
entorno apropiado.
717
4- Eleccin de middleware
Estos son algunos valores para esta cabecera para algunos servidores populares, una vez
que estos servidores estn configurados para admitir el envo acelerado de archivos:
# Nginx
config.action_dispatch.x_sendfile_header = "X-Accel-Redirect"
Asegrese de configurar su servidor para que admita estas opciones siguiendo las
instrucciones de la documentacin de Rack::Sendfile .
Para usar esto, su cliente necesitar hacer una peticin con parmetros codificados por
JSON y especificar el Content-Type como application/json .
jQuery.ajax({
type: 'POST',
url: '/people',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({ person: { firstName: "Yehuda", lastName: "Katz" } }),
success: function(json) { }
});
Rack::MethodOverride
718
4- Eleccin de middleware
ActionDispatch::Cookies
ActionDispatch::Flash
ActionDispatch::Session::CookieStore
ActionDispatch::Session::MemCacheStore
config.middleware.use Rack::MethodOverride
config.middleware.delete ::Rack::Sendfile
719
5- Seleccin de los mdulos del controlador
renderizado.
ActionController::Renderers::All: Soporte para renderizar :json y amigos.
anidado, para que no tenga que especificar elementos raz que envan peticiones
POST por ejemplo.
ActionController::Head : Soporte para devolver una respuesta sin contenido, solo
encabezados
Otros complementos pueden agregar mdulos adicionales. Puede obtener una lista de
todos los mdulos incluidos en ActionController::API en la consola de rails:
720
5- Seleccin de los mdulos del controlador
$ bin/rails c
>> ActionController::API.ancestors - ActionController::Metal.ancestors
=> [ActionController::API,
ActiveRecord::Railties::ControllerRuntime,
ActionDispatch::Routing::RouteSet::MountedHelpers,
ActionController::ParamsWrapper,
... ,
AbstractController::Rendering,
ActionView::ViewPaths]
traduccin de l y t .
ActionController::HttpAuthentication::Basic (or Digest or Token): Soporte para la
721
XXX- Descripcin de Action Cable
722