SlideShare une entreprise Scribd logo
1  sur  45
Cuatro Dias
 con Rails




      compilado por John McCreesh
        traducción por Emmanuel N. Millán
Tabla de Contenidos
Introducción ...................................................................................................................................................1
Día 1 con Rails ...............................................................................................................................................3
    La aplicación ‘Lista de Tareas’ .............................................................................................................3
    Ejecutar el script de Rails ......................................................................................................................3
    Agregar la aplicación al servidor Web ...............................................................................................3
       Definir la aplicación en el archivo de hosts ...............................................................................3
       Definir la aplicación en el archivo de configuración de Apache .........................................3
       Cambiar a fastcgi ................................................................................................................................4
       Chequear que Rails este funcionan d o ..........................................................................................4
       Versiones de Rails ..............................................................................................................................4
    Configurar la Base de Datos .................................................................................................................4
       Crear la tabla Categorias ..................................................................................................................5
         Definición MySQL..........................................................................................................................5
         Modelo de Datos ............................................................................................................................5
    Scaffold .......................................................................................................................................................5
    Realzar el Modelo .....................................................................................................................................6
       Crear reglas de validación de datos ..............................................................................................7
Dia 2 con Rails ...............................................................................................................................................9
    El código generado Scaffold .................................................................................................................9
       El controlador ......................................................................................................................................9
       La Vista ................................................................................................................................................1 1
          Layout .............................................................................................................................................11
          Template (plantilla) ....................................................................................................................12
          Partial (parcial) .............................................................................................................................12
          La vista de renderiza do para la acción “New” ....................................................................13
          Analizando la vista de la acción ‘List’...................................................................................14
    Modificar el código generado por Scaffold ...................................................................................16
       El controlador ....................................................................................................................................16
       La Vista (View)...................................................................................................................................16
          Mostrar mensajes Flash .............................................................................................................16
          Compartir variables entre la plantilla y el Layout ............................................................17
          Atando las pantallas de Edit y New .......................................................................................18
Día 3 con Rails ............................................................................................................................................19
    La tabla ‘Items’ .......................................................................................................................................19
       Definición MySQL de la tabla ........................................................................................................19
       El Modelo .............................................................................................................................................19
          Validar los links entre las tablas ............................................................................................20
          Validar la entrada del usuario .................................................................................................20
    La tabla de ‘Notas’.................................................................................................................................20
       Definición de la tabla MySQL........................................................................................................20
       El modelo ............................................................................................................................................21
          Usar un Modelo para mantener Integridad Referencial ..................................................21
    Mas de Scaffold ......................................................................................................................................22
    Mas acerca de Vistas .............................................................................................................................22
       Crear un Layout para la Aplicación ............................................................................................22
       La pantalla ‘Lista de tareas’ ...........................................................................................................23
          Eliminar ‘tareas’ completadas haciendo click en un ícono ............................................24
          Cambiar el modo de ordena mien t o haciendo click en el Encabezado de la
          Columna .........................................................................................................................................24
          Agregar el Helper ........................................................................................................................25
          Usar botónes de navegación Javascript ................................................................................25
          Formatear una Tabla con un Parcial ......................................................................................25
Formato basado en el valor de los Datos ............................................................................27
         Manejar valores perdidos en una busqued a ......................................................................27
      La pantalla ‘Nueva Tarea’...............................................................................................................27
         Crear una lista desplegable para el campo fecha ..............................................................28
         Atrapar excepciones con Ruby ................................................................................................28
         Crear una lista desplegable desde una tabla de busqueda ............................................29
         Crear una lista desplegable para la lista de constant es ..................................................29
         Crear una casilla de verificación ............................................................................................29
    Toques finales ........................................................................................................................................29
      Modificar la hoja de estilos ...........................................................................................................29
      La pantalla ‘Editar Tarea’...............................................................................................................30
Dia 4 con Rails ............................................................................................................................................31
    Las pantallas ‘Notas’.............................................................................................................................31
       Enlazand o ‘Notas’ con ‘Editar Tarea’..........................................................................................31
       La pantalla ‘Editar Notas’ ...............................................................................................................32
       La pantalla de ‘Nota Nueva’...........................................................................................................33
          Guardar y traer Datos usando variables de Sesión ...........................................................33
    Cambiar la pantalla de ‘Categorias’ .................................................................................................34
    Navegación a traves del sistema .......................................................................................................34
    Descargar una copia de esta aplicación ..........................................................................................35
    Y finalmente ............................................................................................................................................35
Apéndice – Cambios posteriores ..........................................................................................................37
    Actualizaciones Multiples ...................................................................................................................37
      View......................................................................................................................................................37
      Controlador ........................................................................................................................................38
      Consideraciones de la interfaz de usuario ...............................................................................39
    Todavía para hacer ................................................................................................................................39
Introducción

Han habido varias deman da s extravagantes hechas acerca de Rails. Por ejemplo, un
articulo publicado en OnLAMP.com 1 deman da n d o que “puedes desarrollar una aplicación
web por lo menos diez veces mas rápido con Rails que con un tipico framework Java...” El
artículo luego muestra como instalar Rails y Ruby en una PC y contruir una aplicación
funcionan d o con “scaffold” virtualmen te sin código.

Mientras que esto es impresiona nt e, desarrolladores web “reales” saben que esto es humo
y espejos. aplicaciónes ‘reales’ no son tan simples como eso. ¿Qué es realmen te lo que
esta pasan do debajo de la superficie? ¿Qué tan dificil es construir aplicaciónes web
‘reales’?

Aqui es donde la vida se vuelve un poco difícil. Rails tiene muy buena documen t ación
on - line, de hecho, posiblement e esta demasiado bien docume n t a d o para principiantes,
con mas de 30.000 palabras de docume n t ación on- line en el formato de manual de
referencia. Lo que esta faltando en un road ma p (railmap?? - mapa del camino) apunta n d o
a las páginas claves que necesitas saber para comen za r a desarrollar con Rails.

Este documen t o está para llenar ese vacio. Asume que ya tienes Ruby y Rails en
funciona mient o en una PC (si no has llegado tan lejos, ve devuelta y sigue el articulo de
Curt). Esto te lleva al final de ‘Dia 1 con Rails’.

‘Dia 2 con Rails’ comienza posicionan d o se detras del humo y los espejos. Lo lleva a traves
del código ‘scaffold’. Nuevas características son remarcadas en negrita, explicadas en el
texto, y seguidas por una referencia a la documen t acio de Rails o de Ruby donde puedes
aprender más.

‘Dia 3 con Rails’ toma scaffold y comien za a construir algo reconocible como una
aplicación “real”. Todo el tiempo, esta contruyen d o su propia caja de herra mient as con
Rails. Lo mas importa nt e de todo, deberia también sentirse comodo con la
documen t ación en linea para que pueda continuar con la exploración usted solo.

‘Dia 4 con Rails’ agrega otra tabla y trata con algunas de las complejidades de mantene r
la integridad referencial. Al final, tendra una aplicación en funciona mient o, suficientes
herra mient as como para comenza r, y el conocimient o de donde buscar mas información.

Diez veces mas rápido? Después de cuatro dias con Rails, juzguelo por usted mismo!

Documentación : este documen t o contiene referencias destacadas, a cualquiera de los
siguientes sitios:

• Docu m e nt ación – La d oc u m e n t ació n d e Rails en h t t p: / / a pi.r u byo n rails.co m (Esta
  d oc u m e n t ació n t a m bié n est a inst ala d a en s u PC co m o p a r te d e la ins talación d e ge m s
  u bica d a en u n lugar co m o C:Program Filesrubylibrubygemsn.ndocactionpack-
  n.n.nrdocindex.html)
• Rub y Docu m e n t ación – “Progra m mi ng Ruby - The Prag m a tic Progra m m e r's Guide”
  dis p o nible en linea y p a ra bajar en h t t p: / / www.ru by - d oc.org / d ocs / r u by - d oc -
  b u n dle /Progra m mi ngRuby /i n d ex.ht ml




1 Rolling with Ruby on Rails, Curt Hibbs 20- Jan2005
  http: / / w ww.onla m p.co m / p u b / a / o n l a m p / 2 0 0 5 / 0 1 / 2 0 / r a ils.ht m l

                                                                                                       Página 1
Reconocimiento s : m u c h as gracias a la ge n te en el canal irc 2 y e n la lista d e correo 3 . El
regist ro d e arc hivos e n linea fue u n a invaluable asiste ncia m ie n t ras a p re n dia Rails y
Ruby.

Versión: 2.3 usand o la versión 0.12.1 de Rails – vea http: / / r ails.ho melin ux.org para la
última versión y para bajar una copia del futuro código. Document o escrito y pdf
generado con OpenOffice.org 'Writer'.

Copyright : este trabajo tiene copyright ©2005 John McCreesh
jpmcc@users.sourceforge.net y esta bajo la licencia Creative Com mo ns Attribution -
NonCo m m e rcial - ShareAlike License . Para ver una copia de esta licencia, visite
http: / / c re a tiveco m m o n s.org / licenses / b y - nc- sa/2.0 / o envie una carta a Creative
Commo ns, 559 Nathan Abbott Way, Stanford, California 94305, USA.




2 irc:/ /i rc.freeno de.org / r u byon rails
3 http: / / li s t s.rubyonrails.org / m a il m a n / li s tinfo / r ails

Página 2
Día 1 con Rails
La aplicación ‘Lista de Tareas’
Este d oc u m e n t o sig ue la co n s t r ucción d e u n a si m ple a plicació n d e “lista d e ta reas” – el
ti p o d e cosa q ue tienes e n t u PDA, co n u n a lista d e ite m s, agr u p a d o s e n categorias, con
n o ta s o pcio nales (para ver u n a a delan t o d e co m o se va a ver, vea Ilustración 5: La p a nt alla
de ‘Lista de T areas’ en la p ági na 2 3 ).

Ejecutar el script de Rails
Este ejemplo esta en mi PC MS- Windows. Mi material de web esta en c:wwwwebroot, que
etiqueto como mi disco w: para acortar el tipeo:

 C:> subst w: c:wwwwebroot
 C:> w:
 W:> rails ToDo
 W:> cd ToDo
 W:ToDo>

Ejecutar rails ToDo crea un nuevo directorio ToDo y lo puebla con una serie de archivos y
subdirectorios, los mas importan t es de estos son los siguientes:

 app
    contiene el nucleo de la aplicación, dividida en los subdirectorios modelos (model),
    vistas(view), controladores(controller), y 'ayudantes'(helper)
 config
    contiene el archivo database.yml que provee detalles de la base de datos a utilizar
    con la aplicación
 log
    registros especificos de la aplicación. Nota: development.log mantiene una traza de
    cada acción que Rails realiza – muy util para rastrear errores, pero no necesita
    ser purgado regularmente!
 public
    el directorio disponible para Apache, que incluye imagenes, javascripts, y
    subdirectorios para stylesheets


Agregar la aplicación al servidor Web
Como yo estoy ejecutand o todo (Apache2, MySQL, etc) en una sola PC de desarrollo, los
siguientes dos pasos dan un nombre amigable para la aplicación en mi navegador.

Definir la aplicación en el archivo de hosts
 C:winntsystem32driversetchosts (fragmento)
 127.0.0.1 todo

Definir la aplicación en el archivo de configuración de Apache
 Apache2confhttpd.conf
 <VirtualHost *>
   ServerName todo
   DocumentRoot /www/webroot/ToDo/public
   <Directory /www/webroot/ToDo/public/>
     Options ExecCGI FollowSymLinks
     AllowOverride all
     Allow from all
     Order allow,deny
   </Directory>
 </VirtualHost>



                                                                                                    Página 3
Cambiar a fastcgi
A menos que sea paciente (o que tenga una PC potente) deberia habilitar fastcgi para esta
aplicación.
 public.htaccess
 # Para mejor desempeño reemplaze el despachador con el de fastcgi
 RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

Chequear que Rails este funcionando
El sitio ahora deberia ser visible en su navegador como http://todo/ (debería ver la página
Congratulations, you've put Ruby on Rails! en su navegador).

Versiones de Rails
Para el m o m e n t o q ue leas este d oc u m e n t o, Rails p r o b able me n te h aya ava n z a d o varias
versió nes. Si inte n t as avan za r a t raves d e este d oc u m e n t o, cheq uea la versión ins tala da en
t u PC:
 W:ToDo>gem list --local


Si s o n dis tin ta s a las versió ne s lista da s abajo, e n t o nces yo fue rte m e n te aco n sejaria q u e
baje las versió nes u s a d a s en “Cuat ro dias co n Rails”, eje m plo:
 W:ToDo>gem install rails --versión 0.12.1


Esto n o ro m p e ra n a d a; la libreria ge m s d e Ruby es ta di se ña d a p a ra m a neja r m ul ti ples
versió nes. Ento nces p ue de for z a r a Rails a q u e u se las versió nes u tili za d a s e n “Cuat ro
Dias” en la a plicación ‘Lista d e Tareas’ es pecifican d o:
 configenvironment.rb (fragmento)
 # Require Rails libraries.
 require 'rubygems'
 require_gem 'activesupport', '= 1.0.4'
 require_gem 'activerecord', '= 1.10.1'
 require_gem 'actionpack', '= 1.8.1'
 require_gem 'actionmailer', '= 0.9.1'
 require_gem 'actionwebservice', '= 0.7.1'
 require_gem 'rails', '= 0.12.1'


La ra z ó n p a ra u sa r la m i s m a versió n es m uy si m ple. ‘Cuat ro Dias’ u s a m uc h o có digo
genera d o a u t o m a tica me n te p o r Rails. Mient ras Rails se d e sa r rolla, t a m bié n lo h ace es te
có digo – d e safo rt u n a d a m e n t e, es te d oc u m e n t o n o lo h ace (hasta q ue se p r o d uce u n a
n u eva versió n!). Ento nces, h a s t u vida fácil, y m a n t e ne la m i s m a versió n q u e se u sa e n
‘Cuat ro Dias’. Una ve z q ue h ayas t er mi na d o d e t rabajar co n ‘Cuatro Dias’, ve a la úl ti ma y
gra n versió n d e Rails y ve q ue m ejo ra s los d e sa rr ollad o res d e Rails h a n reali za d o.

Configurar la Base de Datos
He configurad o una nueva base de datos llamada ‘todos’ en MySQL. La conexión a la base
de datos es especificada en el archivo configdatabase.yml

 configdatabase.yml (fragmento)
 development:
   adapter: mysql
   database: todos
   host: localhost
   username: foo
   password: bar


Página 4
Crear la tabla Categorias
La tabla categories (categorias) es utilizada en los ejemplos siguientes. Es una simple lista
de categorias que seran usadas para agrupar los items en la Lista de Tareas.

Definición MySQL
    Tabla Categories
    CREATE TABLE `categories` (
      `id` smallint(5) unsigned NOT NULL auto_increment,
      `category` varchar(20) NOT NULL default '',
      `created_on` timestamp(14) NOT NULL,
      `updated_on` timestamp(14) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `category_key` (`category`)
    ) TYPE=MyISAM COMMENT='List of categories';

Algunos tips para los nombres de las tablas y campos:

•  Guiones bajos en el nombre de los campos seran cambiados por espacios por Rails
   para obtener nombres ‘amigables al humano’
• tener cuidado con la mezcla de mayusculas y minisculas en el nombre del campo –
   algunas partes del código de Rails son sensibles a mayusculas y minisculas.
• Cada tabla deberia tener una clave primaria llamada ‘id ’ - en MySQL es mas fácil tener
   este campo como un numeric auto_increment
• enlaces a otras tablas deberian seguir la misma convencion de nombre ‘_id’
• Rails auto matica men t e manten d r a los campos llamados created_at/created_on o
   updated_at/updated_on, entonces es una buena idea agregarlos
 Document ación: ActiveRecord::Timesta m p
• Tip útil: si esta construyen d o un sistema multiusuario (no es relevante aqui), Rails
   también utilizara el bloqueo optimista si agrega un campo llamado lock_versión
   (integer default 0). Todo lo que necesita recordar es incluir lock_versión como un
   campo oculto en sus formularios de actualización.
 Document ación: ActiveRecord::Locking

Modelo de Datos
Genera un archivo vacio:

    W:ToDo>ruby script/generate model category
          exists app/models/
          exists test/unit/
          exists test/fixtures/
          create app/models/category.rb
          create test/unit/category_test.rb
          create test/fixtures/categories.yml

    W:ToDo>
q ue crea u n archivo category.rb, y d o s arc hivos d e p r u eba category_controller_test.rb y
categories.yml. Agregare m o s algu na s en t ra d a s e n el m o d elo d e d a t o s e n u n mi n u t o –
d ejelo vacio p o r el m o m e n t o.

Scaffold
El controlador es el corazón de la aplicación Rails.
    Ejecutar el script generador del controlador
    W:ToDo>ruby script/generate controller category
          exists app/controllers/


                                                                                                 Página 5
exists    app/helpers/
        create    app/views/category
        exists    test/functional/
        create    app/controllers/category_controller.rb
        create    test/functional/category_controller_test.rb
        create    app/helpers/category_helper.rb

 W:ToDo>

que crea dos archivos y dos directorios vacios:
appcontrollerscategory_controller.rb
apphelperscategory_helper.rb
appviewscategories
appviewslayouts

Si no ha visto el truco modelo / scaffold en funciona mient o en un tutorial de principiante
como “Rolling with Ruby on Rails”, pruebelo ahora y asombrese de como toda una
aplicación web puede estar escrita en una sola linea de código:
 appcontrollerscategory_controller.rb
 class CategoryController < ApplicationController
   scaffold :category
 end
Document ación: ActionController::Scaffolding

Ap u n te s u n avega d o r a http://todo/category y a d mi re q ue t a n ingenioso es : - )




  Ilustración 1 : pantalla 'Lista' Scaffold

Para averigüar q u e ta n inge nioso n o es, inte n te agregar la m i s m a categoria d o s veces.
Rails fracasa rá y d a ra u n s ucio m e n saje d e erro r ‘ActiveRecor d::State me n tInvalid in
Category#create’. Pue de ar reglar est o agrega n d o validació n al Modelo.

Realzar el Modelo
El Modelo es donde toda las reglas relacionadas con datos son guarda das, incluida la
validación y integridad relacional. Esto significa que puede definir una sola regla, y Rails
automáticame n t e la aplicará donde sea que el dato es accedido.



Página 6
Crear reglas de validación de datos
Rails otorga mucho manejo de errores gratis (casi). Para demost rar esto, agregue algunas
reglas de validación al modelo de categoría vacio:
    appmodelscategory.rb
    class Category < ActiveRecord::Base
      validates_length_of :category, :within => 1..20
      validates_uniqueness_of :category, :message => "already exists"
    end

Estas entradas automa tica men t e chequearan que:

•    validates_length_of: el ca m p o n o este en vacio y n o sea m uy largo
•    validates_uniqueness_of: valores d u plica d os so n at ra p a d o s. No m e gu s t a
                                                                                         el m e n s aje d e
     erro r p o r d efecto d e Rails - ‘xxx has already been taken’ - en t o nces d oy   mi p r o pio
  m e n s aje. Esta es u n a característica general d e Rails – p ri m e ro p r u ebe los valores p o r
  d efecto, si n o le g us t a n, s ob reescribalos.
Document ación: ActiveRecord::Validations::ClassMethods




                                                                                                  Página 7
Para p r o ba r es to, a h o ra inte n t a agregar u n regist ro d u plica d o d e n u evo. Esta ve z, Rails
m a n eja el erro r e n ve z d e “ro m p e r se” - vea abajo. El estilo es ta u n p oco en s u cara – n o
es la in terfa z d e u s u a rio m a s s u til. De t o d a s for m a s, q ue es pera si es gratis?




   Ilustración 2 : Capturan d o errores de datos




Página 8
Dia 2 con Rails
Para progresar mas alla de este punto, necesita mo s ver que esta pasando detras de la
escena. Durante el dia 2, trabajare m o s sistematica me n t e a traves del código scaffold
generado por Rails, decifrando que significa todo. Con la acción scaffold, Rails genera
todo el código que necesita dinámica me n t e. Ejecutando scaffold como un script , podemo s
obtener todo el código escrito al disco donde lo pode mo s investigar y luego comen za r a
modificarlo para ajustarse a nuestros requeri mient os.
 Ejecutar el script generate scaffold
 W:ToDo>ruby script/generate scaffold category
   dependency model
       exists    app/models/
       exists    test/unit/
       exists    test/fixtures/
         skip    app/models/category.rb
         skip    test/unit/category_test.rb
         skip    test/fixtures/categories.yml
       exists app/controllers/
       exists app/helpers/
       create app/views/categories
       exists test/functional/
       create app/controllers/categories_controller.rb
       create test/functional/categories_controller_test.rb
       create app/helpers/categories_helper.rb
       create app/views/layouts/categories.rhtml
       create public/stylesheets/scaffold.css
       create app/views/categories/list.rhtml
       create app/views/categories/show.rhtml
       create app/views/categories/new.rhtml
       create app/views/categories/edit.rhtml
       create app/views/categories/_form.rhtml

 W:ToDo>

Este script genera un rango de archivos necesarios para crear una aplicación completa,
incluyendo un controlador, vistas, layouts, e incluso hojas de estilo (css).

Note la p e q u e ña bi za r ra convenció n d e n o m b res – n o s h e m o s m ovi do d el si ng ular a
pl u ral, e n t o nces p a ra u s a r el n u evo có digo n ecesita a p u n t a r el n avega d o r a
http://todo/categories. De hec ho, p a ra evitar co nf u sio ne s, es m ejo r bo rra r
appcontrollerscategory_controller.rb etc e n caso d e q ue lo ejecute accide n tal me n te.


El código generado Scaffold
El controlador
Vea m o s el có digo d e t ra s d el co n t rola d o r. El co n t rola d o r es d o n d e d e sca n sa la
p r og ra m ació n lógica d e la a plicación. Interact ua con el u s u a rio u sa n d o vistas (views), y
con la base d e d a t o s a t raves d e los m o d elos (mo dels). Deberia p o d e r leer el con t rola d o r y
ver co m o la a plicació n esta u ni da.
El controlador producido por el script generar scaffold es listado abajo:
 appcontrollerscategories_controller.rb
 class CategoriesController < ApplicationController
   def index
     list
     render_action 'list'
   end

    def list


                                                                                                    Página 9
@category_pages, @categories = paginate :category, :per_page => 10
      end

      def show
        @category = Category.find(@params[:id])
      end

      def new
        @category = Category.new
      end

      def create
        @category = Category.new(@params[:category])
        if @category.save
          flash['notice'] = 'Category was successfully created.'
          redirect_to :action => 'list'
        else
          render_action 'new'
        end
      end

      def edit
        @category = Category.find(@params[:id])
      end

      def update
        @category = Category.find(@params[:id])
        if @category.update_attributes(@params[:category])
          flash['notice'] = 'Category was successfully updated.'
          redirect_to :action => 'show', :id => @category
        else
          render_action 'edit'
        end
      end

      def destroy
        Category.find(@params[:id]).destroy
        redirect_to :action => 'list'
      end
    end



Cuando el usuario de la aplicación Rails selecciona una acción – ejemplo: ‘Show’ (mostrar)
– el controlador ejecutará cualquier código de la sección apropiada – ‘def show’ - y luego
por defecto renderizara una plantilla con el mismo nomb re - ‘show.rthml’. Este
comport a mi en t o por defecto puede ser sobreescrito:

•    render_template le permite renderizar una plantilla diferente – ejemplo: la acción index
   ejecutara el código de la acción ‘list’ - ‘def list’, y renderizara list.rhtml en vez
   de index.rhtml (que no existe)
• redirect_to va un nivel mas alla, y utiliza una respuesta externa HTTP ‘302 moved’
   para volver al controlador – ejemplo: la acción destroy no necesita renderizar una
   plantilla. Despues de realizar su proposito principal (destruir una categoria),
   simpleme n t e lleva al usuario a la acción list.
 Document ación: ActionController::Base

El controlador ActiveRecord usa métodos como find (encontrar), find_all (encontrar
todos), new (nuevo), save (guardar), update_attributes (actualizar atributos), y destroy
(destruir) para mover datos a y desde las tablas de la base de datos. Note que no tiene
que escribir ninguna sentencia SQL, pero si desea ver que SQL Rails esta usando, esta
todo escrito en el archivo development.log.


Página 10
Document ación: ActiveRecord::Base

Note co m o u n a activida d lógica d e s d e la p e r s p ectiva d el u s u a rio p ue de req u erir d o s
p a s o s a t raves d el con t r ola do r: p o r eje m plo, act uali za r u n regist r o en la ta bla. Cua n d o el
u s ua rio selecciona ‘Edit’, el con t r ola do r ext rae el regist ro q u e se d e sea e ditar d el m o d elo,
y re n de ri za la vista edit. Cua n d o el u s u a rio finaliz o la e dición, la vista edit invoca la
acció n update, q ue act uali za el m o d elo y luego invoca la acció n show.

La Vista
Las vistas s o n d o n d e se d efine la interfa z d el u s ua rio. Rails p u e d e re n de ri za r la p ági na
HTML fi nal p rese n ta da al u s u a rio d e s de t res co m p o n e n te s:
              Layout                         Template - Plantilla                     Partial - Parcial
e n appviewslayouts                 e n appviews<controller>            e n appviews<controller>
p o r d efecto: application.rhtml p o r d efecto: <action>.rhtml              p o r d efecto _<partial>.rhtml
o <controller>.rhtml

• Un Layo ut p r ovee có digo co m u n u sa d o p o r t o d a s las acció nes, ti pica me n t e el co mien z o
  y final d el HTML envia do al n avega do r.
• Un Te m plate o Plan tilla p rovee el có digo es pecifico a ca da acción, eje m plo có digo d e
  ‘List’, có digo d e ‘Edit’, etc.
• Un Partial o Parcial p r ovee có digo co m u n - ‘subr u ti nas’ - q u e p ue de se r u s a d o en
  m ul ti ples acció nes – eje m plo: có digo u s a d o p a ra m o s t r ar ta blas en u n fo r m ulario.

Layout
Convención de nombres en Rails: si hay una plantilla en appviewslayouts con el mismo
nombre que el controlador actual entonces sera utilizada auto máticame n t e como layout
del controlador a menos que explícitamen te se indique lo contrario.

Un layout con el nombre de application.rhtml o application.rxml sera configurado como el
controlado r por defecto si no existe un layout con el mismo nombre que el controlador
actual, y no existe un layout asignado explicitamen t e.

El layout generado por el script scaffold se ve como esto:
    appviewslayoutscategories.rhtml
    <html>
    <head>
      <title>Categories: <%= controller.action_name %></title>
      <%= stylesheet_link_tag 'scaffold' %>
    </head>
    <body>

    <%= @content_for_layout %>

    </body>
    </html>

Esto es en su mayoria HTML, mas algunos bits de código Ruby embebido entre etiquetas
<% %>. Este layout sera llamado por el proceso de renderi za d o sin considerar la acción que
se este ejecutan d o. Contiene etiquetas estan da r HTML – las
<html><head>...</head><body>...</body></html> que aparecen en todas las páginas.

Las partes de Ruby en negrita son traducidas a HTML durante el proceso de renderizad o


                                                                                                       Página 11
de Rails como se muest ra a continuación:

•             es un método ActionController que devuelve el nombre de la acción que el
     action_name
  controlador esta procesan do (ejemplo ‘List’) - esto coloca el titulo de la página
  apropiado, depen dien d o de la acción que se esta ejecutan d o.
Document ación: ActionController::Base

•    stylesheet_link_tages un helper (ayudante) de Rails – una manera perezosa de generar
     código. Hay muchos de estos ‘ayudantes’ dentro de Rails. Este simplemen te genera el
     siguiente código HTML: <link href="/stylesheets/scaffold.css" media="screen"
     rel="Stylesheet" type="text/css" />
Document ación: ActionView::Helpers::AssetTagHelper

•                     es la clave de lo que pasa a continuación. Permite a un unico layout
     content_for_layout
  estan dar tener contenido dinamico insertado en tiempo de renderizad o basado en la
  acción ejecutada (ejemplo ‘edit’, ‘new’, ‘list’). Este contenido dinamico proviene de un
  Template (plantilla) con el mismo nombre – ver abajo.
Document ación: ActionController::Layout::ClassMethods.

Template (plantilla)
Convención de nombres de Rails: las plantillas estan guardad as en
appviewscategories‘acción’.rhtml.

El nuevo .rhtml creado por el script scaffold es mostra do a continuación:
    appviewscategoriesnew.rhtml
    <h1>New category</h1>

    <%= start_form_tag :action => 'create' %>
      <%= render_partial "form" %>
      <%= submit_tag "Create" %>
    <%= end_form_tag %>

    <%= link_to 'Back', :action => 'list' %>

•    start_form_tag es un ayudante (helper) de Rails para iniciar un formulario HTML –   aqui
     genera <form action="/categories/create" method="post">
•    submit_tag por si misma generaria <input name="submit" type="submit" value="Save
     changes" />, pero el parámet ro “Create” sobreescribe el valor por defecto “Save
  changes” con “Create”
• end_form_tag solo imprime </form>, no es el helper de Rails mas útil creado :- ) pero
  provee un final satisfactorio para el bloque de código
Document ación: ActionView::Helpers::FormTagHelper

•               invocará un Partial (parcial) _form.rhtml – vea la siguiente sección.
     render_partial
Document ación: ActionView::Partials

•    link_to simplemen te crea un link   – la parte mas funda m e n t al de HTML... <a
     href="/categories/list">Back</a>
Document ación: ActionView::Helpers::UrlHelper

Partial (parcial)
Convención de nombres de Rails: un parcial ‘foo’ estara en el archivo

Página 12
appviews‘action’_foo.rhtml         (note el guion bajo inicial).

Scaffol d u sa el mi s m o có digo p a ra p r ocesa r a m b a s ‘edit’ y ‘new’ acció nes, en to nces coloca
el có digo en u n p a rcial, invoca d o p o r el m é t o d o render_partial.
    appviewscategories_form.rhtml
    <%= error_messages_for 'category' %>

    <!--[form:category]-->
    <p><label for="category_category">Category</label><br/>
    <%= text_field 'category', 'category' %></p>

    <p><label for="category_created_on">Created on</label><br/>
    </p>

    <p><label for="category_updated_on">Updated on</label><br/>
    </p>
    <!--[eoform:category]-->

•    error_messages_fordevuelve una cadena con marca – texto para cualquier mensaje de
     error producido por un intento de enviar el formulario. Si uno o mas errores son
     detectados, el HTML se vera asi:
     <div class="errorExplanation" id="errorExplanation">
       <h2>n errors prohibited this xxx from being saved</h2>
       <p>There were problems with the following fields:</p>
       <ul>
         <li>field_1 error_message_1</li>
         <li>... ...</li>
         <li>field_n error_message_n</li>
       </ul>
     </div>

  Vimos esto en acción en el Día 1 - Ilustración 2: Capturando errores de datos en la
  página 8 . Nota: las etiquetas css igualan las correspo n dien tes declaraciones en la hoja
  de estilos creada por el script generar scaffold.
Document ación: ActionView::Helpers::ActiveRecordHelper

•    text_field es un helper de Rails que genera este HTML: <input id="category_category"
     name="category[category]" size="30" type="text" value="" />. El primer parámet ro es el
  nombre de la tabla; el segund o es el nombre del campo.
Document ación: ActionView::Helpers::FormHelper

Note u n p e q ue ñ o b u g e n Rails – sa be co m o n o crear u n ca m p o d e en t ra da p a ra los
ca m p o s re serva d o s create d_o n y u p d a t e d_on , p e ro a u n asi ge ne ra las etiq ue ta s p a ra
ellos.

La vista de renderizado para la acción “New”
Estamos ya en posición de mirar el código que devuelve al navegador en respuesta a la
acción “New”, y ver de donde vino todo. El Layout provee el texto en negrita; la plantilla
(template) el texto regular; y el parcial el texto en Italica :
    appviewscategoriesnew.rhtml
    <html>
    <head>
      <title>Categories: new</title>
      <link href="/stylesheets/scaffold.css" media="screen" rel="Stylesheet"
    type="text/css" />
    </head>


                                                                                                       Página 13
<body>

 <h1>New category</h1>

 <form action="/categories/create" method="post">

 <!--[form:category]-->
 <p><label for="category_category">Category</label><br/>
 <input id="category_category" name="category[category]" size="30" type="text" value=""
 /></p>

 <p><label for="category_created_on">Created on</label><br/>
 </p>

 <p><label for="category_updated_on">Updated on</label><br/>
 </p>
 <!--[eoform:category]-->

   <input name="submit" type="submit" value="Create" />
 </form>

 <a href="/categories/list">Back</a>

 </body>
 </html>

Analizando la vista de la acción ‘List’
Las vistas ‘Edit’ y ‘Show’ so n si milares a la vista ‘New’. ‘List’ co ntiene algu n o s t r ucos
n u evos. Recuer de co m o el co n t rola d o r ejecut o la siguien te pie z a d e có digo a n t es d e
re n d eri za r la pla n tilla ‘List’:
      @category_pages, @categories = paginate :category, :per_page => 10


p agina te p u e bla la variable d e ins ta ncia @categories con regist ro s o r de n a d o s d e la t abla
Categories, :per_page regist ra p o r ve z, y con tie ne t o d a la lógica p a ra la n avegació n a la
p ágina sig uie n te / a n terio r. @category_pages es u n a ins ta ncia a Paginator. Co m o s o n u s a d a s
e n la pla n tilla se ex plican al final d e la sig uien te secció n.
Document ación: ActionController::Pagination

La pla n tilla se ve co m o sigue:
 appviewscategorieslist.rhtml
 <h1>Listing categories</h1>

 <table>
   <tr>
 <% for column in Category.content_columns %>
     <th><%= column.human_name %></th>
 <% end %>
   </tr>

 <% for category in @categories %>
   <tr>
   <% for column in Category.content_columns %>
     <td><%=h category.send(column.name) %></td>
   <% end %>
     <td><%= link_to 'Show', :action => 'show', :id => category %></td>
     <td><%= link_to 'Edit', :action => 'edit', :id => category %></td>
     <td><%= link_to 'Destroy', {:action => 'destroy', :id => category}, :confirm =>
 "Are you sure?" %></td>
   </tr>
 <% end %>
 </table>


Página 14
<%= link_to "Previous page", { :page => @category_pages.current.previous } if
    @category_pages.current.previous %>
    <%= link_to "Next page", { :page => @category_pages.current.next } if
    @category_pages.current.next %>

    <br />

    <%= link_to 'New category', :action => 'new' %>

•    content_columns devuelve un array de objetos columna excluyendo cualquier columna
  ‘especial’ (la clave primaria id, todas las columnas que finalizen con ‘_id’ o ‘_count’, y
  columnas usadas para herencia de tablas)
Document ación: ActionController::Base

•             es un sinóni mo de human_attribute_name, que transfor m a nombre de
     human_name
  atribut os claves en un formato leible para el huma no, como ‘Primer nombre’ en vez de
  ‘primer_nombre’
Document ación: ActiveRecord::Base

•    h automáticame n t e ‘sale’ del código HTML. Uno de los problemas en permitirle al
     usuario que ingrese datos que luego son mostrad o s en la pantalla es que pueden
     accidental me n t e (o maliciosamen te) ingresar código que podria romper el sistema
     cuando es mostra do 4 . Para cuidarse contra esto, es buena practica utilizar ‘escape
     HTML’ con cualquier dato que es provisto por el usuario. Esto significa que por
     ejemplo </table> es renderiza d o como &lt;/table&gt; que es inofensivo. Rails hace esto
     realmente simple – solo agrega una ‘h’ como se muestra.

•    confirm   es u n p a rá m e t r o o pcio nal m uy ú til p a ra el hel per link_to – genera u n a caja
     e me rge n t e d e JavaScri p t q ue f uer z a al u s u a rio a confir ma r la acció n Destroy a n tes d e
     ejecu ta r el link:




                                Ilustración 3 : Javascript emergente


Document ación: ActionView::Helpers::UrlHelper

La lógica d e la p ági na se aclara u n p oco. Ruby p u e de u tili za r if co m o m o difica do r:
expresion if expresion-booleana evalua expresion solo si expresion-boolean es ver da de ra.
@category_pages.current d ev uelve u n object o Página re p re se n t a n d o la p ági na act u al.

 ActionController::Pagination::Paginator
y @category_pages.current.previous d ev uelve u n n u evo objeto Página re p rese n t a d o la
p ágina a n terio r a la act ual, o n ulo si esta es la p ri m e ra p ági na.
ActionController::Pagination::Paginator::Page


4 Por ejemplo, piense que pasaria si un usuario tipea “< / t a ble >” como una categoria.

                                                                                                      Página 15
Ento nces, si h ay u n a p ágina a n te rior a la cual n avegar, este co nt r uc to r m o s t ra rá u n link;
si n o h ay ni ng u n a, el link es s u p ri mi d o.
El có digo genera d o p a ra la p ágina n se vera asi:
 <a href="/categories/list?page=[n-1]">Previous page</a>
 <a href="/categories/list?page=[n+1]">Next page</a>


Modificar el código generado por Scaffold
El có digo genera d o p o r el scri p t Scaffold es p e rfecta me n te u sa ble, y es r ob u s t o u n a ve z
q ue h aya agrega d o s uficiente vali dació n al m o d elo d e d a t o s. De t o d a s for m a s, si es to
fuera t o d o el d e sa r rollo n ecesario p a ra a plicació nes Rails, en t o nces los p rogra m a d o res se
q ue da rian si n t rabajo, q u e clara m e n te n o es algo b ue n o : - ) asi q u e reali ze m o s algu n as
m o dificaciones:

El controlador
En la vista ‘List’, esperaria que los registros sean mostrad o s en orden alfabético. Esto
requiere un cambio menor al controlador:
 appcontrollerscategories_controller.rb (fragmento)
 def list
     @category_pages, @categories = paginate :category,
          :per_page => 10, :order_by => 'category'
 end


Document ación: ActionController::Pagination

En esta aplicación, la pantalla show es innecesaria – todos los campos entran
comoda me n t e en una sola linea de la pantalla. Entonces, def show puede desaparecer, y
vayamos directa me n t e a la pantalla list despues de un ‘Edit’:
 appcontrollerscategories_controller.rb (fragmento)
 def update
     @category = Category.find(@params[:id])
     if @category.update_attributes(@params[:category])
       flash['notice'] = 'Category was successfully updated.'
       redirect_to :action => 'list'
     else
       render_action 'edit'
     end
   end

El mensaje flash será toma do y mostrara en la siguiente pantalla – en este caso, la
pantalla list. Por defecto, el script scaffold no muestra mensajes flash – cambiare mo s
esto en un minuto – vea abajo.

La Vista (View)

Mostrar mensajes Flash
Rails p rovee u n a t écnica p a ra p a sa r m e n sajes flas h al u s ua rio – eje m plo, u n m e n s aje d e
‘Act uali zació n Exitosa’ q u e se m u e s t ra en la sig uien te p a n t alla y luego d e sa pa rece. Esto s
p u e de n ser t o m a d o s fácil me n t e co n u n p e q ue ño ca m bio al Layo ut (agregarlo al Layou t
significa q ue a pa recera n en cualq uier p a n talla):
 appviewslayoutscategories.rhtml<html>
 <head>
   <title>Categories: <%= controller.action_name %></title>
   <%= stylesheet_link_tag 'scaffold' %>


Página 16
</head>
    <body>
    <h1><%=@heading %></h1>
    <% if @flash["notice"] %>
    <span class="notice">
      <%=h @flash["notice"] %>
    </span>
    <% end %>
    <%= @content_for_layout %>
    </body>
    </html>


Document ación: ActionController::Flash

Un simple agregado a la hoja de estilo hace que el mensaje flash sea mas visible:
    publicstylesheetsscaffold.css (fragmento)
    .notice {
        color: red;
    }

Compartir variables entre la plantilla y el Layout
Note que he movido el texto encabeza d o <h1>...</h1> de la plantilla al Layout para que
aparezca sobre el mensaje flash. Como cada plantilla tendra un encabezad o diferente,
necesito colocar el valor de la variable @heading en la plantilla. Rails no tiene problemas
con esto – variables de plantilla estan disponibles para los Layouts en tiempo de
renderiza do.

He realizado este cambio y algunos cambios de formato para terminar mi plantilla:
    appviewscategorieslist.rhtml
    <% @heading = "Categorias" %>
    <table>
      <tr>
        <th>Categoría</th>
        <th>Creada</th>
        <th>Actualizada</th>
      </tr>
    <% for category in @categories %>
      <tr>
        <td><%=h category["category"] %></td>
        <td><%= category["created_on"].strftime("%I:%M %p %d-%b-%y") %></td>
        <td><%= category["updated_on"].strftime("%I:%M %p %d-%b-%y") %></td>
        <td><%= link_to 'Editar', :action => 'edit', :id => category %></td>
        <td><%= link_to 'Eliminar', {:action => 'destroy', :id => category},
                :confirm => "¿Esta seguro que desea eliminar esta categoria?" %></td>
      </tr>
    <% end %>
    </table>
    <br />
    <%= link_to 'Nueva categoría', :action => 'new' %>
    <% if @category_pages.page_count>1 %>
    <hr />
    Page: <%=págination_links @category_pages %>
    <hr />
    <% end %>

• No me gusta el format o de la fecha por defecto, entonces uso el método strftime() de
  Ruby para formatear los campos de fecha y hora a la forma que quiero.
Ruby Document ación: class Time



                                                                                    Página 17
•    págination_links   crea u n a ba r ra lin k HTML bá sica p a ra u n p agi na d o r d a d o
ActionView::Helpers::PaginationHelper

Atando las pantallas de Edit y New
Un par de cambios al Parcial utilizado por ‘New’ y ‘Edit’: usé una tabla para mejorar el
layout; deshacer me de las innecesarias etiquetas created_on/ updated_on; y prevenir que el
usuario tipee mucho dentro del campo Category:
    appviewscategories_form.rhtml
    <%= error_messages_for 'category' %>
    <table>
    <tr>
      <td><b><label for="category_category">Category:</label></b></td>
      <td><%= text_field "category", "category", "size"=>20, "maxlength"=>20 %></td>
    </tr>
    </table>

y algunos cambios menores a las dos plantillas (note en particular el uso de @heading)::
    appviewscategoriesEdit.rhtml
    <% @heading = "Edit Category" %>
    <%= start_form_tag :action => 'update', :id => @category %>
      <%= render_partial "form" %>
      <hr />
      <%= submit_tag "Save" %>
    <%= end_form_tag %>
    <%= link_to 'Back', :action => 'list' %>


    appviewscategoriesNew.rhtml
    <% @heading = "New Category" %>
    <%= start_form_tag :action => 'create' %>
      <%= render_partial "form" %>
      <hr />
      <%= submit_tag "Save" %>
    <%= end_form_tag %>
    <%= link_to 'Back', :action => 'list' %>


Esto n o s lleva al final d el Dia 2. Tene m o s u n sis te m a fu ncio na n d o p a ra m a n te ner n u es t ra
t abla d e Categorias, y he m o s e m p e z a d o a t o m a r con t rol d el có digo scaffold q u e Rails h a
genera d o.




Página 18
Día 3 con Rails
Ahora es tiempo de empezar con el corazón de la aplicación. La tabla Items contiene la
lista de “cosas para hacer”. Cada item puede pertenecer a una de las categorias creadas
en el Dia 2. Un item opcionalmen t e puede tener un Nota, guardad a en una tabla separada,
que veremos mañana. Cada tabla tiene una clave primaria ‘id’, que también es usada para
guardar links entre las tablas.



                  Categories                 Items                         Notes
                  id                         id                            id
                                             category_id
                                             note_id


         Ilustración 4 : Modelo de datos simplificado


La tabla ‘Items’
Definición MySQL de la tabla
Los ca m p o s en la t abla Ite m s so n los sig uie n tes:
• d o ne – 1 sig nifica q ue el ite m d e la lista ha si d o finali za d o 5
• p rio rity – 1 (Alta p rio ri da d) a 5 (baja p riori da d)
• d e scri p tion – texto libre in dican d o cual es la ta rea
• d u e_da te – in dica cua n d o se d e be ria reali za r la ta rea
• category_id – u n link a la Categoria a la q ue este ite m p e r te nece (‘id’ en la t abla d e
  Catego rias)
• n o te_id – u n link a u n a n o ta o pcio nal ex plican d o es te ite m (‘id’ en la ta bla d e n o t as)
• p rivate – 1 sig nifica q ue el ite m d e la lista est a clasifica d o co m o ‘Priva do’


 Tabla Items
 CREATE TABLE items (
   id smallint(5) unsigned NOT NULL auto_increment,
   done tinyint(1) unsigned NOT NULL default '0',
   priority tinyint(1) unsigned NOT NULL default '3',
   description varchar(40) NOT NULL default '',
   due_date date default NULL,
   category_id smallint(5) unsigned NOT NULL default '0',
   note_id smallint(5) unsigned default NULL,
   private tinyint(3) unsigned NOT NULL default '0',
   created_on timestamp(14) NOT NULL,
   updated_on timestamp(14) NOT NULL,
   PRIMARY KEY (id)
 ) TYPE=MyISAM COMMENT='List of items to be done';

El Modelo
Co m o a n tes, Rails p u e de genera r u n arc hivo d e m o d elo vacio:
 W:ToDo>ruby script/generate model item
       exists app/models/
       exists test/unit/
       exists test/fixtures/

5 MySQL no tiene un tipo ‘booleano’, entonces usamos 0/1

                                                                                                    Página 19
create    app/models/item.rb
          create    test/unit/item_test.rb
          create    test/fixtures/items.yml

    W:ToDo>
q ue p o d e m o s p o blar co n:
    appmodelsitem.rb
    class Item < ActiveRecord::Base
      belongs_to :category
      validates_associated :category
      validates_format_of :done_before_type_cast, :with => /[01]/, :message=>"must be 0 or
    1"
      validates_inclusion_of :priority, :in=>1..5, :message=>"must be between 1 (high) and
    5 (low)"
      validates_presence_of :description
      validates_length_of :description, :maximum=>40
       validates_format_of :private_before_type_cast, :with => /[01]/, :message=>"must be 0
    or 1"
    end

Validar los links entre las tablas
• El uso de belongs_to (pertenece a) y validates_associated (validar asociaciones) enlaza
  la tabla Items con el campo item_id de la tabla Category.
Document ación: ActiveRecord::Associations::ClassMethods

Validar la entrada del usuario
•    validates_presence_of      proteje los campos ‘NOT NULL’ contra entradas nulas del
     usuario
•    validates_format_of      usa expresiones regulares para chequear el formato de la entrada
   del usuario
•  cuando un usuario tipea una entrada para un campo numérico, Rails siempre la
   convertira a un número – si todo falla, un cero. Si desea chequear que el usuario ha
   realmente tipeado un número, entonces necesita validar la entrada con
   _before_type_cast, que permite acceder la entrada ‘bruta’ 6 .
• validates_inclusion_of chequea la entrada del usuario contra un rango de valores
   permitidos
• validates_length_of previene que el usuario ingrese datos que serian truncados cuando
   se almacenen 7 .
 Document ación: ActiveRecord::Validations::ClassMethods

La tabla de ‘Notas’
Esta t a bla co n tiene u n solo ca m p o d e t ext o libre p a ra con te ner infor m ación f ut u r a p a ra
u n ite m d e la lista d e t a reas en p a r ticular. Este d a t o p o d ria, p o r s u p u es t o, h a ber si d o
con te ni d o en u n ca m p o d e la t abla Ite m s, d e t o d a s for m a s, si lo h ace d e es ta for m a
a p re n d e ra m u c h o m a s acerca d e Rails : - )

Definición de la tabla MySQL
    Tabla Notes
    CREATE TABLE notes (

6 Lo que pareceria una alternativa mucho mas obvia: validates_inclusion_of
     :done_before_type_cast, :in=>"0".."1", :message=>"must be between 0 and 1" – falla si el
  campo de entrada queda en blanco
7 Puede combinar las dos reglas para el campo de Descripción en una sola: validates_length_of
     :description, :within => 1..40


Página 20
id smallint(6) NOT NULL auto_increment,
   more_notes text NOT NULL,
   created_on timestamp(14) NOT NULL,
   updated_on timestamp(14) NOT NULL,
   PRIMARY KEY (id)
 ) TYPE=MyISAM COMMENT='Additional optional information for to-dos';

El modelo
Genere el archivo de modelos vacio, pero no contiene nada nuevo:
 appmodelsnote.rb
 class Note < ActiveRecord::Base
   validates_presence_of :more_notes
 end


p e r o n ecesita m o s recor d a r agregar este enlace al m o d elo d e Items :
 appmodelsitem.rb (fragmento)
 class Item < ActiveRecord::Base
   belongs_to :note


Usar un Modelo para mantener Integridad Referencial
El có digo q ue esta m o s a p u n t o d e d e sar r ollar p e r mitira al u s u a rio agregar u n a n o t a a
cualq uier Ite m. Pero q u e ocu rre cua n d o u n u s u a rio bo r ra u n Ite m q ue tiene u n n o t a
asocia da? Clara me n t e, n ecesita m o s e nco n t ra r u n a for m a d e bo rra r el regist ro d e la Nota
t a m bié n, d e o t ra fo r m a n o s q u e d a n regist ro s Notas “huerfa n o s”.
En la for m a d e reali za r el t rabajo Modelo / Vista / Con t r ola do r, es te có digo p e r te nece al
m o d elo. ¿Porq ué? Bien, p o d r a ver m a s ta r de q u e p o d e m o s bo r ra r regist ro s Ite m s
h acien d o click e n u n íco no d e p a p elera d e reciclaje en la p a n talla “lista d e t a reas”, p e r o
t a m bié n p o de m o s b o r ra r u n ite m h acien d o click en Purgar ite m s co m pleta d o s. Colocan d o
el có digo en el Modelo, sera ejecu ta d o sin te ne r en cue n t a d e d o n d e p rove nga la acción d e
eli mi na r.
 appmodelsitem.rb (fragmento)
    def before_destroy
      unless note_id.nil?
        Note.find(note_id).destroy
      end
    end

Esto se lee: antes de borrar un registro Item, encontrar el registro en Notas cuyo id sea
igual al valor de Nota_id en el registro Item que se esta a punto de eliminar, y eliminarlo
primero. A menos que no exista uno :- )

Similarmen te, si un registro es eliminado de la tabla Notas, entonces cualquier referencia
a este en la tabla Items necesita ser eliminada:
 appmodelsnote.rb (fragmento)
   def before_destroy
     Item.find_by_note_id(id).update_attribute('note_id',NIL)
   end
 end


Document ación: ActiveRecord::Callbacks




                                                                                                   Página 21
Mas de Scaffold
Generemo s algo mas de código scaffold. Haremos esto para la tabla Items y la tabla
Notas. Todavía no estamos listos para trabajar sobre Notas, pero tener en su lugar a
scaffold significa que podemo s referirnos hoy al código de las Notas sin generar muchos
errores. Es como construir una casa – scaffold permite contruir una pared a la vez sin
que todo se derru m be alrededor de sus ojos.

 W:ToDo>ruby script/generate scaffold Item
   [snip]
 W:ToDo>ruby script/generate scaffold Note
   [snip]
 W:ToDo>


Nota: co m o m o difica m o s la h oja d e estilos ayer, ingrese “n” a la p reg u n t a “overwrite
(sobreescribir) p u blic / s tyles heet s / scaffol d.css? [Ynaq]”.

Mas acerca de Vistas
Crear un Layout para la Aplicación
Para a ho ra, se esta volvien d o o bvio d e q u e t o d a s m i s pla n tillas te n d ra n las m i s m a s
p ri m era s lineas d e có digo, e n t o nces tiene se n ti do m over el có digo e n co m u n a u n layou t
d e la a plicació n. Borre t o d o s los arc hivos appviewslayouts*.rhtml, y ree m placelos p o r
u n arc hivo co m ú n application.rhtml.
 appviewslayoutsapplication.rhtml
 <html>
 <head>
   <title><%= @heading %></title>
   <%= stylesheet_link_tag 'todo' %>
 <script language="JavaScript">
 <!-- Begin
 function setFocus() {
   if (document.forms.length > 0) {
      var field = document.forms[0];
      for (i = 0; i < field.length; i++) {
        if ((field.elements[i].type == "text") || (field.elements[i].type == "textarea")
 || (field.elements[i].type.toString().charAt(0) == "s")) {
          document.forms[0].elements[i].focus();
          break;
           }
        }
    }
 }
 // End -->
 </script>
 </head>
 <body OnLoad="setFocus()">
 <h1><%=@heading %></h1>
 <% if @flash["notice"] %>
 <span class="notice">
   <%=h @flash["notice"] %>
 </span>
 <% end %>
 <%= @content_for_layout %>
 </body>
 </html>


El @heading en la plantilla es ahora utilizado para las etiquetas <title> como también para
<h1>. He renom bra d o public/stylesheets/scaffold.css a todo.css para mantener una
prolijidad, y también he jugado general ment e con los colores, bordes de las tablas, para

Página 22
dar un estilo mas lindo. También he agregado un poco de Javascript para
automáticame n t e posicionar el cursor en el primer campo de entrada en el navegador
para que el usuario comienze a tipear.

La pantalla ‘Lista de tareas’
Lo q ue est oy inte n t a d o co n seg uir es u n a vista ba sa da e n u n escrit orio Pal mPilot o PDA
si milar. El p r o d uct o fi nal es m o s t ra d o en la Ilus t ració n 5: La p a n t alla d e ‘Lista d e Tareas’8 .
Algu n o s p u n t o s:
• h acien d o click en el e ncabe za d o d e la col u m n a ‘tilde’ (√) eli mi nara t o d o s los ite m s
   co m pleta d o s. (aq uellos m a rca d o s con u n a til de)
• La p a n t alla p u e de ser o r de n a d a hacien d o click e n los encabe z a d o s d e las col u m n a s
   ‘Pri’, ‘Descri pción’, ‘Finali za r’, y ‘Categoria’
• los valores 0 / 1 p a ra ‘Ter mi na d o’ s o n co nverti d os en p e q u e ñ o s ícon os til des
• ite m s q u e p a sa ro n la fecha d e finali zació n (due d a t e) s o n colorea d o s en rojo y
   m o s t ra d o s e n n egrita
• la p re se ncia d e u n a n o t a asociad a es m o s t ra d a co n el ícon o ‘nota’
• los valores 0 / 1 p a ra ‘Priva do’ so n conver ti do s en u n sí m bolo d e can d a d o
• ite m s in divid uales p u e de n ser e di ta d o s o eli mi na d o s h acien d o click en los ícono s d e la
   d e recha d e la p a n t alla
• la p a n t alla tiene u n lin do efecto d e ‘franjas’
• n u evos ite m s p ue de n se r agrega d o s h acien d o click en el b o t ó n ‘Nueva Tarea...’ e n la
   p a r te inferior d e la p a n t alla
• h ay u n bo t ó n e nlace a las ‘Categorias’ d el Día 2




Ilustración 5 : La pantalla de ‘Lista de Tareas’




La pla n tilla u tili za d a p a ra o b te ne r est o es la sig uien te:



8 Es asombros o lo que un par de lineas en la hoja de estilos pueden hacer para cambiar la
  apariencia de la pantalla, por supues to ademas de la colección de íconos...

                                                                                                        Página 23
appviewsitemslist.rhtml
 <% @heading = "To Do List" %>
 <%= start_form_tag :action => 'new' %>
 <table>
   <tr>
     <th><%= link_to_image "done", {:action => "purge_completed"}, :confirm => "Are you
 sure you want to permanently delete all completed To Dos?" %></th>
     <th><%= link_to_image "priority",{:action => "list_by_priority"}, "alt" => "Sort
 by Priority" %></th>
     <th><%= link_to_image "description",{:action => "list_by_description"}, "alt" =>
 "Sort by Description" %></th>
     <th><%= link_to_image "due_date", {:action => "list"}, "alt" => "Sort by Due Date"
 %></th>
     <th><%= link_to_image "category", {:action => "list_by_category"}, "alt" => "Sort
 by Category" %></th>
     <th><%= show_image "note" %></th>
     <th><%= show_image "private" %></th>
     <th>&nbsp;</th>
     <th>&nbsp;</th>
   </tr>
 <%= render_collection_of_partials "list_stripes", @items %>
 </table>
 <hr />
 <%= submit_tag "New To Do..." %>
 <%= submit_tag "Categories...", {:type => 'button', :onClick=>"parent.location='" +
 url_for( :controller => 'categories', :action => 'list' ) + "'" } %>
 <%= end_form_tag %>
 <%= "Page: " + pagination_links(@item_pages, :params => { :action => @params["action"]
 || "index" }) + "<hr />" if @item_pages.page_count>1 %>

Eliminar ‘tareas’ completadas haciendo click en un ícono
Imagenes clickeables so n crea da s p o r link_to_image, q ue p o r d efecto es pe ra enco n t rar la
i mage n en pub/images con u n a exte n sió n .png; h acien d o click en la i mage n ejecu ta ra u n
m é t o d o es pecífico.
Agrega n d o el p a rá m e t ro :confirm genera u n a ven ta n a d e dialogo e me rge n te javascri p t
co m o a n te s
Document ación: ActionView::Helpers::UrlHelper

Haciendo click en ‘OK’ ejecuta el método purge_completed. Este nuevo método
purge_completed necesita ser definido en el controlado r:
 appcontrollersitems_controller.rb (fragmento)
    def purge_completed
      Item.destroy_all "done = 1"
      redirect_to :action => 'list'
    end


Item.destroy_all eli mi na t o d o s los regist ro s   d e la t abla Items d o n d e el valor d el ca m p o id
done es 1, y luego d evuelve la acción list.

Document ación: ActiveRecord::Base

Cambiar el modo de ordenamiento haciendo click en el Encabezado de la Columna
Clickeando en el ícono de Pri invoca el método list_by_priority. Este nuevo método
list_by_priority necesita ser defenido en el controlador:
 appcontrollersitems_controller.rb (fragmento)
    def list
      @item_pages, @items = paginate :item,
       :per_page => 10, :order_by => 'due_date,priority'


Página 24
end

    def list_by_priority
      @item_pages, @items = paginate :item,
        :per_page => 10, :order_by => 'priority,due_date'
      render_action 'list'
    end

Especificamos un modo de ordena mien to por defecto en el método list , y creamos un
nuevo método list_by_priority 9 . Note también que necesita mo s explicitame n te
render_action 'list', por defecto Rails intentará renderizar una plantilla llamada
list_by_priority (que no existe :- )

Agregar el Helper
Los encabezad o s para las columnas Nota y Privado son imagenes, pero no son
clickeables. He decidido escribir un pequeño método show_image(name) para solo most rar
la imagen:
 apphelpersapplication_helper.rb
 module ApplicationHelper
     def self.append_features(controller)
       controller.ancestors.include?(ActionController::Base) ?
         controller.add_template_helper(self) : super
     end

     def show_image(src)
         img_options = { "src" => src.include?("/") ? src : "/images/#{src}" }
         img_options["src"] = img_options["src"] + ".png" unless
 img_options["src"].include?(".")
         img_options["border"] = "0"
         tag("img", img_options)
     end
 end

Una vez que el helper ha sido enlaza do por el controlado r:
 appcontrollersapplication.rb
 class ApplicationController < ActionController::Base
   helper :Application
 end
esta disponible para todas las plantillas en la aplicación
 Document ación: ActionView::Helpers

Usar botónes de navegación Javascript
onClick    es u n a técnica s ta n d a r d Javascri pt p a ra m a nejar acció nes d e bo tó ne s co m o
n avegar a u n a n u eva p ági na. De t o d a s for m a s, Rails reescribe las di reccio nes URLs,
e n t o nces n ecesita m o s p reg u n t a rle a Rails p o r la di reccio n URL cor recta a u tili za r. Dad o
u n controlador y u n a acción, url_for devolverá la URL.
Document ación: ActionController::Base

Formatear una Tabla con un Parcial
Queria crear un efecto de franjas para la lista de items. Los Parciales (Partial) proveen la
solución; pueden ser invocados por el método render_partial:

<% for item in @items %>

9 list_by_description y list_by_category son similares y son dejados como un fácil ejercicio
  para el lector. De todas formas, si queda trabado con list_by_category, vea en la página 39

                                                                                                     Página 25
<%= render_partial "list_stripes", item %>
<% end %>

o por el mas económico método render_collection_of_partials:
render_collection_of_partials "list_stripes", @items
Document ación: ActionView::Partials

Rails también pasa un número secuencial list_stripes_counter al Parcial. Esta es la clave
para el formato alternad o de las filas en la tabla con o un fondo gris claro o un fondo gris
oscuro. Una forma simple para probar si el contador es impar o par: si es impar, usar el
gris claro, si es par, usar el gris oscuro.

El Parcial completo es como sigue:
 appviewsitems_list_stripes.rhtml
   <tr class="<%= list_stripes_counter.modulo(2).nonzero? ? "dk_gray" : "lt_gray" %>">
     <td style="text-align: center"><%= list_stripes["done"] == 1 ?
 show_image("done_ico.gif") : "&nbsp;" %></td>
     <td style="text-align: center"><%= list_stripes["priority"] %></td>
     <td><%=h list_stripes["description"] %></td>
 <% if list_stripes["due_date"].nil? %>
     <td>&nbsp;</td>
 <% else %>
     <%= list_stripes["due_date"] < Date.today ? '<td class="past_due" style="text-
 align: center">' : '<td style="text-align: center">' %><%=
 list_stripes["due_date"].strftime("%d/%m/%y") %></td>
 <% end %>
     <td><%=h list_stripes.category ? list_stripes.category["category"] : "Unfiled"
 %></td>
     <td><%= list_stripes["note_id"].nil? ? "&nbsp;" : show_image("note_ico.gif")
 %></td>
     <td><%= list_stripes["private"] == 1 ? show_image("private_ico.gif") : "&nbsp;"
 %></td>
     <td><%= link_to_image("edit", { :controller => 'items', :action => "edit", :id =>
 list_stripes.id }) %></td>
     <td><%= link_to_image("delete", { :controller => 'items', :action => "destroy",
 :id => list_stripes.id }, :confirm => "Are you sure you want to delete this item?")
 %></td>
   </tr>

Un poco de Ruby es usado para probar si el contador es impar o par y renderizar o
class=“dk_gray” o class=“lt_gray”:
list_stripes_counter.modulo(2).nonzero?    ? "dk_gray" : "lt_gray"
el código hasta el signo de iterrogación pregunta: es el resto cuando se divide
list_stripes_counter por 2 es diferente a cero?
 Ruby Document ación: class Numeric

El resto de la linea es en realidad una criptica expresión if then else que sacrifica ser
legible por ser breve: if la expresión antes de la marca de pregunta es verdadera,
devuelve el valor antes de los dos puntos; sino devuelve el valor después de los dos puntos.
 Ruby Document ación: Expressions

Las dos etiquetas dk_gray y lt_gray son definidas en la hoja de estilos:
 publicstylesheetsToDo.css (fragmento)
 .lt_gray { background-color: #e7e7e7; }
 .dk_gray { background-color: #d6d7d6; }

Nota: el mismo constructor if then else es usado para mostrar el ícono ‘tilde’ si


Página 26
list_stripes["done"]es          igual a 1, de otra forma muestra un caracter de espacio en blanco
HTML:

list_stripes["done"] == 1 ? show_image("done_ico") : "&nbsp;"

Formato basado en el valor de los Datos
Ta m bién es fácil resalta r ite m s es pecíficos d e d a t o s – p o r eje m plo, fecha s en el p a sa d o.
list_stripes["due_date"] < Date.today ? '<td class="past_due">' : '<td>'
De n uevo, est o n ecesita se r igual a la e n t ra d a .past_due en la h oja d e estilos.

Manejar valores perdidos en una busqueda
Quere m o s q ue el sis te m a p ue d a cub ri rse e n la sit uació n d o n d e el u s u a rio bo rra u n a
Categoria q u e est a sie n d o u s a d a p o r u n ite m en la Lista d e Tareas. En este caso, la
Categoria d e be ria ser m o s t ra d a co m o ‘sin arc hivar’:
list_stripes.category ? list_stripes.category["category"] : 'Unfiled'

OK si h a llega d o h a s ta a q ui, d e beria te ner u n a p a n t alla ‘Lista d e Tareas’ q ue se vea algo
co m o la Ilust ración 5 La p a n talla de ‘Lista de T areas’ en la p ágina 2 3 .

La pantalla ‘Nueva Tarea’
Ahora sig ue q u e p a sa cua n d o u n o p re sio na el b ot ó n d e ‘Nueva Tarea...’. De n u evo, t o davía
q ue da n algu n o s t r uco s en el có digo.




                 Ilustración 6 Pantalla Tarea Nueva

La pla n tilla es m í ni m a:
 appviewsitemsnew.rhtml
 <% @heading = "New To Do" %>
 <%= error_messages_for 'item' %>
 <%= start_form_tag :action => 'create' %>
   <table>
 <%= render_partial "form" %>
   </table>
   <hr />
 <%= submit_tag "Save" %>
 <%= submit_tag "Cancel", {:type => 'button', :onClick=>"parent.location='" + url_for(
 :action => 'list' ) + "'" } %>
 <%= end_form_tag %>



                                                                                                       Página 27
y el t rabajo real es reali za d o en el p a rcial, q u e p u e d e ser co m p a r ti d o con la acción ‘Edit’:
 appviewsitems_form.rhtml
     <tr>
       <td><b>Descripción: </b></td>
       <td><%= text_field "item", "description", "size" => 40, "maxlength" => 40
 %></td>
     </tr>
     <tr>
       <td><b>Finalizar: </b></td>
       <td><%= date_select "item", "due_date", :use_month_numbers => true %></td>
     </tr>
     <tr>
       <td><b>Categoria: </b></td>
       <td><select id="item_category_id" name="item[category_id]">
          <%= options_from_collection_for_select @categories, "id", "category",
 @item.category_id %>
            </select>
       </td>
     </tr>
     <tr>
       <td><b>Prioridad: </b></td>
       <% @item.priority = 3 %>
       <td><%= select "item","priority",[1,2,3,4,5] %></td>
     </tr>
     <tr>
       <td><b>Privado? </b></td>
       <td><%= check_box "item","private" %></td>
     </tr>
     <tr>
       <td><b>Completado? </b></td>
       <td><%= check_box "item", "done" %></td>
     </tr>

Crear una lista desplegable para el campo fecha
d a t e_select ge nera u n r u di m e n ta rio m e n u d e s plegable p a ra ingresa r la fecha:
 date_select "item", "due_date", :use_month_numbers => true
Document ación: ActionView::Helpers::DateHelper

Atrapar excepciones con Ruby
Desafor t u n a d a m e n te, date_select feli z m e n te ace p ta fechas co m o 3 1 d e Febrero. Rails
m u e re cua n d o inte n t a g uar d a r es ta fecha en la base d e d a t o s. Una for m a d e evitar est o es
at ra pa r este inte n t o d e g uar da r fallido u sa n d o rescue, u n m é t o d o d e m a n eja r excepcio ne s
d e Ruby
 appcontrollersitems_controller.rb (fragmento)
    def create
       begin
         @item = Item.new(@params[:item])
         if @item.save
            flash['notice'] = 'Tarea creada exitosamente.'
            redirect_to :action => 'list_by_priority'
         else
            @categories = Category.find_all
            render_action 'new'
         end
       rescue
            flash['notice'] = 'La tarea no se pudo grabar.'
            redirect_to :action => 'new'
        end
    end
Ruby Document ación: Exceptions, Catch, and Throw


Página 28
Crear una lista desplegable desde una tabla de busqueda
Este es ot ro eje m plo d e Rails resolvien d o u n p r o ble m a d e co dificación diario d e u n a
fo r m a ext re m a d a m e n te econ ó mica. En es te eje m plo:
options_from_collection_for_select @categories, "id", "category", @item.category_id

options_from_collection_for_select lee t o d o s los regist ro s e n las categorias y los re n de ri za
co m o <option value=”[value of id]”>[value of category]</option>. El regist ro q ue es igual
a @item_category_id sera etiq uet a d o co m o ‘ selecciona d o’. Si es t o n o fuera s uficien te, el
có digo incluso u tili za esca pe s h t ml p a ra los d a t o s. Habil.
Document ación: ActionView::Helpers::FormOptionsHelper

Note q u e las cajas d e s plegables d e be n t raer los d a t o s d e algu n lugar – q ue sig nifica u n
agrega d o al con t r ola do r:
 appcontrollersitems_controller.rb (fragmento)
    def new
      @categories = Category.find_all
      @item = Item.new
    end

    def edit
      @categories = Category.find_all
      @item = Item.find(@params[:id])
    end

Crear una lista desplegable para la lista de constantes
Esta es u n a versión m a s si m ple d el caso a n te rior. Agregar u n a lista d e valores a u n a caja
d e selección en el có digo n o es sie m p re u n a b ue n a idea – es m a s fácil ca m biar los d a t o s
e n la t a bla q ue e ditar los valores en el có digo. De t o d a s for m a s, h ay casos d o n d e es u n a
a p r oxi m ació n p e rfecta m e n te vali da, e n t o nces en Rails h aga:
select "item","priority",[1,2,3,4,5]
Note t a m bién co m o in dicar u n a valor p o r d efecto en la linea d e có digo a n te rior.
Document ación: ActionView::Helpers::FormOptionsHelper

Crear una casilla de verificación
Ot ro re q ue ri mie n t o reg ular; o t r o hel per en Rails:
check_box "item","private"

Document ación: ActionView::Helpers::FormHelper

Toques finales
Modificar la hoja de estilos
Hast a es te p u n t o, la p a n t alla d e ‘Lista d e Tareas’ d e be ria f u ncio na r, y t a m bién d e beria
fu ncio nar el b o t ó n ‘New To Do’. Para p r o d ucir las p a n t allas m o s t ra d a s aq ui, t a m bié n hice
los sig uien te s ca m bios a la h oja d e es tilos:
 publicstylesheetsToDo.css
 body { background-color: #c6c3c6; color: #333; }

 .notice {
   color: red;
   background-color: white;
 }



                                                                                                      Página 29
h1 {
   font-family: verdana, arial, helvetica, sans-serif;
   font-size:   14pt;
   font-weight: bold;
 }

 table {
   background-color:#e7e7e7;
   border: outset 1px;
                border-collapse: separate;
                border-spacing: 1px;
 }

 td { border: inset 1px; }
 .notice {
   color: red;
   background-color: white;
 }
 .lt_gray { background-color: #e7e7e7; }
 .dk_gray { background-color: #d6d7d6; }
 .hightlight_gray { background-color: #4a9284; }
 .past_due { color: red }

La pantalla ‘Editar Tarea’
El re s to d el Dia 3 es la con t r ucció n d e la p a n t alla ‘Editar Tarea’, q u e es m uy si milar a
‘Nueva Tarea’. Estaba acos t u m b ra d o a m olest ar m e cua n d o los texto s d e sec u n d a ria
d ecian: esto q ueda co mo u n ejercicio f ácil p ara el lector, a ho ra es genial p o d er h acer lo
m i s m o con u s t e de s 1 0 .

Esto n o s lleva al final d el Dia 3 – y a h o ra la a plicació n n o se ve p a ra n a d a co m o u n
scaffol d d e Rails, p e ro bajo la s u p e rficie, t o davía u tiliza m o s u n gra n ra ngo d e
h e r ra mie n t a s d e Rails p a ra h acer el d e sa r rollo m a s fácil.




10 Pero no como los autores de los textos de secundaria, yo si muestro la respues t a en el Dia 4 :- ) -
   vea app  views ite m s  e dit.rht ml en la página 31

Página 30
Dia 4 con Rails
Las pantallas ‘Notas’
Enlazando ‘Notas’ con ‘Editar Tarea’
Aunque el código scaffold de las Notas le da todas las fácilidades, no quere mos que el
usuario invoque cualquiera de estas directa me n t e. En cambio, si un item no tiene
asociada una nota, queremo s poder crear una nota haciendo click en el ícono de Nota en
la pantalla de Edicion de tareas:




                     Ilustración 7 : Crear una nota nueva desde la pantalla
                     ‘Editar Tarea’

Si ya existe una nota, queremo s poder editarla o borrarla haciendo click en el ícono
apropiado en la pantalla de Edicion de tareas:




                  Ilustración 8 : Editar o borrar una nota existente

Pri me ro q u e n a d a, vea m o s el có digo d e la p a n t alla ‘Editar Tarea’. Note co m o los bo t ó ne s
d e Notas ca m bian d e acuer d o a si la Nota existe o n o, y co m o el con t r ol es t ra n sferi do al
con t r ola d o r d e Notas:
 appviewsitemsedit.rhtml
 <% @heading = "Edit To Do" %>
 <%= error_messages_for 'item' %>
 <%= start_form_tag :action => 'update', :id => @item %>
   <table>


                                                                                                   Página 31
<%= render_partial "form" %>
     <tr>
       <td><b>Notes: </b></td>
 <% if @item.note_id.nil? %>
       <td>None</td>
       <td><%= link_to_image "note", :controller => "notes", :action => "new", :id =>
 @item.id %></td>
 <% else %>
       <td><%=h @item.note.more_notes %></td>
       <td><%= link_to_image "edit_button", :controller => "notes", :action => "edit",
 :id => @item.note_id %></td>
       <td><%= link_to_image "delete_button", {:controller => "notes", :action =>
 "destroy", :id => @item.note_id }, :confirm => "Are you sure you want to delete this
 note?" %></td>
 <% end %>
 </tr>
   </table>
   <hr />
 <%= submit_tag "Save" %>
 <%= submit_tag "Cancel", {:type => 'button', :onClick=>"parent.location='" + url_for(
 :action => 'list' ) + "'" } %>
 <%= end_form_tag %>

La pantalla ‘Editar Notas’
Editar una nota existente es muy simple. Esta es la plantilla:
 appviewsnotesedit.rhtml
 <% @heading = "Edit Note" %>
 <%= start_form_tag :action => 'update', :id => @note %>
   <%= render_partial "form" %>
   <%= submit_tag "Save" %>
   <%= submit_tag "Cancel", {:type => 'button', :onClick=>"parent.location='" +
 url_for( :controller => 'items', :action => 'list' ) + "'" } %>
 <%= end_form_tag %>

y el parcial:
 appviewsnotes_form.rhtml
 <table>
   <tr>
     <td><label for="note_more_notes">More notes</label></td>
     <td><%= text_area 'note', 'more_notes' %></td>
   </tr>
 </table>

Una vez que la acción update o destroy de la tabla Notas es completada, queremos regresar
a la pantalla de ‘Lista de Tareas’:
 appcontrollersnotes_controller.rb (fragmento)
    def update
      @note = Note.find(@params[:id])
      if @note.update_attributes(@params[:note])
        flash['notice'] = 'Note was successfully updated.'
        redirect_to :controller => 'items', :action => 'list'
     else
        render_action 'edit'
      end
    end

    def destroy
      Note.find(@params[:id]).destroy
      redirect_to :controller => 'items', :action => 'list'
    end
Recuer de las reglas d e integ ri da d refere ncial q ue ya h a n si d o crea da s se asegu rara n d e


Página 32
q ue cua n d o u n a n o t a es eli mina da, cualq uier refere ncia a ella sera re m ovida d el Ite m
t a m bié n (vea Integridad Refere ncial en la p ágina 2 1 ).

La pantalla de ‘Nota Nueva’
Crear es u n p oco m a s difícil. Quere m o s h acer lo siguien te:

•    guar d a r u n a n ueva n o ta e n la t abla d e Notas
•    e nco n t ra r el id d e u n n u evo regist ro crea d o en la ta bla d e Notas
•    regist ra r es te id en el ca m p o n o tes_id d el regist ro asocia do en la t abla d e Ite m s

Las variables d e Sesió n n o s p r oveen u n a for m a ú til d e m a n t e ne r d a t o s e n t re p a n t allas –
p o d e m o s u tili za rlas a q ui p a ra g ua r d a r el Id d el regist ro en la t abla d e Notas.
Document ación: ActionController::Base

Guardar y traer Datos usando variables de Sesión
Primero que nada, cuando creamos un nuevo registro de Nota, pasamo s el id del Item que
estamo s editando:
    appviewsitemsedit.rhtml (fragmento)
          <td><%= link_to_image "note", :controller => "notes", :action => "new", :id =>
    @item.id %></td>

El método new en el controlador Notes guarda esto en una variable de sesión :
    appcontrollersnotes_controller.rb (fragmento)
      def new
        @session[:item_id] = @params[:id]
        @note = Note.new
      end

La plantilla ‘Notas Nuevas’ no tienen sorpresas:
    appviewsnotesnew.rhtml
    <% @heading = "New Note" %>
    <%= start_form_tag :action => 'create' %>
    <%= render_partial "form" %>
    <%= submit_tag "Save" %>
    <%= submit_tag "Cancel", {:type => 'button', :onClick=>"parent.location='" + url_for(
    :controller => 'items', :action => 'list' ) + "'" } %>
    <%= end_form_tag %>

El método create trae los datos de la variable de sesión de nuevo y lo usa para encontrar
el registro en la tabla de Items. Luego actualiza el campo note_id en la tabla Item con el id
del registro que se acaba de crear en la tabla de Notas, y retorna al controlador Items de
nuevo:
    appcontrollersnotes_controller.rb (fragmento)
      def create
        @note = Note.new(@params[:note])
        if @note.save
          flash['notice'] = 'Note was successfully created.'
          @item = Item.find(@session[:item_id])
          @item.update_attribute(:note_id, @note.id)
          redirect_to :controller => 'items', :action => 'list'
        else
          render_action 'new'
        end
      end


                                                                                                         Página 33
Cambiar la pantalla de ‘Categorias’
No hay demasiado por hacer en el sistema ahora, a parte de acomo da r las plantillas
creadas en los dias anteriores para que tengan el mismo estilo que los botónes de
navegación:
 appviewscategorieslist.rhtml
 <% @heading = "Categories" %>
 <form action="/categories/new" method="post">
 <table>
   <tr>
     <th>Category</th>
     <th>Created</th>
     <th>Updated</th>
   </tr>
 <% for category in @categories %>
   <tr>
     <td><%=h category["category"] %></td>
     <td><%= category["created_on"].strftime("%I:%M %p %d-%b-%y") %></td>
     <td><%= category["updated_on"].strftime("%I:%M %p %d-%b-%y") %></td>
     <td><%= link_to_image 'edit', { :action => 'edit', :id => category.id } %></td>
     <td><%= link_to_image 'delete', { :action => 'destroy', :id => category.id },
 :confirm => 'Are you sure you want to delete this category?' %></td>
   </tr>
 <% end %>
 </table>
 <hr />
   <input type="submit" value="New Category..." />
   <input type="button" value="To Dos" onClick="parent.location='<%= url_for(
 :controller => 'items', :action => 'list' ) %>'">
 </form>


 appviewscategoriesnew.rhtml
 <% @heading = "Add new Category" %>
 <%= error_messages_for 'category' %>
 <%= start_form_tag :action => 'create' %>
   <%= render_partial "form" %>
   <hr />
   <input type="submit" value="Save" />
   <input type="button" value="Cancel" onClick="parent.location='<%= url_for( :action
 => 'list' ) %>'">
 <%= end_form_tag %>


 appviewscategoriesedit.rhtml
 <% @heading = "Rename Category" %>
 <%= error_messages_for 'category' %>
 <%= start_form_tag :action => 'update', :id => @category %>
   <%= render_partial "form" %>
   <hr />
   <input type="submit" value="Update" />
   <input type="button" value="Cancel" onClick="parent.location='<%= url_for( :action
 => 'list' ) %>'">
 <%= end_form_tag %>


Navegación a traves del sistema
Los ca mi no s finales d e n avegación a t raves d el sis te m a so n m o s t r a d o s a con tin uació n.
Cualq uier có digo scaffol d re d u n d a n te – eje m plo los arc hivos show.rhtml – p u e n d e ser
si m ple m e n t e eli mi na d o s. Esa es la belle za d el có digo scaffol d – n o le cos to ni ng u n
esf ue r z o crear el có digo e n p ri me r lugar, y u na ve z q u e sirvio s u p r o p o si to, di recta m e n te
lo p u e d e eli mi nar.



Página 34
Nueva
                                                     Tarea



                          Nueva
                         Categoria
                                                      Lista
                                                     Tareas                      Nueva
                                                                                 Nota
                           Lista
                        Categorias

                                                                                  Editar
                                                     Editar                       Not a
                                                     Tarea
                          Editar
                         Categoria




          Ilustración 9 Caminos de navegación a traves de la aplicación

Colocar una página de inicio para la Aplicación
Co m o p a so final, necesita m o s eli mi na r la p a n t alla p o r d efecto 'Bienveni do a Rails' si el
u s ua rio ingresa e n s u n avega d o r http://todo. Hay d o s p a so s:
• Agregar u n a p ági na d e inicio al arc hivo Routes:
    configroutes.rb (fragmento)
      map.connect '', :controller => 'items'
•    re n o m b ra r publicindex.html publicindex.html.orig

Descargar una copia de esta aplicación
Si q uiere u n a co pia d e la a plicación ‘Lista d e Tareas’ p a ra j ugar, h ay u n enlace en
h t t p: / / r ails.ho melin ux.org. Necesita
      •      u sa r Rails p a ra ar m a r la es t r uct u ra d e directo rios (vea Rails en la p ágina 3 )
      •      d e scarga r el archivo todo_app.zip en el n uevo di recto rio crea d o ToDo
      •      d e sco m p ri mi r los arc hivos unzip -o todo_app.zip
      •      re n o m b ra r publicindex.html publicindex.html.orig
      •      si d e sea u sa r la ba se d e d a t o s d e eje m plo, mysql -uroot -p < db/ToDo.sql

Y finalmente
Espero q ue e nc ue n t re es te d oc u m e n t o ú til – sie m p re m e p o n e co n te n t o recibir
co me n t arios, b ue n o s o m alos, a j p mcc@users.so u rceforge.ne t.
Co me n ta rios d e la versió n en es pa ñ ol a e m m a n u eln _at_ g m ail.co m

Feliz d e sa r rollo con Rails!




                                                                                                         Página 35
Apéndice – Cambios posteriores
Des p ues d e escribir ‘Cuat ro Dias’, recibi m u c h o s co me n t a rio s q ue ay u d a ro n a m ej ora r la
calida d d el d oc u m e n t o. Una p reg u n t a a pa recio re pe tí da me n te - “co m o act uali zo m a s d e
u n regist ro d e s de la m i s m a p a n t alla” - en to nces a q ui h ay a pé n dice cub rien d o esta s
Pregu n t a s Frecue n te s. No es el conce p t o m a s fácil d e d o mi na r, y es u n area q u e es pe ra ria
q ue a pa re zca n m a s “ayu da n te s” (hel per s) e n el f ut u r o.

Actualizaciones Multiples
En la captura de pantalla de abajo, el usuario puede tildar / d e s tildar varias “Tareas”
usando las cajas de verificación en la columna de la izquierda, y luego presionar
“Guardar” para guardar los resultados en la base de datos.




Ilustración 10 : Actualizaciones multiples

View
Rails soporta actualizaciones multiples con otra convención de nombres, que es agregar
el id del registro que se esta editan do al nombre entre corchetes [ ]. Esto permite
seleccionar un registro en particular desde multiples registros en la pantalla.

Trabajemos hacia atras desde el HTML que estamos generan do. Esto es lo que se ve para
el registro con id = 6:

<td style="text-align: center">
  <input type="checkbox" id="item_done" name="item[6][done]" value="1" checked />
  <input name="item[6][done]" type="hidden" value="0" />
</td>

(“checked” (seleccionado) es omitido si la casilla de verificación no esta chequeada)

Una forma de generar este código es:
 appviewitems_list_stripes.rhtm (fragmento)
 <td style="text-align: center">
    <%=check_box_tag("item["+list_stripes.id.to_s+"][done]","1",list_stripes["done"]==1)
 %>


                                                                                                     Página 37
<%=hidden_field_tag("item["+list_stripes.id.to_s+"][done]","0") %>
 </td>

Los p a rá m e t r o s p a ra check_box_tag so n name, value = "1", checked = false, options = {};
p a ra hidden_field_tag name, value = nil, options = {}
Document ación: ActionView::Helpers::FormTagHelper

Ade m a s necesita m o s u n bo tó n Guar d a r (Save):
 appviewsitemslist.rhtml (fragmento)
 <% @heading = "To Do List" %>
 <%= start_form_tag :action => 'updater' %>
 <table>
 ...
 </table>
 <hr />
 <%= submit_tag "Save" %>
 <%= submit_tag "New To Do...", {:type => 'button', :onClick=>"parent.location='" +
 url_for( :controller => 'items', :action => 'new' ) + "'" } %>
 <%= submit_tag "Categories...", {:type => 'button', :onClick=>"parent.location='" +
 url_for( :controller => 'categories', :action => 'list' ) + "'" } %>
 <%= end_form_tag %>
 <%= "Page: " + págination_links(@item_pages, :params => { :action => @params["action"]
 || "index" }) + "<hr />" if @item_pages.page_count>1 %>

Controlador
Lo q ue re t o r na d el co nt rola d o r cua n d o se p re sio na el b o t ó n “Guar d ar” es el siguien te
h a s h:
params: {
  :controller=>"items",
  :item=> {
    "6"=>{"done"=>"0"},
    ... etc...
    "5"=>{"done"=>"1"}
   },
  :action=>"updater"
}


Esta m o s interesa d o s en la p a r t e d e :item. Por eje m plo, la linea e n negrita significa “el
regist ro co n el id = 6 tiene el valor d el ca m p o done en 0”. Des de aq ui, es u n t rabajo
ba s ta n te si m ple el d e act uali za r la t abla d e Items:
 appcontrolleritems_controller (fragmento)
    def updater
      @params[:item].each { |item_id, attr|
        item = Item.find(item_id)
        item.update_attribute(:done,attr[:done])
      }
      redirect_to :action => 'list'
    end


each   coloca “6” e n la variable item_id, y “do ne” = > “0” e n attr.
Ruby Document ación: class Array

Este có digo f u ncio na, p e ro si ve q ue es ta p a sa n d o en development.log, vera q ue Rails esta
t rayen d o y act uali za n d o ca da regist ro, sea m o difica do o n o. No solo est o est a crean d o
act u ali zacio nes in necesa rias en la ba se d e d a t o s, p e r o t a m bié n sig nifica q ue updated_on
t a m bié n esta n sien d o m o dificad o, q ue n o es en realida d lo q ue d e sea m o s. Mucho m ej o r

Página 38
My cool new Slideshow!
My cool new Slideshow!
My cool new Slideshow!

Contenu connexe

Tendances

Elastix a Ritmo de Merengue rev 1.3
Elastix a Ritmo de Merengue rev 1.3Elastix a Ritmo de Merengue rev 1.3
Elastix a Ritmo de Merengue rev 1.3edgarjgonzalezg
 
Proyecto integrador aplicaciones smart client
Proyecto integrador   aplicaciones smart clientProyecto integrador   aplicaciones smart client
Proyecto integrador aplicaciones smart clientCarlos Rojo Sánchez
 
Libro Bitcoin: La tecnología Blockchain y su investigación
Libro Bitcoin: La tecnología Blockchain y su investigaciónLibro Bitcoin: La tecnología Blockchain y su investigación
Libro Bitcoin: La tecnología Blockchain y su investigaciónTelefónica
 
Manual de microsoft office access 2010
Manual de microsoft office access 2010Manual de microsoft office access 2010
Manual de microsoft office access 2010Javier Condori Flores
 

Tendances (7)

Elastix a Ritmo de Merengue rev 1.3
Elastix a Ritmo de Merengue rev 1.3Elastix a Ritmo de Merengue rev 1.3
Elastix a Ritmo de Merengue rev 1.3
 
Mat de sec 1°
Mat de sec 1°Mat de sec 1°
Mat de sec 1°
 
Proyecto integrador aplicaciones smart client
Proyecto integrador   aplicaciones smart clientProyecto integrador   aplicaciones smart client
Proyecto integrador aplicaciones smart client
 
Manual de sn_g_carreno
Manual de sn_g_carrenoManual de sn_g_carreno
Manual de sn_g_carreno
 
Libro Bitcoin: La tecnología Blockchain y su investigación
Libro Bitcoin: La tecnología Blockchain y su investigaciónLibro Bitcoin: La tecnología Blockchain y su investigación
Libro Bitcoin: La tecnología Blockchain y su investigación
 
Guia Gpss
Guia GpssGuia Gpss
Guia Gpss
 
Manual de microsoft office access 2010
Manual de microsoft office access 2010Manual de microsoft office access 2010
Manual de microsoft office access 2010
 

En vedette

Escuelas económicas 1
Escuelas económicas 1Escuelas económicas 1
Escuelas económicas 1AldiPittolo
 
Pecha kucha.Alberto Lorente y Luis Marín. NTAE
Pecha kucha.Alberto Lorente y Luis Marín. NTAEPecha kucha.Alberto Lorente y Luis Marín. NTAE
Pecha kucha.Alberto Lorente y Luis Marín. NTAEAlberto Lorente García
 
La educación artística en base al modelo integral
La educación artística en base al modelo integralLa educación artística en base al modelo integral
La educación artística en base al modelo integralTeresa Arias Rojas
 
gana dinero con videos
gana dinero con videosgana dinero con videos
gana dinero con videosHenry Taira
 
B O L E T I N A R T I C U L O U N O J O R G E T O L E D O
B O L E T I N  A R T I C U L O  U N O  J O R G E  T O L E D OB O L E T I N  A R T I C U L O  U N O  J O R G E  T O L E D O
B O L E T I N A R T I C U L O U N O J O R G E T O L E D OJuan Carlos Paredes Plaza
 

En vedette (7)

Medios de comunicacion
Medios de comunicacionMedios de comunicacion
Medios de comunicacion
 
Escuelas económicas 1
Escuelas económicas 1Escuelas económicas 1
Escuelas económicas 1
 
Pecha kucha.Alberto Lorente y Luis Marín. NTAE
Pecha kucha.Alberto Lorente y Luis Marín. NTAEPecha kucha.Alberto Lorente y Luis Marín. NTAE
Pecha kucha.Alberto Lorente y Luis Marín. NTAE
 
La educación artística en base al modelo integral
La educación artística en base al modelo integralLa educación artística en base al modelo integral
La educación artística en base al modelo integral
 
Ppt1 (1)
Ppt1 (1)Ppt1 (1)
Ppt1 (1)
 
gana dinero con videos
gana dinero con videosgana dinero con videos
gana dinero con videos
 
B O L E T I N A R T I C U L O U N O J O R G E T O L E D O
B O L E T I N  A R T I C U L O  U N O  J O R G E  T O L E D OB O L E T I N  A R T I C U L O  U N O  J O R G E  T O L E D O
B O L E T I N A R T I C U L O U N O J O R G E T O L E D O
 

Similaire à My cool new Slideshow!

Similaire à My cool new Slideshow! (20)

Manual usuario publisher
Manual usuario publisherManual usuario publisher
Manual usuario publisher
 
Manual civilcad
Manual civilcadManual civilcad
Manual civilcad
 
Manual usuario ECR SAMPOS ER-009
Manual usuario ECR SAMPOS ER-009Manual usuario ECR SAMPOS ER-009
Manual usuario ECR SAMPOS ER-009
 
Manual usuario ECR SAMPOS ER-059
Manual usuario ECR SAMPOS ER-059Manual usuario ECR SAMPOS ER-059
Manual usuario ECR SAMPOS ER-059
 
Manual blackberry b8520_[www.gsmspain.com]
Manual blackberry b8520_[www.gsmspain.com]Manual blackberry b8520_[www.gsmspain.com]
Manual blackberry b8520_[www.gsmspain.com]
 
Manual Noiseware EspañOl
Manual Noiseware EspañOlManual Noiseware EspañOl
Manual Noiseware EspañOl
 
Manual Noiseware EspañOl
Manual Noiseware EspañOlManual Noiseware EspañOl
Manual Noiseware EspañOl
 
Manual de usuario joomla
Manual de usuario joomlaManual de usuario joomla
Manual de usuario joomla
 
Manual prestashop
Manual prestashopManual prestashop
Manual prestashop
 
Manual desarrollador
Manual desarrolladorManual desarrollador
Manual desarrollador
 
Guia microsoft word
Guia microsoft wordGuia microsoft word
Guia microsoft word
 
Guia microsoft word
Guia microsoft wordGuia microsoft word
Guia microsoft word
 
Word 2007 para blog
Word 2007 para blogWord 2007 para blog
Word 2007 para blog
 
manual impresora.pdf
manual impresora.pdfmanual impresora.pdf
manual impresora.pdf
 
Ikertia y la innovación
Ikertia y la innovaciónIkertia y la innovación
Ikertia y la innovación
 
Cursojoomlacep
CursojoomlacepCursojoomlacep
Cursojoomlacep
 
Curso Joomla
Curso JoomlaCurso Joomla
Curso Joomla
 
Curso joomla
Curso joomlaCurso joomla
Curso joomla
 
Manual Sng CarreñO
Manual Sng CarreñOManual Sng CarreñO
Manual Sng CarreñO
 
Manual Sn G 2da Edicion
Manual  Sn G 2da   EdicionManual  Sn G 2da   Edicion
Manual Sn G 2da Edicion
 

Plus de gealgaro

My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 
My cool new Slideshow!3
My cool new Slideshow!3My cool new Slideshow!3
My cool new Slideshow!3gealgaro
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!gealgaro
 

Plus de gealgaro (13)

My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 
My cool new Slideshow!3
My cool new Slideshow!3My cool new Slideshow!3
My cool new Slideshow!3
 
My cool new Slideshow!
My cool new Slideshow!My cool new Slideshow!
My cool new Slideshow!
 

Dernier

Tecnología Educativa- presentación maestría
Tecnología Educativa- presentación maestríaTecnología Educativa- presentación maestría
Tecnología Educativa- presentación maestríaElizabethLpezSoto
 
La electricidad y la electronica.10-7.pdf
La electricidad y la electronica.10-7.pdfLa electricidad y la electronica.10-7.pdf
La electricidad y la electronica.10-7.pdfcristianrb0324
 
TENDENCIAS DE IA Inteligencia artificial generativa.pdf
TENDENCIAS DE IA Inteligencia artificial generativa.pdfTENDENCIAS DE IA Inteligencia artificial generativa.pdf
TENDENCIAS DE IA Inteligencia artificial generativa.pdfJoseAlejandroPerezBa
 
Análisis de los artefactos (nintendo NES)
Análisis de los artefactos (nintendo NES)Análisis de los artefactos (nintendo NES)
Análisis de los artefactos (nintendo NES)JuanStevenTrujilloCh
 
Actividades de computación para alumnos de preescolar
Actividades de computación para alumnos de preescolarActividades de computación para alumnos de preescolar
Actividades de computación para alumnos de preescolar24roberto21
 
Clasificación de Conjuntos de Datos Desequilibrados.pptx
Clasificación de Conjuntos de Datos Desequilibrados.pptxClasificación de Conjuntos de Datos Desequilibrados.pptx
Clasificación de Conjuntos de Datos Desequilibrados.pptxCarolina Bujaico
 
CommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 TestcontainersCommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 TestcontainersIván López Martín
 
Herramientas que posibilitan la información y la investigación.pdf
Herramientas que posibilitan la información y la investigación.pdfHerramientas que posibilitan la información y la investigación.pdf
Herramientas que posibilitan la información y la investigación.pdfKarinaCambero3
 
ORIENTACIONES DE INFORMÁTICA-2024.pdf-guia
ORIENTACIONES DE INFORMÁTICA-2024.pdf-guiaORIENTACIONES DE INFORMÁTICA-2024.pdf-guia
ORIENTACIONES DE INFORMÁTICA-2024.pdf-guiaYeimys Ch
 
Trabajo de Tecnología .pdfywhwhejsjsjsjsjsk
Trabajo de Tecnología .pdfywhwhejsjsjsjsjskTrabajo de Tecnología .pdfywhwhejsjsjsjsjsk
Trabajo de Tecnología .pdfywhwhejsjsjsjsjskbydaniela5
 
tecnologiaactividad11-240323205859-a9b9b9bc.pdf
tecnologiaactividad11-240323205859-a9b9b9bc.pdftecnologiaactividad11-240323205859-a9b9b9bc.pdf
tecnologiaactividad11-240323205859-a9b9b9bc.pdflauralizcano0319
 
_Planificacion Anual NTICX 2024.SEC.21.4.1.docx.pdf
_Planificacion Anual NTICX 2024.SEC.21.4.1.docx.pdf_Planificacion Anual NTICX 2024.SEC.21.4.1.docx.pdf
_Planificacion Anual NTICX 2024.SEC.21.4.1.docx.pdfBetianaJuarez1
 
Trabajo de tecnología liceo departamental
Trabajo de tecnología liceo departamentalTrabajo de tecnología liceo departamental
Trabajo de tecnología liceo departamentalEmanuelCastro64
 
Trabajando con Formasy Smart art en power Point
Trabajando con Formasy Smart art en power PointTrabajando con Formasy Smart art en power Point
Trabajando con Formasy Smart art en power PointValerioIvanDePazLoja
 
Trabajo de tecnología primer periodo 2024
Trabajo de tecnología primer periodo 2024Trabajo de tecnología primer periodo 2024
Trabajo de tecnología primer periodo 2024anasofiarodriguezcru
 
Slideshare y Scribd - Noli Cubillan Gerencia
Slideshare y Scribd - Noli Cubillan GerenciaSlideshare y Scribd - Noli Cubillan Gerencia
Slideshare y Scribd - Noli Cubillan Gerenciacubillannoly
 
TALLER DE ANALISIS SOLUCION PART 2 (1)-1.docx
TALLER DE ANALISIS SOLUCION  PART 2 (1)-1.docxTALLER DE ANALISIS SOLUCION  PART 2 (1)-1.docx
TALLER DE ANALISIS SOLUCION PART 2 (1)-1.docxobandopaula444
 
Guía de Registro slideshare paso a paso 1
Guía de Registro slideshare paso a paso 1Guía de Registro slideshare paso a paso 1
Guía de Registro slideshare paso a paso 1ivanapaterninar
 
Trabajo de tecnología excel avanzado.pdf
Trabajo de tecnología excel avanzado.pdfTrabajo de tecnología excel avanzado.pdf
Trabajo de tecnología excel avanzado.pdfedepmariaperez
 
Inteligencia Artificial. Matheo Hernandez Serrano USCO 2024
Inteligencia Artificial. Matheo Hernandez Serrano USCO 2024Inteligencia Artificial. Matheo Hernandez Serrano USCO 2024
Inteligencia Artificial. Matheo Hernandez Serrano USCO 2024u20211198540
 

Dernier (20)

Tecnología Educativa- presentación maestría
Tecnología Educativa- presentación maestríaTecnología Educativa- presentación maestría
Tecnología Educativa- presentación maestría
 
La electricidad y la electronica.10-7.pdf
La electricidad y la electronica.10-7.pdfLa electricidad y la electronica.10-7.pdf
La electricidad y la electronica.10-7.pdf
 
TENDENCIAS DE IA Inteligencia artificial generativa.pdf
TENDENCIAS DE IA Inteligencia artificial generativa.pdfTENDENCIAS DE IA Inteligencia artificial generativa.pdf
TENDENCIAS DE IA Inteligencia artificial generativa.pdf
 
Análisis de los artefactos (nintendo NES)
Análisis de los artefactos (nintendo NES)Análisis de los artefactos (nintendo NES)
Análisis de los artefactos (nintendo NES)
 
Actividades de computación para alumnos de preescolar
Actividades de computación para alumnos de preescolarActividades de computación para alumnos de preescolar
Actividades de computación para alumnos de preescolar
 
Clasificación de Conjuntos de Datos Desequilibrados.pptx
Clasificación de Conjuntos de Datos Desequilibrados.pptxClasificación de Conjuntos de Datos Desequilibrados.pptx
Clasificación de Conjuntos de Datos Desequilibrados.pptx
 
CommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 TestcontainersCommitConf 2024 - Spring Boot <3 Testcontainers
CommitConf 2024 - Spring Boot <3 Testcontainers
 
Herramientas que posibilitan la información y la investigación.pdf
Herramientas que posibilitan la información y la investigación.pdfHerramientas que posibilitan la información y la investigación.pdf
Herramientas que posibilitan la información y la investigación.pdf
 
ORIENTACIONES DE INFORMÁTICA-2024.pdf-guia
ORIENTACIONES DE INFORMÁTICA-2024.pdf-guiaORIENTACIONES DE INFORMÁTICA-2024.pdf-guia
ORIENTACIONES DE INFORMÁTICA-2024.pdf-guia
 
Trabajo de Tecnología .pdfywhwhejsjsjsjsjsk
Trabajo de Tecnología .pdfywhwhejsjsjsjsjskTrabajo de Tecnología .pdfywhwhejsjsjsjsjsk
Trabajo de Tecnología .pdfywhwhejsjsjsjsjsk
 
tecnologiaactividad11-240323205859-a9b9b9bc.pdf
tecnologiaactividad11-240323205859-a9b9b9bc.pdftecnologiaactividad11-240323205859-a9b9b9bc.pdf
tecnologiaactividad11-240323205859-a9b9b9bc.pdf
 
_Planificacion Anual NTICX 2024.SEC.21.4.1.docx.pdf
_Planificacion Anual NTICX 2024.SEC.21.4.1.docx.pdf_Planificacion Anual NTICX 2024.SEC.21.4.1.docx.pdf
_Planificacion Anual NTICX 2024.SEC.21.4.1.docx.pdf
 
Trabajo de tecnología liceo departamental
Trabajo de tecnología liceo departamentalTrabajo de tecnología liceo departamental
Trabajo de tecnología liceo departamental
 
Trabajando con Formasy Smart art en power Point
Trabajando con Formasy Smart art en power PointTrabajando con Formasy Smart art en power Point
Trabajando con Formasy Smart art en power Point
 
Trabajo de tecnología primer periodo 2024
Trabajo de tecnología primer periodo 2024Trabajo de tecnología primer periodo 2024
Trabajo de tecnología primer periodo 2024
 
Slideshare y Scribd - Noli Cubillan Gerencia
Slideshare y Scribd - Noli Cubillan GerenciaSlideshare y Scribd - Noli Cubillan Gerencia
Slideshare y Scribd - Noli Cubillan Gerencia
 
TALLER DE ANALISIS SOLUCION PART 2 (1)-1.docx
TALLER DE ANALISIS SOLUCION  PART 2 (1)-1.docxTALLER DE ANALISIS SOLUCION  PART 2 (1)-1.docx
TALLER DE ANALISIS SOLUCION PART 2 (1)-1.docx
 
Guía de Registro slideshare paso a paso 1
Guía de Registro slideshare paso a paso 1Guía de Registro slideshare paso a paso 1
Guía de Registro slideshare paso a paso 1
 
Trabajo de tecnología excel avanzado.pdf
Trabajo de tecnología excel avanzado.pdfTrabajo de tecnología excel avanzado.pdf
Trabajo de tecnología excel avanzado.pdf
 
Inteligencia Artificial. Matheo Hernandez Serrano USCO 2024
Inteligencia Artificial. Matheo Hernandez Serrano USCO 2024Inteligencia Artificial. Matheo Hernandez Serrano USCO 2024
Inteligencia Artificial. Matheo Hernandez Serrano USCO 2024
 

My cool new Slideshow!

  • 1. Cuatro Dias con Rails compilado por John McCreesh traducción por Emmanuel N. Millán
  • 2.
  • 3. Tabla de Contenidos Introducción ...................................................................................................................................................1 Día 1 con Rails ...............................................................................................................................................3 La aplicación ‘Lista de Tareas’ .............................................................................................................3 Ejecutar el script de Rails ......................................................................................................................3 Agregar la aplicación al servidor Web ...............................................................................................3 Definir la aplicación en el archivo de hosts ...............................................................................3 Definir la aplicación en el archivo de configuración de Apache .........................................3 Cambiar a fastcgi ................................................................................................................................4 Chequear que Rails este funcionan d o ..........................................................................................4 Versiones de Rails ..............................................................................................................................4 Configurar la Base de Datos .................................................................................................................4 Crear la tabla Categorias ..................................................................................................................5 Definición MySQL..........................................................................................................................5 Modelo de Datos ............................................................................................................................5 Scaffold .......................................................................................................................................................5 Realzar el Modelo .....................................................................................................................................6 Crear reglas de validación de datos ..............................................................................................7 Dia 2 con Rails ...............................................................................................................................................9 El código generado Scaffold .................................................................................................................9 El controlador ......................................................................................................................................9 La Vista ................................................................................................................................................1 1 Layout .............................................................................................................................................11 Template (plantilla) ....................................................................................................................12 Partial (parcial) .............................................................................................................................12 La vista de renderiza do para la acción “New” ....................................................................13 Analizando la vista de la acción ‘List’...................................................................................14 Modificar el código generado por Scaffold ...................................................................................16 El controlador ....................................................................................................................................16 La Vista (View)...................................................................................................................................16 Mostrar mensajes Flash .............................................................................................................16 Compartir variables entre la plantilla y el Layout ............................................................17 Atando las pantallas de Edit y New .......................................................................................18 Día 3 con Rails ............................................................................................................................................19 La tabla ‘Items’ .......................................................................................................................................19 Definición MySQL de la tabla ........................................................................................................19 El Modelo .............................................................................................................................................19 Validar los links entre las tablas ............................................................................................20 Validar la entrada del usuario .................................................................................................20 La tabla de ‘Notas’.................................................................................................................................20 Definición de la tabla MySQL........................................................................................................20 El modelo ............................................................................................................................................21 Usar un Modelo para mantener Integridad Referencial ..................................................21 Mas de Scaffold ......................................................................................................................................22 Mas acerca de Vistas .............................................................................................................................22 Crear un Layout para la Aplicación ............................................................................................22 La pantalla ‘Lista de tareas’ ...........................................................................................................23 Eliminar ‘tareas’ completadas haciendo click en un ícono ............................................24 Cambiar el modo de ordena mien t o haciendo click en el Encabezado de la Columna .........................................................................................................................................24 Agregar el Helper ........................................................................................................................25 Usar botónes de navegación Javascript ................................................................................25 Formatear una Tabla con un Parcial ......................................................................................25
  • 4. Formato basado en el valor de los Datos ............................................................................27 Manejar valores perdidos en una busqued a ......................................................................27 La pantalla ‘Nueva Tarea’...............................................................................................................27 Crear una lista desplegable para el campo fecha ..............................................................28 Atrapar excepciones con Ruby ................................................................................................28 Crear una lista desplegable desde una tabla de busqueda ............................................29 Crear una lista desplegable para la lista de constant es ..................................................29 Crear una casilla de verificación ............................................................................................29 Toques finales ........................................................................................................................................29 Modificar la hoja de estilos ...........................................................................................................29 La pantalla ‘Editar Tarea’...............................................................................................................30 Dia 4 con Rails ............................................................................................................................................31 Las pantallas ‘Notas’.............................................................................................................................31 Enlazand o ‘Notas’ con ‘Editar Tarea’..........................................................................................31 La pantalla ‘Editar Notas’ ...............................................................................................................32 La pantalla de ‘Nota Nueva’...........................................................................................................33 Guardar y traer Datos usando variables de Sesión ...........................................................33 Cambiar la pantalla de ‘Categorias’ .................................................................................................34 Navegación a traves del sistema .......................................................................................................34 Descargar una copia de esta aplicación ..........................................................................................35 Y finalmente ............................................................................................................................................35 Apéndice – Cambios posteriores ..........................................................................................................37 Actualizaciones Multiples ...................................................................................................................37 View......................................................................................................................................................37 Controlador ........................................................................................................................................38 Consideraciones de la interfaz de usuario ...............................................................................39 Todavía para hacer ................................................................................................................................39
  • 5. Introducción Han habido varias deman da s extravagantes hechas acerca de Rails. Por ejemplo, un articulo publicado en OnLAMP.com 1 deman da n d o que “puedes desarrollar una aplicación web por lo menos diez veces mas rápido con Rails que con un tipico framework Java...” El artículo luego muestra como instalar Rails y Ruby en una PC y contruir una aplicación funcionan d o con “scaffold” virtualmen te sin código. Mientras que esto es impresiona nt e, desarrolladores web “reales” saben que esto es humo y espejos. aplicaciónes ‘reales’ no son tan simples como eso. ¿Qué es realmen te lo que esta pasan do debajo de la superficie? ¿Qué tan dificil es construir aplicaciónes web ‘reales’? Aqui es donde la vida se vuelve un poco difícil. Rails tiene muy buena documen t ación on - line, de hecho, posiblement e esta demasiado bien docume n t a d o para principiantes, con mas de 30.000 palabras de docume n t ación on- line en el formato de manual de referencia. Lo que esta faltando en un road ma p (railmap?? - mapa del camino) apunta n d o a las páginas claves que necesitas saber para comen za r a desarrollar con Rails. Este documen t o está para llenar ese vacio. Asume que ya tienes Ruby y Rails en funciona mient o en una PC (si no has llegado tan lejos, ve devuelta y sigue el articulo de Curt). Esto te lleva al final de ‘Dia 1 con Rails’. ‘Dia 2 con Rails’ comienza posicionan d o se detras del humo y los espejos. Lo lleva a traves del código ‘scaffold’. Nuevas características son remarcadas en negrita, explicadas en el texto, y seguidas por una referencia a la documen t acio de Rails o de Ruby donde puedes aprender más. ‘Dia 3 con Rails’ toma scaffold y comien za a construir algo reconocible como una aplicación “real”. Todo el tiempo, esta contruyen d o su propia caja de herra mient as con Rails. Lo mas importa nt e de todo, deberia también sentirse comodo con la documen t ación en linea para que pueda continuar con la exploración usted solo. ‘Dia 4 con Rails’ agrega otra tabla y trata con algunas de las complejidades de mantene r la integridad referencial. Al final, tendra una aplicación en funciona mient o, suficientes herra mient as como para comenza r, y el conocimient o de donde buscar mas información. Diez veces mas rápido? Después de cuatro dias con Rails, juzguelo por usted mismo! Documentación : este documen t o contiene referencias destacadas, a cualquiera de los siguientes sitios: • Docu m e nt ación – La d oc u m e n t ació n d e Rails en h t t p: / / a pi.r u byo n rails.co m (Esta d oc u m e n t ació n t a m bié n est a inst ala d a en s u PC co m o p a r te d e la ins talación d e ge m s u bica d a en u n lugar co m o C:Program Filesrubylibrubygemsn.ndocactionpack- n.n.nrdocindex.html) • Rub y Docu m e n t ación – “Progra m mi ng Ruby - The Prag m a tic Progra m m e r's Guide” dis p o nible en linea y p a ra bajar en h t t p: / / www.ru by - d oc.org / d ocs / r u by - d oc - b u n dle /Progra m mi ngRuby /i n d ex.ht ml 1 Rolling with Ruby on Rails, Curt Hibbs 20- Jan2005 http: / / w ww.onla m p.co m / p u b / a / o n l a m p / 2 0 0 5 / 0 1 / 2 0 / r a ils.ht m l Página 1
  • 6. Reconocimiento s : m u c h as gracias a la ge n te en el canal irc 2 y e n la lista d e correo 3 . El regist ro d e arc hivos e n linea fue u n a invaluable asiste ncia m ie n t ras a p re n dia Rails y Ruby. Versión: 2.3 usand o la versión 0.12.1 de Rails – vea http: / / r ails.ho melin ux.org para la última versión y para bajar una copia del futuro código. Document o escrito y pdf generado con OpenOffice.org 'Writer'. Copyright : este trabajo tiene copyright ©2005 John McCreesh jpmcc@users.sourceforge.net y esta bajo la licencia Creative Com mo ns Attribution - NonCo m m e rcial - ShareAlike License . Para ver una copia de esta licencia, visite http: / / c re a tiveco m m o n s.org / licenses / b y - nc- sa/2.0 / o envie una carta a Creative Commo ns, 559 Nathan Abbott Way, Stanford, California 94305, USA. 2 irc:/ /i rc.freeno de.org / r u byon rails 3 http: / / li s t s.rubyonrails.org / m a il m a n / li s tinfo / r ails Página 2
  • 7. Día 1 con Rails La aplicación ‘Lista de Tareas’ Este d oc u m e n t o sig ue la co n s t r ucción d e u n a si m ple a plicació n d e “lista d e ta reas” – el ti p o d e cosa q ue tienes e n t u PDA, co n u n a lista d e ite m s, agr u p a d o s e n categorias, con n o ta s o pcio nales (para ver u n a a delan t o d e co m o se va a ver, vea Ilustración 5: La p a nt alla de ‘Lista de T areas’ en la p ági na 2 3 ). Ejecutar el script de Rails Este ejemplo esta en mi PC MS- Windows. Mi material de web esta en c:wwwwebroot, que etiqueto como mi disco w: para acortar el tipeo: C:> subst w: c:wwwwebroot C:> w: W:> rails ToDo W:> cd ToDo W:ToDo> Ejecutar rails ToDo crea un nuevo directorio ToDo y lo puebla con una serie de archivos y subdirectorios, los mas importan t es de estos son los siguientes: app contiene el nucleo de la aplicación, dividida en los subdirectorios modelos (model), vistas(view), controladores(controller), y 'ayudantes'(helper) config contiene el archivo database.yml que provee detalles de la base de datos a utilizar con la aplicación log registros especificos de la aplicación. Nota: development.log mantiene una traza de cada acción que Rails realiza – muy util para rastrear errores, pero no necesita ser purgado regularmente! public el directorio disponible para Apache, que incluye imagenes, javascripts, y subdirectorios para stylesheets Agregar la aplicación al servidor Web Como yo estoy ejecutand o todo (Apache2, MySQL, etc) en una sola PC de desarrollo, los siguientes dos pasos dan un nombre amigable para la aplicación en mi navegador. Definir la aplicación en el archivo de hosts C:winntsystem32driversetchosts (fragmento) 127.0.0.1 todo Definir la aplicación en el archivo de configuración de Apache Apache2confhttpd.conf <VirtualHost *> ServerName todo DocumentRoot /www/webroot/ToDo/public <Directory /www/webroot/ToDo/public/> Options ExecCGI FollowSymLinks AllowOverride all Allow from all Order allow,deny </Directory> </VirtualHost> Página 3
  • 8. Cambiar a fastcgi A menos que sea paciente (o que tenga una PC potente) deberia habilitar fastcgi para esta aplicación. public.htaccess # Para mejor desempeño reemplaze el despachador con el de fastcgi RewriteRule ^(.*)$ dispatch.fcgi [QSA,L] Chequear que Rails este funcionando El sitio ahora deberia ser visible en su navegador como http://todo/ (debería ver la página Congratulations, you've put Ruby on Rails! en su navegador). Versiones de Rails Para el m o m e n t o q ue leas este d oc u m e n t o, Rails p r o b able me n te h aya ava n z a d o varias versió nes. Si inte n t as avan za r a t raves d e este d oc u m e n t o, cheq uea la versión ins tala da en t u PC: W:ToDo>gem list --local Si s o n dis tin ta s a las versió ne s lista da s abajo, e n t o nces yo fue rte m e n te aco n sejaria q u e baje las versió nes u s a d a s en “Cuat ro dias co n Rails”, eje m plo: W:ToDo>gem install rails --versión 0.12.1 Esto n o ro m p e ra n a d a; la libreria ge m s d e Ruby es ta di se ña d a p a ra m a neja r m ul ti ples versió nes. Ento nces p ue de for z a r a Rails a q u e u se las versió nes u tili za d a s e n “Cuat ro Dias” en la a plicación ‘Lista d e Tareas’ es pecifican d o: configenvironment.rb (fragmento) # Require Rails libraries. require 'rubygems' require_gem 'activesupport', '= 1.0.4' require_gem 'activerecord', '= 1.10.1' require_gem 'actionpack', '= 1.8.1' require_gem 'actionmailer', '= 0.9.1' require_gem 'actionwebservice', '= 0.7.1' require_gem 'rails', '= 0.12.1' La ra z ó n p a ra u sa r la m i s m a versió n es m uy si m ple. ‘Cuat ro Dias’ u s a m uc h o có digo genera d o a u t o m a tica me n te p o r Rails. Mient ras Rails se d e sa r rolla, t a m bié n lo h ace es te có digo – d e safo rt u n a d a m e n t e, es te d oc u m e n t o n o lo h ace (hasta q ue se p r o d uce u n a n u eva versió n!). Ento nces, h a s t u vida fácil, y m a n t e ne la m i s m a versió n q u e se u sa e n ‘Cuat ro Dias’. Una ve z q ue h ayas t er mi na d o d e t rabajar co n ‘Cuatro Dias’, ve a la úl ti ma y gra n versió n d e Rails y ve q ue m ejo ra s los d e sa rr ollad o res d e Rails h a n reali za d o. Configurar la Base de Datos He configurad o una nueva base de datos llamada ‘todos’ en MySQL. La conexión a la base de datos es especificada en el archivo configdatabase.yml configdatabase.yml (fragmento) development: adapter: mysql database: todos host: localhost username: foo password: bar Página 4
  • 9. Crear la tabla Categorias La tabla categories (categorias) es utilizada en los ejemplos siguientes. Es una simple lista de categorias que seran usadas para agrupar los items en la Lista de Tareas. Definición MySQL Tabla Categories CREATE TABLE `categories` ( `id` smallint(5) unsigned NOT NULL auto_increment, `category` varchar(20) NOT NULL default '', `created_on` timestamp(14) NOT NULL, `updated_on` timestamp(14) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `category_key` (`category`) ) TYPE=MyISAM COMMENT='List of categories'; Algunos tips para los nombres de las tablas y campos: • Guiones bajos en el nombre de los campos seran cambiados por espacios por Rails para obtener nombres ‘amigables al humano’ • tener cuidado con la mezcla de mayusculas y minisculas en el nombre del campo – algunas partes del código de Rails son sensibles a mayusculas y minisculas. • Cada tabla deberia tener una clave primaria llamada ‘id ’ - en MySQL es mas fácil tener este campo como un numeric auto_increment • enlaces a otras tablas deberian seguir la misma convencion de nombre ‘_id’ • Rails auto matica men t e manten d r a los campos llamados created_at/created_on o updated_at/updated_on, entonces es una buena idea agregarlos Document ación: ActiveRecord::Timesta m p • Tip útil: si esta construyen d o un sistema multiusuario (no es relevante aqui), Rails también utilizara el bloqueo optimista si agrega un campo llamado lock_versión (integer default 0). Todo lo que necesita recordar es incluir lock_versión como un campo oculto en sus formularios de actualización. Document ación: ActiveRecord::Locking Modelo de Datos Genera un archivo vacio: W:ToDo>ruby script/generate model category exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/category.rb create test/unit/category_test.rb create test/fixtures/categories.yml W:ToDo> q ue crea u n archivo category.rb, y d o s arc hivos d e p r u eba category_controller_test.rb y categories.yml. Agregare m o s algu na s en t ra d a s e n el m o d elo d e d a t o s e n u n mi n u t o – d ejelo vacio p o r el m o m e n t o. Scaffold El controlador es el corazón de la aplicación Rails. Ejecutar el script generador del controlador W:ToDo>ruby script/generate controller category exists app/controllers/ Página 5
  • 10. exists app/helpers/ create app/views/category exists test/functional/ create app/controllers/category_controller.rb create test/functional/category_controller_test.rb create app/helpers/category_helper.rb W:ToDo> que crea dos archivos y dos directorios vacios: appcontrollerscategory_controller.rb apphelperscategory_helper.rb appviewscategories appviewslayouts Si no ha visto el truco modelo / scaffold en funciona mient o en un tutorial de principiante como “Rolling with Ruby on Rails”, pruebelo ahora y asombrese de como toda una aplicación web puede estar escrita en una sola linea de código: appcontrollerscategory_controller.rb class CategoryController < ApplicationController scaffold :category end Document ación: ActionController::Scaffolding Ap u n te s u n avega d o r a http://todo/category y a d mi re q ue t a n ingenioso es : - ) Ilustración 1 : pantalla 'Lista' Scaffold Para averigüar q u e ta n inge nioso n o es, inte n te agregar la m i s m a categoria d o s veces. Rails fracasa rá y d a ra u n s ucio m e n saje d e erro r ‘ActiveRecor d::State me n tInvalid in Category#create’. Pue de ar reglar est o agrega n d o validació n al Modelo. Realzar el Modelo El Modelo es donde toda las reglas relacionadas con datos son guarda das, incluida la validación y integridad relacional. Esto significa que puede definir una sola regla, y Rails automáticame n t e la aplicará donde sea que el dato es accedido. Página 6
  • 11. Crear reglas de validación de datos Rails otorga mucho manejo de errores gratis (casi). Para demost rar esto, agregue algunas reglas de validación al modelo de categoría vacio: appmodelscategory.rb class Category < ActiveRecord::Base validates_length_of :category, :within => 1..20 validates_uniqueness_of :category, :message => "already exists" end Estas entradas automa tica men t e chequearan que: • validates_length_of: el ca m p o n o este en vacio y n o sea m uy largo • validates_uniqueness_of: valores d u plica d os so n at ra p a d o s. No m e gu s t a el m e n s aje d e erro r p o r d efecto d e Rails - ‘xxx has already been taken’ - en t o nces d oy mi p r o pio m e n s aje. Esta es u n a característica general d e Rails – p ri m e ro p r u ebe los valores p o r d efecto, si n o le g us t a n, s ob reescribalos. Document ación: ActiveRecord::Validations::ClassMethods Página 7
  • 12. Para p r o ba r es to, a h o ra inte n t a agregar u n regist ro d u plica d o d e n u evo. Esta ve z, Rails m a n eja el erro r e n ve z d e “ro m p e r se” - vea abajo. El estilo es ta u n p oco en s u cara – n o es la in terfa z d e u s u a rio m a s s u til. De t o d a s for m a s, q ue es pera si es gratis? Ilustración 2 : Capturan d o errores de datos Página 8
  • 13. Dia 2 con Rails Para progresar mas alla de este punto, necesita mo s ver que esta pasando detras de la escena. Durante el dia 2, trabajare m o s sistematica me n t e a traves del código scaffold generado por Rails, decifrando que significa todo. Con la acción scaffold, Rails genera todo el código que necesita dinámica me n t e. Ejecutando scaffold como un script , podemo s obtener todo el código escrito al disco donde lo pode mo s investigar y luego comen za r a modificarlo para ajustarse a nuestros requeri mient os. Ejecutar el script generate scaffold W:ToDo>ruby script/generate scaffold category dependency model exists app/models/ exists test/unit/ exists test/fixtures/ skip app/models/category.rb skip test/unit/category_test.rb skip test/fixtures/categories.yml exists app/controllers/ exists app/helpers/ create app/views/categories exists test/functional/ create app/controllers/categories_controller.rb create test/functional/categories_controller_test.rb create app/helpers/categories_helper.rb create app/views/layouts/categories.rhtml create public/stylesheets/scaffold.css create app/views/categories/list.rhtml create app/views/categories/show.rhtml create app/views/categories/new.rhtml create app/views/categories/edit.rhtml create app/views/categories/_form.rhtml W:ToDo> Este script genera un rango de archivos necesarios para crear una aplicación completa, incluyendo un controlador, vistas, layouts, e incluso hojas de estilo (css). Note la p e q u e ña bi za r ra convenció n d e n o m b res – n o s h e m o s m ovi do d el si ng ular a pl u ral, e n t o nces p a ra u s a r el n u evo có digo n ecesita a p u n t a r el n avega d o r a http://todo/categories. De hec ho, p a ra evitar co nf u sio ne s, es m ejo r bo rra r appcontrollerscategory_controller.rb etc e n caso d e q ue lo ejecute accide n tal me n te. El código generado Scaffold El controlador Vea m o s el có digo d e t ra s d el co n t rola d o r. El co n t rola d o r es d o n d e d e sca n sa la p r og ra m ació n lógica d e la a plicación. Interact ua con el u s u a rio u sa n d o vistas (views), y con la base d e d a t o s a t raves d e los m o d elos (mo dels). Deberia p o d e r leer el con t rola d o r y ver co m o la a plicació n esta u ni da. El controlador producido por el script generar scaffold es listado abajo: appcontrollerscategories_controller.rb class CategoriesController < ApplicationController def index list render_action 'list' end def list Página 9
  • 14. @category_pages, @categories = paginate :category, :per_page => 10 end def show @category = Category.find(@params[:id]) end def new @category = Category.new end def create @category = Category.new(@params[:category]) if @category.save flash['notice'] = 'Category was successfully created.' redirect_to :action => 'list' else render_action 'new' end end def edit @category = Category.find(@params[:id]) end def update @category = Category.find(@params[:id]) if @category.update_attributes(@params[:category]) flash['notice'] = 'Category was successfully updated.' redirect_to :action => 'show', :id => @category else render_action 'edit' end end def destroy Category.find(@params[:id]).destroy redirect_to :action => 'list' end end Cuando el usuario de la aplicación Rails selecciona una acción – ejemplo: ‘Show’ (mostrar) – el controlador ejecutará cualquier código de la sección apropiada – ‘def show’ - y luego por defecto renderizara una plantilla con el mismo nomb re - ‘show.rthml’. Este comport a mi en t o por defecto puede ser sobreescrito: • render_template le permite renderizar una plantilla diferente – ejemplo: la acción index ejecutara el código de la acción ‘list’ - ‘def list’, y renderizara list.rhtml en vez de index.rhtml (que no existe) • redirect_to va un nivel mas alla, y utiliza una respuesta externa HTTP ‘302 moved’ para volver al controlador – ejemplo: la acción destroy no necesita renderizar una plantilla. Despues de realizar su proposito principal (destruir una categoria), simpleme n t e lleva al usuario a la acción list. Document ación: ActionController::Base El controlador ActiveRecord usa métodos como find (encontrar), find_all (encontrar todos), new (nuevo), save (guardar), update_attributes (actualizar atributos), y destroy (destruir) para mover datos a y desde las tablas de la base de datos. Note que no tiene que escribir ninguna sentencia SQL, pero si desea ver que SQL Rails esta usando, esta todo escrito en el archivo development.log. Página 10
  • 15. Document ación: ActiveRecord::Base Note co m o u n a activida d lógica d e s d e la p e r s p ectiva d el u s u a rio p ue de req u erir d o s p a s o s a t raves d el con t r ola do r: p o r eje m plo, act uali za r u n regist r o en la ta bla. Cua n d o el u s ua rio selecciona ‘Edit’, el con t r ola do r ext rae el regist ro q u e se d e sea e ditar d el m o d elo, y re n de ri za la vista edit. Cua n d o el u s u a rio finaliz o la e dición, la vista edit invoca la acció n update, q ue act uali za el m o d elo y luego invoca la acció n show. La Vista Las vistas s o n d o n d e se d efine la interfa z d el u s ua rio. Rails p u e d e re n de ri za r la p ági na HTML fi nal p rese n ta da al u s u a rio d e s de t res co m p o n e n te s: Layout Template - Plantilla Partial - Parcial e n appviewslayouts e n appviews<controller> e n appviews<controller> p o r d efecto: application.rhtml p o r d efecto: <action>.rhtml p o r d efecto _<partial>.rhtml o <controller>.rhtml • Un Layo ut p r ovee có digo co m u n u sa d o p o r t o d a s las acció nes, ti pica me n t e el co mien z o y final d el HTML envia do al n avega do r. • Un Te m plate o Plan tilla p rovee el có digo es pecifico a ca da acción, eje m plo có digo d e ‘List’, có digo d e ‘Edit’, etc. • Un Partial o Parcial p r ovee có digo co m u n - ‘subr u ti nas’ - q u e p ue de se r u s a d o en m ul ti ples acció nes – eje m plo: có digo u s a d o p a ra m o s t r ar ta blas en u n fo r m ulario. Layout Convención de nombres en Rails: si hay una plantilla en appviewslayouts con el mismo nombre que el controlador actual entonces sera utilizada auto máticame n t e como layout del controlador a menos que explícitamen te se indique lo contrario. Un layout con el nombre de application.rhtml o application.rxml sera configurado como el controlado r por defecto si no existe un layout con el mismo nombre que el controlador actual, y no existe un layout asignado explicitamen t e. El layout generado por el script scaffold se ve como esto: appviewslayoutscategories.rhtml <html> <head> <title>Categories: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold' %> </head> <body> <%= @content_for_layout %> </body> </html> Esto es en su mayoria HTML, mas algunos bits de código Ruby embebido entre etiquetas <% %>. Este layout sera llamado por el proceso de renderi za d o sin considerar la acción que se este ejecutan d o. Contiene etiquetas estan da r HTML – las <html><head>...</head><body>...</body></html> que aparecen en todas las páginas. Las partes de Ruby en negrita son traducidas a HTML durante el proceso de renderizad o Página 11
  • 16. de Rails como se muest ra a continuación: • es un método ActionController que devuelve el nombre de la acción que el action_name controlador esta procesan do (ejemplo ‘List’) - esto coloca el titulo de la página apropiado, depen dien d o de la acción que se esta ejecutan d o. Document ación: ActionController::Base • stylesheet_link_tages un helper (ayudante) de Rails – una manera perezosa de generar código. Hay muchos de estos ‘ayudantes’ dentro de Rails. Este simplemen te genera el siguiente código HTML: <link href="/stylesheets/scaffold.css" media="screen" rel="Stylesheet" type="text/css" /> Document ación: ActionView::Helpers::AssetTagHelper • es la clave de lo que pasa a continuación. Permite a un unico layout content_for_layout estan dar tener contenido dinamico insertado en tiempo de renderizad o basado en la acción ejecutada (ejemplo ‘edit’, ‘new’, ‘list’). Este contenido dinamico proviene de un Template (plantilla) con el mismo nombre – ver abajo. Document ación: ActionController::Layout::ClassMethods. Template (plantilla) Convención de nombres de Rails: las plantillas estan guardad as en appviewscategories‘acción’.rhtml. El nuevo .rhtml creado por el script scaffold es mostra do a continuación: appviewscategoriesnew.rhtml <h1>New category</h1> <%= start_form_tag :action => 'create' %> <%= render_partial "form" %> <%= submit_tag "Create" %> <%= end_form_tag %> <%= link_to 'Back', :action => 'list' %> • start_form_tag es un ayudante (helper) de Rails para iniciar un formulario HTML – aqui genera <form action="/categories/create" method="post"> • submit_tag por si misma generaria <input name="submit" type="submit" value="Save changes" />, pero el parámet ro “Create” sobreescribe el valor por defecto “Save changes” con “Create” • end_form_tag solo imprime </form>, no es el helper de Rails mas útil creado :- ) pero provee un final satisfactorio para el bloque de código Document ación: ActionView::Helpers::FormTagHelper • invocará un Partial (parcial) _form.rhtml – vea la siguiente sección. render_partial Document ación: ActionView::Partials • link_to simplemen te crea un link – la parte mas funda m e n t al de HTML... <a href="/categories/list">Back</a> Document ación: ActionView::Helpers::UrlHelper Partial (parcial) Convención de nombres de Rails: un parcial ‘foo’ estara en el archivo Página 12
  • 17. appviews‘action’_foo.rhtml (note el guion bajo inicial). Scaffol d u sa el mi s m o có digo p a ra p r ocesa r a m b a s ‘edit’ y ‘new’ acció nes, en to nces coloca el có digo en u n p a rcial, invoca d o p o r el m é t o d o render_partial. appviewscategories_form.rhtml <%= error_messages_for 'category' %> <!--[form:category]--> <p><label for="category_category">Category</label><br/> <%= text_field 'category', 'category' %></p> <p><label for="category_created_on">Created on</label><br/> </p> <p><label for="category_updated_on">Updated on</label><br/> </p> <!--[eoform:category]--> • error_messages_fordevuelve una cadena con marca – texto para cualquier mensaje de error producido por un intento de enviar el formulario. Si uno o mas errores son detectados, el HTML se vera asi: <div class="errorExplanation" id="errorExplanation"> <h2>n errors prohibited this xxx from being saved</h2> <p>There were problems with the following fields:</p> <ul> <li>field_1 error_message_1</li> <li>... ...</li> <li>field_n error_message_n</li> </ul> </div> Vimos esto en acción en el Día 1 - Ilustración 2: Capturando errores de datos en la página 8 . Nota: las etiquetas css igualan las correspo n dien tes declaraciones en la hoja de estilos creada por el script generar scaffold. Document ación: ActionView::Helpers::ActiveRecordHelper • text_field es un helper de Rails que genera este HTML: <input id="category_category" name="category[category]" size="30" type="text" value="" />. El primer parámet ro es el nombre de la tabla; el segund o es el nombre del campo. Document ación: ActionView::Helpers::FormHelper Note u n p e q ue ñ o b u g e n Rails – sa be co m o n o crear u n ca m p o d e en t ra da p a ra los ca m p o s re serva d o s create d_o n y u p d a t e d_on , p e ro a u n asi ge ne ra las etiq ue ta s p a ra ellos. La vista de renderizado para la acción “New” Estamos ya en posición de mirar el código que devuelve al navegador en respuesta a la acción “New”, y ver de donde vino todo. El Layout provee el texto en negrita; la plantilla (template) el texto regular; y el parcial el texto en Italica : appviewscategoriesnew.rhtml <html> <head> <title>Categories: new</title> <link href="/stylesheets/scaffold.css" media="screen" rel="Stylesheet" type="text/css" /> </head> Página 13
  • 18. <body> <h1>New category</h1> <form action="/categories/create" method="post"> <!--[form:category]--> <p><label for="category_category">Category</label><br/> <input id="category_category" name="category[category]" size="30" type="text" value="" /></p> <p><label for="category_created_on">Created on</label><br/> </p> <p><label for="category_updated_on">Updated on</label><br/> </p> <!--[eoform:category]--> <input name="submit" type="submit" value="Create" /> </form> <a href="/categories/list">Back</a> </body> </html> Analizando la vista de la acción ‘List’ Las vistas ‘Edit’ y ‘Show’ so n si milares a la vista ‘New’. ‘List’ co ntiene algu n o s t r ucos n u evos. Recuer de co m o el co n t rola d o r ejecut o la siguien te pie z a d e có digo a n t es d e re n d eri za r la pla n tilla ‘List’: @category_pages, @categories = paginate :category, :per_page => 10 p agina te p u e bla la variable d e ins ta ncia @categories con regist ro s o r de n a d o s d e la t abla Categories, :per_page regist ra p o r ve z, y con tie ne t o d a la lógica p a ra la n avegació n a la p ágina sig uie n te / a n terio r. @category_pages es u n a ins ta ncia a Paginator. Co m o s o n u s a d a s e n la pla n tilla se ex plican al final d e la sig uien te secció n. Document ación: ActionController::Pagination La pla n tilla se ve co m o sigue: appviewscategorieslist.rhtml <h1>Listing categories</h1> <table> <tr> <% for column in Category.content_columns %> <th><%= column.human_name %></th> <% end %> </tr> <% for category in @categories %> <tr> <% for column in Category.content_columns %> <td><%=h category.send(column.name) %></td> <% end %> <td><%= link_to 'Show', :action => 'show', :id => category %></td> <td><%= link_to 'Edit', :action => 'edit', :id => category %></td> <td><%= link_to 'Destroy', {:action => 'destroy', :id => category}, :confirm => "Are you sure?" %></td> </tr> <% end %> </table> Página 14
  • 19. <%= link_to "Previous page", { :page => @category_pages.current.previous } if @category_pages.current.previous %> <%= link_to "Next page", { :page => @category_pages.current.next } if @category_pages.current.next %> <br /> <%= link_to 'New category', :action => 'new' %> • content_columns devuelve un array de objetos columna excluyendo cualquier columna ‘especial’ (la clave primaria id, todas las columnas que finalizen con ‘_id’ o ‘_count’, y columnas usadas para herencia de tablas) Document ación: ActionController::Base • es un sinóni mo de human_attribute_name, que transfor m a nombre de human_name atribut os claves en un formato leible para el huma no, como ‘Primer nombre’ en vez de ‘primer_nombre’ Document ación: ActiveRecord::Base • h automáticame n t e ‘sale’ del código HTML. Uno de los problemas en permitirle al usuario que ingrese datos que luego son mostrad o s en la pantalla es que pueden accidental me n t e (o maliciosamen te) ingresar código que podria romper el sistema cuando es mostra do 4 . Para cuidarse contra esto, es buena practica utilizar ‘escape HTML’ con cualquier dato que es provisto por el usuario. Esto significa que por ejemplo </table> es renderiza d o como &lt;/table&gt; que es inofensivo. Rails hace esto realmente simple – solo agrega una ‘h’ como se muestra. • confirm es u n p a rá m e t r o o pcio nal m uy ú til p a ra el hel per link_to – genera u n a caja e me rge n t e d e JavaScri p t q ue f uer z a al u s u a rio a confir ma r la acció n Destroy a n tes d e ejecu ta r el link: Ilustración 3 : Javascript emergente Document ación: ActionView::Helpers::UrlHelper La lógica d e la p ági na se aclara u n p oco. Ruby p u e de u tili za r if co m o m o difica do r: expresion if expresion-booleana evalua expresion solo si expresion-boolean es ver da de ra. @category_pages.current d ev uelve u n object o Página re p re se n t a n d o la p ági na act u al. ActionController::Pagination::Paginator y @category_pages.current.previous d ev uelve u n n u evo objeto Página re p rese n t a d o la p ágina a n terio r a la act ual, o n ulo si esta es la p ri m e ra p ági na. ActionController::Pagination::Paginator::Page 4 Por ejemplo, piense que pasaria si un usuario tipea “< / t a ble >” como una categoria. Página 15
  • 20. Ento nces, si h ay u n a p ágina a n te rior a la cual n avegar, este co nt r uc to r m o s t ra rá u n link; si n o h ay ni ng u n a, el link es s u p ri mi d o. El có digo genera d o p a ra la p ágina n se vera asi: <a href="/categories/list?page=[n-1]">Previous page</a> <a href="/categories/list?page=[n+1]">Next page</a> Modificar el código generado por Scaffold El có digo genera d o p o r el scri p t Scaffold es p e rfecta me n te u sa ble, y es r ob u s t o u n a ve z q ue h aya agrega d o s uficiente vali dació n al m o d elo d e d a t o s. De t o d a s for m a s, si es to fuera t o d o el d e sa r rollo n ecesario p a ra a plicació nes Rails, en t o nces los p rogra m a d o res se q ue da rian si n t rabajo, q u e clara m e n te n o es algo b ue n o : - ) asi q u e reali ze m o s algu n as m o dificaciones: El controlador En la vista ‘List’, esperaria que los registros sean mostrad o s en orden alfabético. Esto requiere un cambio menor al controlador: appcontrollerscategories_controller.rb (fragmento) def list @category_pages, @categories = paginate :category, :per_page => 10, :order_by => 'category' end Document ación: ActionController::Pagination En esta aplicación, la pantalla show es innecesaria – todos los campos entran comoda me n t e en una sola linea de la pantalla. Entonces, def show puede desaparecer, y vayamos directa me n t e a la pantalla list despues de un ‘Edit’: appcontrollerscategories_controller.rb (fragmento) def update @category = Category.find(@params[:id]) if @category.update_attributes(@params[:category]) flash['notice'] = 'Category was successfully updated.' redirect_to :action => 'list' else render_action 'edit' end end El mensaje flash será toma do y mostrara en la siguiente pantalla – en este caso, la pantalla list. Por defecto, el script scaffold no muestra mensajes flash – cambiare mo s esto en un minuto – vea abajo. La Vista (View) Mostrar mensajes Flash Rails p rovee u n a t écnica p a ra p a sa r m e n sajes flas h al u s ua rio – eje m plo, u n m e n s aje d e ‘Act uali zació n Exitosa’ q u e se m u e s t ra en la sig uien te p a n t alla y luego d e sa pa rece. Esto s p u e de n ser t o m a d o s fácil me n t e co n u n p e q ue ño ca m bio al Layo ut (agregarlo al Layou t significa q ue a pa recera n en cualq uier p a n talla): appviewslayoutscategories.rhtml<html> <head> <title>Categories: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold' %> Página 16
  • 21. </head> <body> <h1><%=@heading %></h1> <% if @flash["notice"] %> <span class="notice"> <%=h @flash["notice"] %> </span> <% end %> <%= @content_for_layout %> </body> </html> Document ación: ActionController::Flash Un simple agregado a la hoja de estilo hace que el mensaje flash sea mas visible: publicstylesheetsscaffold.css (fragmento) .notice { color: red; } Compartir variables entre la plantilla y el Layout Note que he movido el texto encabeza d o <h1>...</h1> de la plantilla al Layout para que aparezca sobre el mensaje flash. Como cada plantilla tendra un encabezad o diferente, necesito colocar el valor de la variable @heading en la plantilla. Rails no tiene problemas con esto – variables de plantilla estan disponibles para los Layouts en tiempo de renderiza do. He realizado este cambio y algunos cambios de formato para terminar mi plantilla: appviewscategorieslist.rhtml <% @heading = "Categorias" %> <table> <tr> <th>Categoría</th> <th>Creada</th> <th>Actualizada</th> </tr> <% for category in @categories %> <tr> <td><%=h category["category"] %></td> <td><%= category["created_on"].strftime("%I:%M %p %d-%b-%y") %></td> <td><%= category["updated_on"].strftime("%I:%M %p %d-%b-%y") %></td> <td><%= link_to 'Editar', :action => 'edit', :id => category %></td> <td><%= link_to 'Eliminar', {:action => 'destroy', :id => category}, :confirm => "¿Esta seguro que desea eliminar esta categoria?" %></td> </tr> <% end %> </table> <br /> <%= link_to 'Nueva categoría', :action => 'new' %> <% if @category_pages.page_count>1 %> <hr /> Page: <%=págination_links @category_pages %> <hr /> <% end %> • No me gusta el format o de la fecha por defecto, entonces uso el método strftime() de Ruby para formatear los campos de fecha y hora a la forma que quiero. Ruby Document ación: class Time Página 17
  • 22. págination_links crea u n a ba r ra lin k HTML bá sica p a ra u n p agi na d o r d a d o ActionView::Helpers::PaginationHelper Atando las pantallas de Edit y New Un par de cambios al Parcial utilizado por ‘New’ y ‘Edit’: usé una tabla para mejorar el layout; deshacer me de las innecesarias etiquetas created_on/ updated_on; y prevenir que el usuario tipee mucho dentro del campo Category: appviewscategories_form.rhtml <%= error_messages_for 'category' %> <table> <tr> <td><b><label for="category_category">Category:</label></b></td> <td><%= text_field "category", "category", "size"=>20, "maxlength"=>20 %></td> </tr> </table> y algunos cambios menores a las dos plantillas (note en particular el uso de @heading):: appviewscategoriesEdit.rhtml <% @heading = "Edit Category" %> <%= start_form_tag :action => 'update', :id => @category %> <%= render_partial "form" %> <hr /> <%= submit_tag "Save" %> <%= end_form_tag %> <%= link_to 'Back', :action => 'list' %> appviewscategoriesNew.rhtml <% @heading = "New Category" %> <%= start_form_tag :action => 'create' %> <%= render_partial "form" %> <hr /> <%= submit_tag "Save" %> <%= end_form_tag %> <%= link_to 'Back', :action => 'list' %> Esto n o s lleva al final d el Dia 2. Tene m o s u n sis te m a fu ncio na n d o p a ra m a n te ner n u es t ra t abla d e Categorias, y he m o s e m p e z a d o a t o m a r con t rol d el có digo scaffold q u e Rails h a genera d o. Página 18
  • 23. Día 3 con Rails Ahora es tiempo de empezar con el corazón de la aplicación. La tabla Items contiene la lista de “cosas para hacer”. Cada item puede pertenecer a una de las categorias creadas en el Dia 2. Un item opcionalmen t e puede tener un Nota, guardad a en una tabla separada, que veremos mañana. Cada tabla tiene una clave primaria ‘id’, que también es usada para guardar links entre las tablas. Categories Items Notes id id id category_id note_id Ilustración 4 : Modelo de datos simplificado La tabla ‘Items’ Definición MySQL de la tabla Los ca m p o s en la t abla Ite m s so n los sig uie n tes: • d o ne – 1 sig nifica q ue el ite m d e la lista ha si d o finali za d o 5 • p rio rity – 1 (Alta p rio ri da d) a 5 (baja p riori da d) • d e scri p tion – texto libre in dican d o cual es la ta rea • d u e_da te – in dica cua n d o se d e be ria reali za r la ta rea • category_id – u n link a la Categoria a la q ue este ite m p e r te nece (‘id’ en la t abla d e Catego rias) • n o te_id – u n link a u n a n o ta o pcio nal ex plican d o es te ite m (‘id’ en la ta bla d e n o t as) • p rivate – 1 sig nifica q ue el ite m d e la lista est a clasifica d o co m o ‘Priva do’ Tabla Items CREATE TABLE items ( id smallint(5) unsigned NOT NULL auto_increment, done tinyint(1) unsigned NOT NULL default '0', priority tinyint(1) unsigned NOT NULL default '3', description varchar(40) NOT NULL default '', due_date date default NULL, category_id smallint(5) unsigned NOT NULL default '0', note_id smallint(5) unsigned default NULL, private tinyint(3) unsigned NOT NULL default '0', created_on timestamp(14) NOT NULL, updated_on timestamp(14) NOT NULL, PRIMARY KEY (id) ) TYPE=MyISAM COMMENT='List of items to be done'; El Modelo Co m o a n tes, Rails p u e de genera r u n arc hivo d e m o d elo vacio: W:ToDo>ruby script/generate model item exists app/models/ exists test/unit/ exists test/fixtures/ 5 MySQL no tiene un tipo ‘booleano’, entonces usamos 0/1 Página 19
  • 24. create app/models/item.rb create test/unit/item_test.rb create test/fixtures/items.yml W:ToDo> q ue p o d e m o s p o blar co n: appmodelsitem.rb class Item < ActiveRecord::Base belongs_to :category validates_associated :category validates_format_of :done_before_type_cast, :with => /[01]/, :message=>"must be 0 or 1" validates_inclusion_of :priority, :in=>1..5, :message=>"must be between 1 (high) and 5 (low)" validates_presence_of :description validates_length_of :description, :maximum=>40 validates_format_of :private_before_type_cast, :with => /[01]/, :message=>"must be 0 or 1" end Validar los links entre las tablas • El uso de belongs_to (pertenece a) y validates_associated (validar asociaciones) enlaza la tabla Items con el campo item_id de la tabla Category. Document ación: ActiveRecord::Associations::ClassMethods Validar la entrada del usuario • validates_presence_of proteje los campos ‘NOT NULL’ contra entradas nulas del usuario • validates_format_of usa expresiones regulares para chequear el formato de la entrada del usuario • cuando un usuario tipea una entrada para un campo numérico, Rails siempre la convertira a un número – si todo falla, un cero. Si desea chequear que el usuario ha realmente tipeado un número, entonces necesita validar la entrada con _before_type_cast, que permite acceder la entrada ‘bruta’ 6 . • validates_inclusion_of chequea la entrada del usuario contra un rango de valores permitidos • validates_length_of previene que el usuario ingrese datos que serian truncados cuando se almacenen 7 . Document ación: ActiveRecord::Validations::ClassMethods La tabla de ‘Notas’ Esta t a bla co n tiene u n solo ca m p o d e t ext o libre p a ra con te ner infor m ación f ut u r a p a ra u n ite m d e la lista d e t a reas en p a r ticular. Este d a t o p o d ria, p o r s u p u es t o, h a ber si d o con te ni d o en u n ca m p o d e la t abla Ite m s, d e t o d a s for m a s, si lo h ace d e es ta for m a a p re n d e ra m u c h o m a s acerca d e Rails : - ) Definición de la tabla MySQL Tabla Notes CREATE TABLE notes ( 6 Lo que pareceria una alternativa mucho mas obvia: validates_inclusion_of :done_before_type_cast, :in=>"0".."1", :message=>"must be between 0 and 1" – falla si el campo de entrada queda en blanco 7 Puede combinar las dos reglas para el campo de Descripción en una sola: validates_length_of :description, :within => 1..40 Página 20
  • 25. id smallint(6) NOT NULL auto_increment, more_notes text NOT NULL, created_on timestamp(14) NOT NULL, updated_on timestamp(14) NOT NULL, PRIMARY KEY (id) ) TYPE=MyISAM COMMENT='Additional optional information for to-dos'; El modelo Genere el archivo de modelos vacio, pero no contiene nada nuevo: appmodelsnote.rb class Note < ActiveRecord::Base validates_presence_of :more_notes end p e r o n ecesita m o s recor d a r agregar este enlace al m o d elo d e Items : appmodelsitem.rb (fragmento) class Item < ActiveRecord::Base belongs_to :note Usar un Modelo para mantener Integridad Referencial El có digo q ue esta m o s a p u n t o d e d e sar r ollar p e r mitira al u s u a rio agregar u n a n o t a a cualq uier Ite m. Pero q u e ocu rre cua n d o u n u s u a rio bo r ra u n Ite m q ue tiene u n n o t a asocia da? Clara me n t e, n ecesita m o s e nco n t ra r u n a for m a d e bo rra r el regist ro d e la Nota t a m bié n, d e o t ra fo r m a n o s q u e d a n regist ro s Notas “huerfa n o s”. En la for m a d e reali za r el t rabajo Modelo / Vista / Con t r ola do r, es te có digo p e r te nece al m o d elo. ¿Porq ué? Bien, p o d r a ver m a s ta r de q u e p o d e m o s bo r ra r regist ro s Ite m s h acien d o click e n u n íco no d e p a p elera d e reciclaje en la p a n talla “lista d e t a reas”, p e r o t a m bié n p o de m o s b o r ra r u n ite m h acien d o click en Purgar ite m s co m pleta d o s. Colocan d o el có digo en el Modelo, sera ejecu ta d o sin te ne r en cue n t a d e d o n d e p rove nga la acción d e eli mi na r. appmodelsitem.rb (fragmento) def before_destroy unless note_id.nil? Note.find(note_id).destroy end end Esto se lee: antes de borrar un registro Item, encontrar el registro en Notas cuyo id sea igual al valor de Nota_id en el registro Item que se esta a punto de eliminar, y eliminarlo primero. A menos que no exista uno :- ) Similarmen te, si un registro es eliminado de la tabla Notas, entonces cualquier referencia a este en la tabla Items necesita ser eliminada: appmodelsnote.rb (fragmento) def before_destroy Item.find_by_note_id(id).update_attribute('note_id',NIL) end end Document ación: ActiveRecord::Callbacks Página 21
  • 26. Mas de Scaffold Generemo s algo mas de código scaffold. Haremos esto para la tabla Items y la tabla Notas. Todavía no estamos listos para trabajar sobre Notas, pero tener en su lugar a scaffold significa que podemo s referirnos hoy al código de las Notas sin generar muchos errores. Es como construir una casa – scaffold permite contruir una pared a la vez sin que todo se derru m be alrededor de sus ojos. W:ToDo>ruby script/generate scaffold Item [snip] W:ToDo>ruby script/generate scaffold Note [snip] W:ToDo> Nota: co m o m o difica m o s la h oja d e estilos ayer, ingrese “n” a la p reg u n t a “overwrite (sobreescribir) p u blic / s tyles heet s / scaffol d.css? [Ynaq]”. Mas acerca de Vistas Crear un Layout para la Aplicación Para a ho ra, se esta volvien d o o bvio d e q u e t o d a s m i s pla n tillas te n d ra n las m i s m a s p ri m era s lineas d e có digo, e n t o nces tiene se n ti do m over el có digo e n co m u n a u n layou t d e la a plicació n. Borre t o d o s los arc hivos appviewslayouts*.rhtml, y ree m placelos p o r u n arc hivo co m ú n application.rhtml. appviewslayoutsapplication.rhtml <html> <head> <title><%= @heading %></title> <%= stylesheet_link_tag 'todo' %> <script language="JavaScript"> <!-- Begin function setFocus() { if (document.forms.length > 0) { var field = document.forms[0]; for (i = 0; i < field.length; i++) { if ((field.elements[i].type == "text") || (field.elements[i].type == "textarea") || (field.elements[i].type.toString().charAt(0) == "s")) { document.forms[0].elements[i].focus(); break; } } } } // End --> </script> </head> <body OnLoad="setFocus()"> <h1><%=@heading %></h1> <% if @flash["notice"] %> <span class="notice"> <%=h @flash["notice"] %> </span> <% end %> <%= @content_for_layout %> </body> </html> El @heading en la plantilla es ahora utilizado para las etiquetas <title> como también para <h1>. He renom bra d o public/stylesheets/scaffold.css a todo.css para mantener una prolijidad, y también he jugado general ment e con los colores, bordes de las tablas, para Página 22
  • 27. dar un estilo mas lindo. También he agregado un poco de Javascript para automáticame n t e posicionar el cursor en el primer campo de entrada en el navegador para que el usuario comienze a tipear. La pantalla ‘Lista de tareas’ Lo q ue est oy inte n t a d o co n seg uir es u n a vista ba sa da e n u n escrit orio Pal mPilot o PDA si milar. El p r o d uct o fi nal es m o s t ra d o en la Ilus t ració n 5: La p a n t alla d e ‘Lista d e Tareas’8 . Algu n o s p u n t o s: • h acien d o click en el e ncabe za d o d e la col u m n a ‘tilde’ (√) eli mi nara t o d o s los ite m s co m pleta d o s. (aq uellos m a rca d o s con u n a til de) • La p a n t alla p u e de ser o r de n a d a hacien d o click e n los encabe z a d o s d e las col u m n a s ‘Pri’, ‘Descri pción’, ‘Finali za r’, y ‘Categoria’ • los valores 0 / 1 p a ra ‘Ter mi na d o’ s o n co nverti d os en p e q u e ñ o s ícon os til des • ite m s q u e p a sa ro n la fecha d e finali zació n (due d a t e) s o n colorea d o s en rojo y m o s t ra d o s e n n egrita • la p re se ncia d e u n a n o t a asociad a es m o s t ra d a co n el ícon o ‘nota’ • los valores 0 / 1 p a ra ‘Priva do’ so n conver ti do s en u n sí m bolo d e can d a d o • ite m s in divid uales p u e de n ser e di ta d o s o eli mi na d o s h acien d o click en los ícono s d e la d e recha d e la p a n t alla • la p a n t alla tiene u n lin do efecto d e ‘franjas’ • n u evos ite m s p ue de n se r agrega d o s h acien d o click en el b o t ó n ‘Nueva Tarea...’ e n la p a r te inferior d e la p a n t alla • h ay u n bo t ó n e nlace a las ‘Categorias’ d el Día 2 Ilustración 5 : La pantalla de ‘Lista de Tareas’ La pla n tilla u tili za d a p a ra o b te ne r est o es la sig uien te: 8 Es asombros o lo que un par de lineas en la hoja de estilos pueden hacer para cambiar la apariencia de la pantalla, por supues to ademas de la colección de íconos... Página 23
  • 28. appviewsitemslist.rhtml <% @heading = "To Do List" %> <%= start_form_tag :action => 'new' %> <table> <tr> <th><%= link_to_image "done", {:action => "purge_completed"}, :confirm => "Are you sure you want to permanently delete all completed To Dos?" %></th> <th><%= link_to_image "priority",{:action => "list_by_priority"}, "alt" => "Sort by Priority" %></th> <th><%= link_to_image "description",{:action => "list_by_description"}, "alt" => "Sort by Description" %></th> <th><%= link_to_image "due_date", {:action => "list"}, "alt" => "Sort by Due Date" %></th> <th><%= link_to_image "category", {:action => "list_by_category"}, "alt" => "Sort by Category" %></th> <th><%= show_image "note" %></th> <th><%= show_image "private" %></th> <th>&nbsp;</th> <th>&nbsp;</th> </tr> <%= render_collection_of_partials "list_stripes", @items %> </table> <hr /> <%= submit_tag "New To Do..." %> <%= submit_tag "Categories...", {:type => 'button', :onClick=>"parent.location='" + url_for( :controller => 'categories', :action => 'list' ) + "'" } %> <%= end_form_tag %> <%= "Page: " + pagination_links(@item_pages, :params => { :action => @params["action"] || "index" }) + "<hr />" if @item_pages.page_count>1 %> Eliminar ‘tareas’ completadas haciendo click en un ícono Imagenes clickeables so n crea da s p o r link_to_image, q ue p o r d efecto es pe ra enco n t rar la i mage n en pub/images con u n a exte n sió n .png; h acien d o click en la i mage n ejecu ta ra u n m é t o d o es pecífico. Agrega n d o el p a rá m e t ro :confirm genera u n a ven ta n a d e dialogo e me rge n te javascri p t co m o a n te s Document ación: ActionView::Helpers::UrlHelper Haciendo click en ‘OK’ ejecuta el método purge_completed. Este nuevo método purge_completed necesita ser definido en el controlado r: appcontrollersitems_controller.rb (fragmento) def purge_completed Item.destroy_all "done = 1" redirect_to :action => 'list' end Item.destroy_all eli mi na t o d o s los regist ro s d e la t abla Items d o n d e el valor d el ca m p o id done es 1, y luego d evuelve la acción list. Document ación: ActiveRecord::Base Cambiar el modo de ordenamiento haciendo click en el Encabezado de la Columna Clickeando en el ícono de Pri invoca el método list_by_priority. Este nuevo método list_by_priority necesita ser defenido en el controlador: appcontrollersitems_controller.rb (fragmento) def list @item_pages, @items = paginate :item, :per_page => 10, :order_by => 'due_date,priority' Página 24
  • 29. end def list_by_priority @item_pages, @items = paginate :item, :per_page => 10, :order_by => 'priority,due_date' render_action 'list' end Especificamos un modo de ordena mien to por defecto en el método list , y creamos un nuevo método list_by_priority 9 . Note también que necesita mo s explicitame n te render_action 'list', por defecto Rails intentará renderizar una plantilla llamada list_by_priority (que no existe :- ) Agregar el Helper Los encabezad o s para las columnas Nota y Privado son imagenes, pero no son clickeables. He decidido escribir un pequeño método show_image(name) para solo most rar la imagen: apphelpersapplication_helper.rb module ApplicationHelper def self.append_features(controller) controller.ancestors.include?(ActionController::Base) ? controller.add_template_helper(self) : super end def show_image(src) img_options = { "src" => src.include?("/") ? src : "/images/#{src}" } img_options["src"] = img_options["src"] + ".png" unless img_options["src"].include?(".") img_options["border"] = "0" tag("img", img_options) end end Una vez que el helper ha sido enlaza do por el controlado r: appcontrollersapplication.rb class ApplicationController < ActionController::Base helper :Application end esta disponible para todas las plantillas en la aplicación Document ación: ActionView::Helpers Usar botónes de navegación Javascript onClick es u n a técnica s ta n d a r d Javascri pt p a ra m a nejar acció nes d e bo tó ne s co m o n avegar a u n a n u eva p ági na. De t o d a s for m a s, Rails reescribe las di reccio nes URLs, e n t o nces n ecesita m o s p reg u n t a rle a Rails p o r la di reccio n URL cor recta a u tili za r. Dad o u n controlador y u n a acción, url_for devolverá la URL. Document ación: ActionController::Base Formatear una Tabla con un Parcial Queria crear un efecto de franjas para la lista de items. Los Parciales (Partial) proveen la solución; pueden ser invocados por el método render_partial: <% for item in @items %> 9 list_by_description y list_by_category son similares y son dejados como un fácil ejercicio para el lector. De todas formas, si queda trabado con list_by_category, vea en la página 39 Página 25
  • 30. <%= render_partial "list_stripes", item %> <% end %> o por el mas económico método render_collection_of_partials: render_collection_of_partials "list_stripes", @items Document ación: ActionView::Partials Rails también pasa un número secuencial list_stripes_counter al Parcial. Esta es la clave para el formato alternad o de las filas en la tabla con o un fondo gris claro o un fondo gris oscuro. Una forma simple para probar si el contador es impar o par: si es impar, usar el gris claro, si es par, usar el gris oscuro. El Parcial completo es como sigue: appviewsitems_list_stripes.rhtml <tr class="<%= list_stripes_counter.modulo(2).nonzero? ? "dk_gray" : "lt_gray" %>"> <td style="text-align: center"><%= list_stripes["done"] == 1 ? show_image("done_ico.gif") : "&nbsp;" %></td> <td style="text-align: center"><%= list_stripes["priority"] %></td> <td><%=h list_stripes["description"] %></td> <% if list_stripes["due_date"].nil? %> <td>&nbsp;</td> <% else %> <%= list_stripes["due_date"] < Date.today ? '<td class="past_due" style="text- align: center">' : '<td style="text-align: center">' %><%= list_stripes["due_date"].strftime("%d/%m/%y") %></td> <% end %> <td><%=h list_stripes.category ? list_stripes.category["category"] : "Unfiled" %></td> <td><%= list_stripes["note_id"].nil? ? "&nbsp;" : show_image("note_ico.gif") %></td> <td><%= list_stripes["private"] == 1 ? show_image("private_ico.gif") : "&nbsp;" %></td> <td><%= link_to_image("edit", { :controller => 'items', :action => "edit", :id => list_stripes.id }) %></td> <td><%= link_to_image("delete", { :controller => 'items', :action => "destroy", :id => list_stripes.id }, :confirm => "Are you sure you want to delete this item?") %></td> </tr> Un poco de Ruby es usado para probar si el contador es impar o par y renderizar o class=“dk_gray” o class=“lt_gray”: list_stripes_counter.modulo(2).nonzero? ? "dk_gray" : "lt_gray" el código hasta el signo de iterrogación pregunta: es el resto cuando se divide list_stripes_counter por 2 es diferente a cero? Ruby Document ación: class Numeric El resto de la linea es en realidad una criptica expresión if then else que sacrifica ser legible por ser breve: if la expresión antes de la marca de pregunta es verdadera, devuelve el valor antes de los dos puntos; sino devuelve el valor después de los dos puntos. Ruby Document ación: Expressions Las dos etiquetas dk_gray y lt_gray son definidas en la hoja de estilos: publicstylesheetsToDo.css (fragmento) .lt_gray { background-color: #e7e7e7; } .dk_gray { background-color: #d6d7d6; } Nota: el mismo constructor if then else es usado para mostrar el ícono ‘tilde’ si Página 26
  • 31. list_stripes["done"]es igual a 1, de otra forma muestra un caracter de espacio en blanco HTML: list_stripes["done"] == 1 ? show_image("done_ico") : "&nbsp;" Formato basado en el valor de los Datos Ta m bién es fácil resalta r ite m s es pecíficos d e d a t o s – p o r eje m plo, fecha s en el p a sa d o. list_stripes["due_date"] < Date.today ? '<td class="past_due">' : '<td>' De n uevo, est o n ecesita se r igual a la e n t ra d a .past_due en la h oja d e estilos. Manejar valores perdidos en una busqueda Quere m o s q ue el sis te m a p ue d a cub ri rse e n la sit uació n d o n d e el u s u a rio bo rra u n a Categoria q u e est a sie n d o u s a d a p o r u n ite m en la Lista d e Tareas. En este caso, la Categoria d e be ria ser m o s t ra d a co m o ‘sin arc hivar’: list_stripes.category ? list_stripes.category["category"] : 'Unfiled' OK si h a llega d o h a s ta a q ui, d e beria te ner u n a p a n t alla ‘Lista d e Tareas’ q ue se vea algo co m o la Ilust ración 5 La p a n talla de ‘Lista de T areas’ en la p ágina 2 3 . La pantalla ‘Nueva Tarea’ Ahora sig ue q u e p a sa cua n d o u n o p re sio na el b ot ó n d e ‘Nueva Tarea...’. De n u evo, t o davía q ue da n algu n o s t r uco s en el có digo. Ilustración 6 Pantalla Tarea Nueva La pla n tilla es m í ni m a: appviewsitemsnew.rhtml <% @heading = "New To Do" %> <%= error_messages_for 'item' %> <%= start_form_tag :action => 'create' %> <table> <%= render_partial "form" %> </table> <hr /> <%= submit_tag "Save" %> <%= submit_tag "Cancel", {:type => 'button', :onClick=>"parent.location='" + url_for( :action => 'list' ) + "'" } %> <%= end_form_tag %> Página 27
  • 32. y el t rabajo real es reali za d o en el p a rcial, q u e p u e d e ser co m p a r ti d o con la acción ‘Edit’: appviewsitems_form.rhtml <tr> <td><b>Descripción: </b></td> <td><%= text_field "item", "description", "size" => 40, "maxlength" => 40 %></td> </tr> <tr> <td><b>Finalizar: </b></td> <td><%= date_select "item", "due_date", :use_month_numbers => true %></td> </tr> <tr> <td><b>Categoria: </b></td> <td><select id="item_category_id" name="item[category_id]"> <%= options_from_collection_for_select @categories, "id", "category", @item.category_id %> </select> </td> </tr> <tr> <td><b>Prioridad: </b></td> <% @item.priority = 3 %> <td><%= select "item","priority",[1,2,3,4,5] %></td> </tr> <tr> <td><b>Privado? </b></td> <td><%= check_box "item","private" %></td> </tr> <tr> <td><b>Completado? </b></td> <td><%= check_box "item", "done" %></td> </tr> Crear una lista desplegable para el campo fecha d a t e_select ge nera u n r u di m e n ta rio m e n u d e s plegable p a ra ingresa r la fecha: date_select "item", "due_date", :use_month_numbers => true Document ación: ActionView::Helpers::DateHelper Atrapar excepciones con Ruby Desafor t u n a d a m e n te, date_select feli z m e n te ace p ta fechas co m o 3 1 d e Febrero. Rails m u e re cua n d o inte n t a g uar d a r es ta fecha en la base d e d a t o s. Una for m a d e evitar est o es at ra pa r este inte n t o d e g uar da r fallido u sa n d o rescue, u n m é t o d o d e m a n eja r excepcio ne s d e Ruby appcontrollersitems_controller.rb (fragmento) def create begin @item = Item.new(@params[:item]) if @item.save flash['notice'] = 'Tarea creada exitosamente.' redirect_to :action => 'list_by_priority' else @categories = Category.find_all render_action 'new' end rescue flash['notice'] = 'La tarea no se pudo grabar.' redirect_to :action => 'new' end end Ruby Document ación: Exceptions, Catch, and Throw Página 28
  • 33. Crear una lista desplegable desde una tabla de busqueda Este es ot ro eje m plo d e Rails resolvien d o u n p r o ble m a d e co dificación diario d e u n a fo r m a ext re m a d a m e n te econ ó mica. En es te eje m plo: options_from_collection_for_select @categories, "id", "category", @item.category_id options_from_collection_for_select lee t o d o s los regist ro s e n las categorias y los re n de ri za co m o <option value=”[value of id]”>[value of category]</option>. El regist ro q ue es igual a @item_category_id sera etiq uet a d o co m o ‘ selecciona d o’. Si es t o n o fuera s uficien te, el có digo incluso u tili za esca pe s h t ml p a ra los d a t o s. Habil. Document ación: ActionView::Helpers::FormOptionsHelper Note q u e las cajas d e s plegables d e be n t raer los d a t o s d e algu n lugar – q ue sig nifica u n agrega d o al con t r ola do r: appcontrollersitems_controller.rb (fragmento) def new @categories = Category.find_all @item = Item.new end def edit @categories = Category.find_all @item = Item.find(@params[:id]) end Crear una lista desplegable para la lista de constantes Esta es u n a versión m a s si m ple d el caso a n te rior. Agregar u n a lista d e valores a u n a caja d e selección en el có digo n o es sie m p re u n a b ue n a idea – es m a s fácil ca m biar los d a t o s e n la t a bla q ue e ditar los valores en el có digo. De t o d a s for m a s, h ay casos d o n d e es u n a a p r oxi m ació n p e rfecta m e n te vali da, e n t o nces en Rails h aga: select "item","priority",[1,2,3,4,5] Note t a m bién co m o in dicar u n a valor p o r d efecto en la linea d e có digo a n te rior. Document ación: ActionView::Helpers::FormOptionsHelper Crear una casilla de verificación Ot ro re q ue ri mie n t o reg ular; o t r o hel per en Rails: check_box "item","private" Document ación: ActionView::Helpers::FormHelper Toques finales Modificar la hoja de estilos Hast a es te p u n t o, la p a n t alla d e ‘Lista d e Tareas’ d e be ria f u ncio na r, y t a m bién d e beria fu ncio nar el b o t ó n ‘New To Do’. Para p r o d ucir las p a n t allas m o s t ra d a s aq ui, t a m bié n hice los sig uien te s ca m bios a la h oja d e es tilos: publicstylesheetsToDo.css body { background-color: #c6c3c6; color: #333; } .notice { color: red; background-color: white; } Página 29
  • 34. h1 { font-family: verdana, arial, helvetica, sans-serif; font-size: 14pt; font-weight: bold; } table { background-color:#e7e7e7; border: outset 1px; border-collapse: separate; border-spacing: 1px; } td { border: inset 1px; } .notice { color: red; background-color: white; } .lt_gray { background-color: #e7e7e7; } .dk_gray { background-color: #d6d7d6; } .hightlight_gray { background-color: #4a9284; } .past_due { color: red } La pantalla ‘Editar Tarea’ El re s to d el Dia 3 es la con t r ucció n d e la p a n t alla ‘Editar Tarea’, q u e es m uy si milar a ‘Nueva Tarea’. Estaba acos t u m b ra d o a m olest ar m e cua n d o los texto s d e sec u n d a ria d ecian: esto q ueda co mo u n ejercicio f ácil p ara el lector, a ho ra es genial p o d er h acer lo m i s m o con u s t e de s 1 0 . Esto n o s lleva al final d el Dia 3 – y a h o ra la a plicació n n o se ve p a ra n a d a co m o u n scaffol d d e Rails, p e ro bajo la s u p e rficie, t o davía u tiliza m o s u n gra n ra ngo d e h e r ra mie n t a s d e Rails p a ra h acer el d e sa r rollo m a s fácil. 10 Pero no como los autores de los textos de secundaria, yo si muestro la respues t a en el Dia 4 :- ) - vea app views ite m s e dit.rht ml en la página 31 Página 30
  • 35. Dia 4 con Rails Las pantallas ‘Notas’ Enlazando ‘Notas’ con ‘Editar Tarea’ Aunque el código scaffold de las Notas le da todas las fácilidades, no quere mos que el usuario invoque cualquiera de estas directa me n t e. En cambio, si un item no tiene asociada una nota, queremo s poder crear una nota haciendo click en el ícono de Nota en la pantalla de Edicion de tareas: Ilustración 7 : Crear una nota nueva desde la pantalla ‘Editar Tarea’ Si ya existe una nota, queremo s poder editarla o borrarla haciendo click en el ícono apropiado en la pantalla de Edicion de tareas: Ilustración 8 : Editar o borrar una nota existente Pri me ro q u e n a d a, vea m o s el có digo d e la p a n t alla ‘Editar Tarea’. Note co m o los bo t ó ne s d e Notas ca m bian d e acuer d o a si la Nota existe o n o, y co m o el con t r ol es t ra n sferi do al con t r ola d o r d e Notas: appviewsitemsedit.rhtml <% @heading = "Edit To Do" %> <%= error_messages_for 'item' %> <%= start_form_tag :action => 'update', :id => @item %> <table> Página 31
  • 36. <%= render_partial "form" %> <tr> <td><b>Notes: </b></td> <% if @item.note_id.nil? %> <td>None</td> <td><%= link_to_image "note", :controller => "notes", :action => "new", :id => @item.id %></td> <% else %> <td><%=h @item.note.more_notes %></td> <td><%= link_to_image "edit_button", :controller => "notes", :action => "edit", :id => @item.note_id %></td> <td><%= link_to_image "delete_button", {:controller => "notes", :action => "destroy", :id => @item.note_id }, :confirm => "Are you sure you want to delete this note?" %></td> <% end %> </tr> </table> <hr /> <%= submit_tag "Save" %> <%= submit_tag "Cancel", {:type => 'button', :onClick=>"parent.location='" + url_for( :action => 'list' ) + "'" } %> <%= end_form_tag %> La pantalla ‘Editar Notas’ Editar una nota existente es muy simple. Esta es la plantilla: appviewsnotesedit.rhtml <% @heading = "Edit Note" %> <%= start_form_tag :action => 'update', :id => @note %> <%= render_partial "form" %> <%= submit_tag "Save" %> <%= submit_tag "Cancel", {:type => 'button', :onClick=>"parent.location='" + url_for( :controller => 'items', :action => 'list' ) + "'" } %> <%= end_form_tag %> y el parcial: appviewsnotes_form.rhtml <table> <tr> <td><label for="note_more_notes">More notes</label></td> <td><%= text_area 'note', 'more_notes' %></td> </tr> </table> Una vez que la acción update o destroy de la tabla Notas es completada, queremos regresar a la pantalla de ‘Lista de Tareas’: appcontrollersnotes_controller.rb (fragmento) def update @note = Note.find(@params[:id]) if @note.update_attributes(@params[:note]) flash['notice'] = 'Note was successfully updated.' redirect_to :controller => 'items', :action => 'list' else render_action 'edit' end end def destroy Note.find(@params[:id]).destroy redirect_to :controller => 'items', :action => 'list' end Recuer de las reglas d e integ ri da d refere ncial q ue ya h a n si d o crea da s se asegu rara n d e Página 32
  • 37. q ue cua n d o u n a n o t a es eli mina da, cualq uier refere ncia a ella sera re m ovida d el Ite m t a m bié n (vea Integridad Refere ncial en la p ágina 2 1 ). La pantalla de ‘Nota Nueva’ Crear es u n p oco m a s difícil. Quere m o s h acer lo siguien te: • guar d a r u n a n ueva n o ta e n la t abla d e Notas • e nco n t ra r el id d e u n n u evo regist ro crea d o en la ta bla d e Notas • regist ra r es te id en el ca m p o n o tes_id d el regist ro asocia do en la t abla d e Ite m s Las variables d e Sesió n n o s p r oveen u n a for m a ú til d e m a n t e ne r d a t o s e n t re p a n t allas – p o d e m o s u tili za rlas a q ui p a ra g ua r d a r el Id d el regist ro en la t abla d e Notas. Document ación: ActionController::Base Guardar y traer Datos usando variables de Sesión Primero que nada, cuando creamos un nuevo registro de Nota, pasamo s el id del Item que estamo s editando: appviewsitemsedit.rhtml (fragmento) <td><%= link_to_image "note", :controller => "notes", :action => "new", :id => @item.id %></td> El método new en el controlador Notes guarda esto en una variable de sesión : appcontrollersnotes_controller.rb (fragmento) def new @session[:item_id] = @params[:id] @note = Note.new end La plantilla ‘Notas Nuevas’ no tienen sorpresas: appviewsnotesnew.rhtml <% @heading = "New Note" %> <%= start_form_tag :action => 'create' %> <%= render_partial "form" %> <%= submit_tag "Save" %> <%= submit_tag "Cancel", {:type => 'button', :onClick=>"parent.location='" + url_for( :controller => 'items', :action => 'list' ) + "'" } %> <%= end_form_tag %> El método create trae los datos de la variable de sesión de nuevo y lo usa para encontrar el registro en la tabla de Items. Luego actualiza el campo note_id en la tabla Item con el id del registro que se acaba de crear en la tabla de Notas, y retorna al controlador Items de nuevo: appcontrollersnotes_controller.rb (fragmento) def create @note = Note.new(@params[:note]) if @note.save flash['notice'] = 'Note was successfully created.' @item = Item.find(@session[:item_id]) @item.update_attribute(:note_id, @note.id) redirect_to :controller => 'items', :action => 'list' else render_action 'new' end end Página 33
  • 38. Cambiar la pantalla de ‘Categorias’ No hay demasiado por hacer en el sistema ahora, a parte de acomo da r las plantillas creadas en los dias anteriores para que tengan el mismo estilo que los botónes de navegación: appviewscategorieslist.rhtml <% @heading = "Categories" %> <form action="/categories/new" method="post"> <table> <tr> <th>Category</th> <th>Created</th> <th>Updated</th> </tr> <% for category in @categories %> <tr> <td><%=h category["category"] %></td> <td><%= category["created_on"].strftime("%I:%M %p %d-%b-%y") %></td> <td><%= category["updated_on"].strftime("%I:%M %p %d-%b-%y") %></td> <td><%= link_to_image 'edit', { :action => 'edit', :id => category.id } %></td> <td><%= link_to_image 'delete', { :action => 'destroy', :id => category.id }, :confirm => 'Are you sure you want to delete this category?' %></td> </tr> <% end %> </table> <hr /> <input type="submit" value="New Category..." /> <input type="button" value="To Dos" onClick="parent.location='<%= url_for( :controller => 'items', :action => 'list' ) %>'"> </form> appviewscategoriesnew.rhtml <% @heading = "Add new Category" %> <%= error_messages_for 'category' %> <%= start_form_tag :action => 'create' %> <%= render_partial "form" %> <hr /> <input type="submit" value="Save" /> <input type="button" value="Cancel" onClick="parent.location='<%= url_for( :action => 'list' ) %>'"> <%= end_form_tag %> appviewscategoriesedit.rhtml <% @heading = "Rename Category" %> <%= error_messages_for 'category' %> <%= start_form_tag :action => 'update', :id => @category %> <%= render_partial "form" %> <hr /> <input type="submit" value="Update" /> <input type="button" value="Cancel" onClick="parent.location='<%= url_for( :action => 'list' ) %>'"> <%= end_form_tag %> Navegación a traves del sistema Los ca mi no s finales d e n avegación a t raves d el sis te m a so n m o s t r a d o s a con tin uació n. Cualq uier có digo scaffol d re d u n d a n te – eje m plo los arc hivos show.rhtml – p u e n d e ser si m ple m e n t e eli mi na d o s. Esa es la belle za d el có digo scaffol d – n o le cos to ni ng u n esf ue r z o crear el có digo e n p ri me r lugar, y u na ve z q u e sirvio s u p r o p o si to, di recta m e n te lo p u e d e eli mi nar. Página 34
  • 39. Nueva Tarea Nueva Categoria Lista Tareas Nueva Nota Lista Categorias Editar Editar Not a Tarea Editar Categoria Ilustración 9 Caminos de navegación a traves de la aplicación Colocar una página de inicio para la Aplicación Co m o p a so final, necesita m o s eli mi na r la p a n t alla p o r d efecto 'Bienveni do a Rails' si el u s ua rio ingresa e n s u n avega d o r http://todo. Hay d o s p a so s: • Agregar u n a p ági na d e inicio al arc hivo Routes: configroutes.rb (fragmento) map.connect '', :controller => 'items' • re n o m b ra r publicindex.html publicindex.html.orig Descargar una copia de esta aplicación Si q uiere u n a co pia d e la a plicación ‘Lista d e Tareas’ p a ra j ugar, h ay u n enlace en h t t p: / / r ails.ho melin ux.org. Necesita • u sa r Rails p a ra ar m a r la es t r uct u ra d e directo rios (vea Rails en la p ágina 3 ) • d e scarga r el archivo todo_app.zip en el n uevo di recto rio crea d o ToDo • d e sco m p ri mi r los arc hivos unzip -o todo_app.zip • re n o m b ra r publicindex.html publicindex.html.orig • si d e sea u sa r la ba se d e d a t o s d e eje m plo, mysql -uroot -p < db/ToDo.sql Y finalmente Espero q ue e nc ue n t re es te d oc u m e n t o ú til – sie m p re m e p o n e co n te n t o recibir co me n t arios, b ue n o s o m alos, a j p mcc@users.so u rceforge.ne t. Co me n ta rios d e la versió n en es pa ñ ol a e m m a n u eln _at_ g m ail.co m Feliz d e sa r rollo con Rails! Página 35
  • 40.
  • 41. Apéndice – Cambios posteriores Des p ues d e escribir ‘Cuat ro Dias’, recibi m u c h o s co me n t a rio s q ue ay u d a ro n a m ej ora r la calida d d el d oc u m e n t o. Una p reg u n t a a pa recio re pe tí da me n te - “co m o act uali zo m a s d e u n regist ro d e s de la m i s m a p a n t alla” - en to nces a q ui h ay a pé n dice cub rien d o esta s Pregu n t a s Frecue n te s. No es el conce p t o m a s fácil d e d o mi na r, y es u n area q u e es pe ra ria q ue a pa re zca n m a s “ayu da n te s” (hel per s) e n el f ut u r o. Actualizaciones Multiples En la captura de pantalla de abajo, el usuario puede tildar / d e s tildar varias “Tareas” usando las cajas de verificación en la columna de la izquierda, y luego presionar “Guardar” para guardar los resultados en la base de datos. Ilustración 10 : Actualizaciones multiples View Rails soporta actualizaciones multiples con otra convención de nombres, que es agregar el id del registro que se esta editan do al nombre entre corchetes [ ]. Esto permite seleccionar un registro en particular desde multiples registros en la pantalla. Trabajemos hacia atras desde el HTML que estamos generan do. Esto es lo que se ve para el registro con id = 6: <td style="text-align: center"> <input type="checkbox" id="item_done" name="item[6][done]" value="1" checked /> <input name="item[6][done]" type="hidden" value="0" /> </td> (“checked” (seleccionado) es omitido si la casilla de verificación no esta chequeada) Una forma de generar este código es: appviewitems_list_stripes.rhtm (fragmento) <td style="text-align: center"> <%=check_box_tag("item["+list_stripes.id.to_s+"][done]","1",list_stripes["done"]==1) %> Página 37
  • 42. <%=hidden_field_tag("item["+list_stripes.id.to_s+"][done]","0") %> </td> Los p a rá m e t r o s p a ra check_box_tag so n name, value = "1", checked = false, options = {}; p a ra hidden_field_tag name, value = nil, options = {} Document ación: ActionView::Helpers::FormTagHelper Ade m a s necesita m o s u n bo tó n Guar d a r (Save): appviewsitemslist.rhtml (fragmento) <% @heading = "To Do List" %> <%= start_form_tag :action => 'updater' %> <table> ... </table> <hr /> <%= submit_tag "Save" %> <%= submit_tag "New To Do...", {:type => 'button', :onClick=>"parent.location='" + url_for( :controller => 'items', :action => 'new' ) + "'" } %> <%= submit_tag "Categories...", {:type => 'button', :onClick=>"parent.location='" + url_for( :controller => 'categories', :action => 'list' ) + "'" } %> <%= end_form_tag %> <%= "Page: " + págination_links(@item_pages, :params => { :action => @params["action"] || "index" }) + "<hr />" if @item_pages.page_count>1 %> Controlador Lo q ue re t o r na d el co nt rola d o r cua n d o se p re sio na el b o t ó n “Guar d ar” es el siguien te h a s h: params: { :controller=>"items", :item=> { "6"=>{"done"=>"0"}, ... etc... "5"=>{"done"=>"1"} }, :action=>"updater" } Esta m o s interesa d o s en la p a r t e d e :item. Por eje m plo, la linea e n negrita significa “el regist ro co n el id = 6 tiene el valor d el ca m p o done en 0”. Des de aq ui, es u n t rabajo ba s ta n te si m ple el d e act uali za r la t abla d e Items: appcontrolleritems_controller (fragmento) def updater @params[:item].each { |item_id, attr| item = Item.find(item_id) item.update_attribute(:done,attr[:done]) } redirect_to :action => 'list' end each coloca “6” e n la variable item_id, y “do ne” = > “0” e n attr. Ruby Document ación: class Array Este có digo f u ncio na, p e ro si ve q ue es ta p a sa n d o en development.log, vera q ue Rails esta t rayen d o y act uali za n d o ca da regist ro, sea m o difica do o n o. No solo est o est a crean d o act u ali zacio nes in necesa rias en la ba se d e d a t o s, p e r o t a m bié n sig nifica q ue updated_on t a m bié n esta n sien d o m o dificad o, q ue n o es en realida d lo q ue d e sea m o s. Mucho m ej o r Página 38