restful rails es

Upload: luis-gonzalez

Post on 10-Feb-2018

224 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/22/2019 Restful Rails Es

    1/41

    Desarrollo REST con Rails

    Ralf Wirdemann Thomas Baustert

    [email protected] [email protected]

    traduccion de Juan [email protected]

    17 de junio de 2007

  • 7/22/2019 Restful Rails Es

    2/41

    2

    ListingListado

  • 7/22/2019 Restful Rails Es

    3/41

    Agradecimientos

    Damos las gracias a Astrid Ritscher por las revisiones que hizo dela primera version de este documento y a Adam Groves de Berlnpor la revision final de la version en ingles de este documento.

    LicenciaEste trabajo se distribuye bajo la licencia Creative CommonsReconocimiento-SinObraDerivada 2.0 Espana. Para ver una copiade esta licencia visite http://creativecommons.org/licenses/by-nd/2.0/es/ o enve una carta a Creative Commons, 543 HowardStreet, 5th Floor, San Francisco, California, 94105, USA.

    Ralf Wirdemann, Hamburgo en Febrero de 2007

  • 7/22/2019 Restful Rails Es

    4/41

    ii

  • 7/22/2019 Restful Rails Es

    5/41

    Indice general

    1. Rails y REST 1

    1.1. Que es REST? . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.2. Por que usar REST? . . . . . . . . . . . . . . . . . . . . . . . 31.3. Y que hay de nuevo? . . . . . . . . . . . . . . . . . . . . . . . 31.4. Preparativos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

    1.4.1. Rails 1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.5. Andamiaje del Recurso . . . . . . . . . . . . . . . . . . . . . . . 41.6. El modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.7. El controlador . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

    1.7.1. URLs REST . . . . . . . . . . . . . . . . . . . . . . . . 71.7.2. Las acciones REST utilizan respond to . . . . . . . . . . 81.7.3. Campo Accept de la cabecera HTTP . . . . . . . . . . . 9

    1.7.4. Especificacion del formato por la URL de la peticion . . 101.8. URLs y vistas REST . . . . . . . . . . . . . . . . . . . . . . . . 111.8.1. New y Edit . . . . . . . . . . . . . . . . . . . . . . . . . 131.8.2. Metodos de Path en los formularios: Create y Update . 131.8.3. Destroy . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

    1.9. Metodos de URL en el controlador . . . . . . . . . . . . . . . . 151.10. Rutas REST . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

    1.10.1. Convenciones . . . . . . . . . . . . . . . . . . . . . . . . 161.10.2. Ajustes . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

    1.11. Recursos anidados . . . . . . . . . . . . . . . . . . . . . . . . . 181.11.1. Adaptacion de los controladores . . . . . . . . . . . . . 20

    1.11.2. Nuevos parametros en los helpers de path y URL . . . . 201.11.3. Creando nuevas iteraciones . . . . . . . . . . . . . . . . 231.11.4. Edicion de las iteraciones . . . . . . . . . . . . . . . . . 25

    1.12. Definicion de otras acciones . . . . . . . . . . . . . . . . . . . . 261.12.1. Seguro que no nos repetimos? . . . . . . . . . . . . . . 29

    1.13. Definicion de nuestros propios formatos . . . . . . . . . . . . . 291.14. REST y AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . 301.15. Pruebas del codigo . . . . . . . . . . . . . . . . . . . . . . . . . 311.16. Clientes REST: ActiveResource . . . . . . . . . . . . . . . . . . 321.17. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

    Bibliografa 35

    iii

  • 7/22/2019 Restful Rails Es

    6/41

    iv INDICE GENERAL

  • 7/22/2019 Restful Rails Es

    7/41

    Captulo 1

    Rails y REST

    Es un hecho olvidado por muchos desarrolladores web de hoy que el proto-colo HTTP puede hacer algo mas que GETs y POSTs. Sin embargo, esto noresulta tan sorprendente si consideramos que los navegadores tan solo sopor-tan esas dos peticiones. GET y POST son los tipos de peticiones HTTP que sesuelen transmitir del cliente a servidor, pero el protocolo HTTP tambien defi-ne los metodos PUT y DELETE que, en teora, se deberan usar para crear oborrar un recurso en la web. En este tutorial ampliaremos nuestros horizontesy profundizaremos en los metodos PUT y DELETE.

    Recientemente se ha hecho popular el termino REST, que combina PUT yDELETE junto con GET y POST. Una de las nuevas caractersticas de Rails1.2 es que soporta REST.

    El tutorial comienza con una breve introduccion de los conceptos y elambito de REST. A continuacion se explicaran las razones que justifican eldesarrollo de aplicaciones REST con Rails: usando andamiajes, mostraremosel desarrollo detallado de un controlador REST nos mostrara las herramientastecnicas que nos ayudaran en el desarrollo REST. Con esta base tecnica enmente el siguiente captulo mostrara la funcionalidad general y las modificacio-

    nes en las rutas de las cuales depende en gran medida la funcionalidad REST.El captulo Recursos anidados presenta al lector como se pueden anidar losrecursos en una relacion de parentesco sin violar los conceptos de las URLsREST. Por ultimo, el tutorial termina con captulos sobre REST y AJAX, laautomatizacion de pruebas de aplicacion REST y una breve introduccion aActiveResource, la parte de cliente de REST.

    Antes de empezar, conviene aclarar que este tutorial asume que el lectortiene al menos un conocimiento basico del desarrollo con Rails. Si no es esteel caso es mejor visitar alguno de los muchos tutoriales de Rails disponiblesen la Red. (e.g., [3], [4], [5]) o leer algunos de los muchos libros en la materia

    que, por el momento, solo se encuentran en ingles (p.e. [1] y [2]).

    1

  • 7/22/2019 Restful Rails Es

    8/41

    2 CAPITULO 1. RAILS Y REST

    1.1. Que es REST?

    El termino REST aparecio por primera vez en la tesis doctoral de RoyFielding [6] y significa Representational State Transfer1. REST describe todoun paradigma de arquitectura para aplicaciones que solicitan y manipulanrecursos en la web utilizando los metodos estandar de HTTP: GET, POST,PUT y DELETE.

    En REST todo recurso es una entidad direccionable mediante una URLunica con la que se puede interactuar a traves del protocolo HTTP. Dichosrecursos pueden representarse en diversos formatos como HTML, XML o RSS,segun lo solicite el cliente. Al contrario que en las aplicaciones Rails tradicio-nales 2, la URL de un recurso no hace referencia a un modelo y su acci on

    correspondiente; tan solo hace referencia al propio recurso.

    Web

    Wunderloop

    Webcert

    Bellybutton

    http://ontrack.b-simple.de/projects/1

    http://ontrack.b-simple/projects/2

    http://ontrack.b-simple.de/projects/3

    Figura 1.1: Recursos en la web y sus URLs

    Los tres recursos de la figura 1.1 estan representados por URLs casi identi-

    cas seguidas por el identificador del recurso. Observese que la URL no muestraque se desea hacer con el recurso.

    Un recurso, en el contexto de una aplicacion Rails, es una combinacion deun controlador dedicado y un modelo. As, desde un punto de vista tecnico,los recursos proyecto de la figura 1.1 son instancias de la clase ActiveRecordProject combinadas con un controlador ProjectsController que es reponsablede manipular dichas instancias.

    1Transferencia de estado representacional2Cuando queramos hacer una distincion entre aplicaciones Rails basadas o no en REST

    utilizaremos la palabra tradicional. Tradicional en este caso no quiere decir obsoleta o in-correcta, simplemente se utiliza para hacer referencia a un concepto no de REST. De esta

    manera debera ser mas facil explicar esta nueva tecnologa.

  • 7/22/2019 Restful Rails Es

    9/41

    1.2. POR QUE USAR REST? 3

    1.2. Por que usar REST?

    Esta es una cuestion interesante, si tenemos en cuenta que se vienen desa-rrollando con exito aplicaciones Rails desde hace dos anos utilizando el pa-radigma MVC. A continuacion mostramos una lista de caractersticas de lasaplicaciones REST, que servira para mostrar las mejoras conceptuales quepueden hacerse en Rails.

    URLs limpias. En REST las URLs representan recursos y no acciones,por lo tanto siempre tienen el mismo formato: primero aparece el controlador yluego el identificador de recurso. La manipulacion requerida es independientede la URL y se expresa con la ayuda de los verbos HTTP.

    Formatos de respuesta variados. Los controladores REST estan escri-

    tos de manera que las acciones pueden devolver sus resultados facilmente endiferentes formatos de respuesta. Una misma accion puede entregar HTML,XML, RSS o cualquier otro formato de datos segun los requisitos de la apli-cacion cliente de manera simple y sencilla.

    Menos codigo. El desarrollar acciones unicas capaces de soportar multi-ples clientes distintos evita repeticiones en el sentido DRY3 y da como resul-tado que los controladores tengan menos codigo.

    Controladores orientados a CRUD. Los controladores y los recursosse funden en una unica cosa - cada controlador tiene como responsabilidadmanipular un unico tipo de recurso.

    Diseno limpio de la aplicacion. El desarrollo REST produce un diseno

    de aplicacion conceptualmente claro y mas facil de mantener.En los proximos captulos de este tutorial veremos las caractersticas an-

    teriores con la ayuda de varios ejemplos.

    1.3. Y que hay de nuevo?

    Aunque podra parecer que el diseno de aplicaciones basado en REST haceinutil toda la experiencia que hayamos atesorado en el desarrollo con Railspodemos asegurar que no es el caso: REST sigue estando basado en MVC ydesde un punto de vista tecnico se puede resumir en las siguientes tecnicasnuevas:

    El uso de respond to en el codigo del controlador.

    Nuevos metodos helper para enlaces y formularios.

    El uso de metodos de URL en las redirecciones desde el controlador.

    Nuevas rutas, generadas por el metodo resources en routes.rb.

    Una vez que entendamos y comencemos a usar estas tecnicas el diseno deaplicaciones REST se convertira en algo natural.

    3

    Dont repeat yourself

  • 7/22/2019 Restful Rails Es

    10/41

    4 CAPITULO 1. RAILS Y REST

    1.4. Preparativos

    A continuacion explicaremos las nuevas funcionalidades especficas de RESTque incorpora Rails en el contexto de la aplicacion de ejemplo de nuestro libroRapid Web Development mit Ruby on Rails [1], Ontrack, una aplicacion degestion de proyectos. Por supuesto no vamos a desarrollar aqu toda la aplica-cion sino que utilizaremos la misma terminologa para crear un entorno tecnicosobre el que mostrar los conceptos REST.

    Empezaremos generando nuestro proyecto Rails:

    > r a il s o n tr a ck

    A continuacion crearemos las bases de datos de test y desarrollo:

    > m ys ql - u r ai ls - p

    E n te r p a ss w or d : * * ** *

    my sq l > create database on tr ac k_d ev el op men t ;

    my sq l > create database ontr ack_ test ;

    my sq l > qu it

    1.4.1. Rails 1.2

    Asumiremos que no todos nuestros lectores querran realizar una instala-cion de Rails 1.2 a nivel de sistema, dado que entonces todas sus aplicacionesutilizaran Rails 1.2 En su lugar vamos a instalar Rails 1.2 directamente sobrenuestro proyecto de manera que solo nuestra aplicacion de ejemplo ontrackutilizara esta nueva version. La etiqueta de la ultima version estable de Rails1.2 segun la documentacion es rel 1-2-2. El siguiente comando rake instala lanueva version solo en nuestro proyecto:

    > c d o nt ra ck

    > r a k e r a i l s : f r e ez e : e d g e T A G = r e l_ 1 - 2 - 2

    En la pagina principal de Rails http://www.rubyonrails.orgpueden encon-trarse otros metodos alternativos de instalacion, as como informacion acercade las nuevas versiones que puedan aparecer.

    1.5. Andamiaje del Recurso

    Empezaremos por crear el recurso Project con el nuevo generador scaf-fold resource. Este generador toma un nombre de recurso (en nuestro caso

    project) como primer parametro y, opcionalmente, una lista de atributos delmodelo y sus tipos. Estos atributos se usaran para la generacion de un scriptde migracion de la base datos y para definir los campos apropiados en las

    vistas generadas:

  • 7/22/2019 Restful Rails Es

    11/41

    1.6. EL MODELO 5

    > c d o nt ra ck

    > r u by s c ri p t / g en e ra t e s c a ff o l d_ r e so u r ce p r oj e ct \

    > name :string desc :text

    e xi st s a pp / m od el s /

    e x is t s a pp / c o n t ro l le r s /

    e x is t s a pp / h e l pe r s /

    c r ea t e a pp / v i e ws / p r o je c ts

    e x is t s t es t / f u n ct i o na l /

    e xi st s t es t / un it /

    c r ea t e a pp / v i e ws / p r o je c ts / i n d ex . r h t ml

    c r ea t e a pp / v i e ws / p r o je c ts / s h o w . r ht m l

    c r ea t e a pp / v i e ws / p r o je c ts / n e w . r ht m l

    c r ea t e a pp / v i e ws / p r o je c ts / e d i t . r ht m l

    c r ea t e a pp / v i e ws / l a y ou t s / p r oj e ct s . r h tm l

    c r ea t e p u bl i c / s t yl e sh e e ts / s c a f fo l d . c ssc r ea t e a pp / m o d el s / p r o je c t . rb

    c r e a te a p p / c o n t r o l le r s / p r o j e c t s _ c o n t r o l l er . r b

    c r e a te t e s t / f u n c t io n a l / p r o j e c t s _ c o n t r o l l e r_ t e s t . r b

    c r ea t e a pp / h e l pe r s / p r oj e c ts _ h el p e r . rb

    c r ea t e t es t / u ni t / p r o je c t_ t e st . r b

    c r ea t e t es t / f i xt u re s / p r o je c ts . y m l

    c r ea t e d b / m ig r at e

    c r ea t e d b / m ig r at e / 0 01 _ c r e a te _ p ro j e ct s . r b

    r o ut e m ap . r e s o ur c es : p r oj e ct s

    Ademas del modelo, el controlador y las vistas, el generador tambien crea

    un script de migracion completamente funcional, as como una nueva entradamap.resources :projects en config/routes.rb, que sera responsable del caracterREST de nuestro nuevo controlador. Pero antes de profundizar en esto haremosen primer lugar un recorrido paso a paso por todo lo que ha sido generadopara nosotros.

    1.6. El modelo

    Tal y como mencionamos al principio los recursos REST son, en el contextode Rails, la combinacion de un controlador y un modelo. El modelo es una clase

    normal ActiveRecord que hereda de ActiveRecord::Base:

    c l as s P r oj e ct < A c t iv e R ec o r d :: B a se

    en d

    As que en el caso del modelo no hay novedades. Pero no debemos olvidar-nos de generar la tabla de la base de datos:

    > r a ke d b : m ig r at e

  • 7/22/2019 Restful Rails Es

    12/41

    6 CAPITULO 1. RAILS Y REST

    1.7. El controlador

    ProjectsController es un controlador CRUD que manipula el recurso Pro-ject, lo que quiere decir que maneja exactamente un tipo de recurso y ofreceuna accion especfica para cada una de las cuatro operaciones CRUD 4:

    4El controlador tambien ofrece las acciones index para mostrar un listado de todos losrecursos de este tipo,new para abrir el formulario de creacion de nuevo recurso y edit para

    mostrar el formulario de edicion.

  • 7/22/2019 Restful Rails Es

    13/41

    1.7. EL CONTROLADOR 7

    Listado 1.1: ontrack/app/controllers/projects controller.rb

    c l a s s P r o j e c t s C o n t r o l l e r < A p p l i c a t i o nC o n t r o l l e r# G ET / p r o je c ts

    # G ET / p r o je c ts . x m l

    d ef i n de x . . .

    # G ET / p r o je c ts / 1

    # G ET / p r o je c ts / 1 . x ml

    d ef s h ow . . .

    # G ET / p r o je c ts / n e w

    d ef n ew . . .

    # G ET / p r o je c ts / 1 ; e d it

    d ef e d it . . .

    # P O ST / p r o je c ts

    # P O ST / p r o je c ts . x m l

    d e f c r e a te . . .

    # P UT / p r o je c ts / 1

    # P UT / p r o je c ts / 1 . x ml

    d e f u p d a te . . .

    en d

    # D E LE T E / p r o je c ts / 1

    # D E LE T E / p r o je c ts / 1 . x ml

    d e f d e s t r oy . . .

    en d

    No hay muchas novedades por aqu: en el controlador generado automati-camente hay acciones para la creacion, recuperacion, modificacion y borradode proyectos. Tanto el controlador como las acciones parecen normales a pri-mera vista, pero todos tienen un comentario mostrando la peticion URL a laque responderan con su verbo HTTP incluido. Se trata de URLs REST y lasinspeccionaremos mas a fondo en la siguiente seccion.

    1.7.1. URLs REST

    Las URLs basicas en REST no se componen de nombre de controlador,accion e identificador del modelo (por ejemplo, /projects/show/1 ) como esta-mos acostumbrados a ver en las aplicaciones tradicionales Rails. En lugar deesto tan solo incluyen el nombre del controlador seguido del identificador delrecurso a manipular:

    / p r o j e c t s / 1

    Al haber desaparecido el nombre de la accion ya no resulta obvio determi-nar que va a ocurrir con el recurso indicado. Por ejemplo, la URL mostrada

    anteriormente debera mostrar o borrar el recurso? La respuesta a esta cues-

  • 7/22/2019 Restful Rails Es

    14/41

    8 CAPITULO 1. RAILS Y REST

    tion viene dada por el metodo HTTP 5 que se utilizara al solicitar la URL.

    La siguiente tabla presenta los cuatro verbos HTTP, sus URLs REST y c omose corresponderan con acciones de controlador en las URLs tradicionales deRails:

    Cuadro 1.1: Verbos HTTP y URLs RESTVerbo HTTP URL REST Accion URL sin REST

    GET /projects/1 show GET /projects/show/1DELETE /projects/1 destroy GET /projects/destroy/1PUT /pro jects/1 update POST /pro jects/update/1POST /pro jects create POST /pro jects/create

    Las URLs REST son identicas para todas los verbos excepto en el caso dePOST porque cuando creamos un nuevo proyecto aun no existe su identifica-dor. Por lo general, la accion a ejecutar viene determinada por el verbo HTTPy las URLs hacen referencia a recursos en lugar de acciones.

    Nota: Si introducimos la URL http://localhost:3000/projects/1 en el na-vegador siempre se producira una llamada a show porque cuando un navegadorabre una direccion siempre utiliza el verbo GET. Dado que los navegadoressolo utilizan los verbos GET y POST, Rails tiene que hacer algunas triquinue-las para habilitar las acciones destroy y destroy, en este caso proporcionandohelpers especiales para la creacion de links para borrar y crear recursos, deforma que el verbo DELETE se transmite al servidor en un campo oculto den-tro de una peticion POST (como se vera en la seccion 1.8.3). El verbo PUT seenva de la misma forma para la creacion de nuevos recursos (vease a seccion1.8.2).

    1.7.2. Las acciones REST utilizan respond to

    Ya hemos visto que las acciones REST se activan mediante una combi-nacion de URL de recurso y un verbo HTTP dando como resultado URLslimpias que solo direccionan el recurso a manipular. Pero, que mas se puedeespecificar en una URL REST?

    Las acciones REST tambien pueden responder a diferentes tipos de clientesque esperan diferentes formatos de respuesta. Por supuesto el cliente m as ha-bitual para una aplicacion web sera una navegador pero tambien puede haber,por ejemplo, clientes de servicios web que suelen esperar la respuesta en XMLo agregadores de feeds que prefieren el resultado en RSS o Atom.

    El mecanismo principal para la generacion del formato de respuesta soli-citado por el cliente es el metodo respond to que el generador de andamiajescoloca en las acciones CRUD. El siguiente fragmento de c odigo muestra laaccion show como ejemplo de uso de respond to:

    5en este tutorial utilizaremos el termino verbo HTTP, porque expresa mejor que la peti-

    cion dara como resultado una accion.

  • 7/22/2019 Restful Rails Es

    15/41

    1.7. EL CONTROLADOR 9

    Listado 1.2: ontrack/app/controllers/projects controller.rb

    # G ET / p r o je c ts / 1# G ET / p r o je c ts / 1 . x ml

    d ef s h ow

    @ p r o j ec t = P r o j ec t . f i n d ( p a r a m s [ : i d ] )

    r e s po n d_ t o d o | f o rm a t |

    f o rm a t . h tm l # s h ow . r h t ml

    f o rm a t . xm l { r e nd e r : x ml = > @ p ro j ec t . t o _x m l }

    en d

    en d

    El metodo respond to recibe un bloque con instrucciones especficas paracada formato. En nuestro ejemplo el bloque maneja dos formatos: HTML yXML, y segun el formato solicitado por el cliente se ejecutan las instruccionescorrespondientes. Si es HTML no ocurre nada especial, lo que produce comoresultado la generacion de la vista por defecto, show.rhtml, y si por el contrarioel formato es XML el recurso sera devuelto como XML.

    El formato de la respuesta puede indicarse de dos maneras: o bien se colocaen el campo accept de la cabecera HTTP de la peticion o se anade a la URLde la peticion.

    1.7.3. Campo Accept de la cabecera HTTP

    Empezaremos viendo la produceimera tecnica: utilizar el verbo HTTP en elcampo accept de la cabecera. Es muy sencillo cambiar la cabecera HTTP con

    la herramienta de lnea de comandos curl Pero antes de comprobarlo tenemosque arrancar el servidor web:

    > r u by s c ri p t / s er v er w e br i ck

    = > B o ot i ng W E Br i ck . . .

    = > R a il s a p p li c a ti o n s t ar t ed o n h tt p : / / 0 .0 . 0 .0 : 3 00 0

    = > C tr l - C t o s hu td ow n s er ve r ; c al l w it h - - he lp f or o pt io ns

    [ 2 00 6 - 1 2 - 30 1 8 : 1 0 :5 0 ] I N FO W E Br i ck 1 . 3 . 1

    [ 2 00 6 - 1 2 - 30 1 8 : 10 : 50 ] I N F O r u by 1 . 8. 4 ( 2 0 05 - 1 2 - 2 4)

    [ 2 00 6 - 1 2 - 30 1 8 : 10 : 50 ] I NF O W E Br i ck : : H T T PS e rv e r # s t ar t : p o rt = 3 0 00

    A continuacion abriremos la pagina de proyectos de Ontrack, abriendo la

    siguiente URL: http://localhost:3000/projects, y crearemos uno o mas proyec-tos (vease la figura 1.2).

    Este invocacion de curl solicita el recurso proyecto 1 en formato XML:

    > c u rl - H " A c c e pt : a p p li c a ti o n / x ml " \

    - i - X G ET h t tp : / / l o c al h os t : 3 0 00 / p r o je c ts / 1

    = >

    H T TP / 1 . 1 2 00 O K

    C o n n e c ti o n : c l o se

    D at e : Sa t , 3 0 D ec 2 00 6 1 7: 31 :5 0 G MT

    S et - C o o k ie : _ s e s s i on _ i d = 4 5 4 5 e a b d 9 d 1 b e b d e 3 6 7 e c b ad f 0 1 5 b c c 2 ; p a t h = /

    S t at u s : 2 00 O K

    C a ch e - C o n t ro l : n o - c a c h e

    S e r v er : M o n g r el 0 . 3 . 1 3. 4

  • 7/22/2019 Restful Rails Es

    16/41

    10 CAPITULO 1. RAILS Y REST

    Figura 1.2: Crear algunos proyectos

    C o n te n t - T y p e : a p p l i c at i o n / x m l ; c h a r se t = u t f - 8

    Content -Length : 160

    < ? x ml v e r s io n = " 1 . 0 " e n c o d in g = " U T F - 8 " ? >

    < d e sc > F u t u r e o f O n l i ne M a r ke t i ng < / d es c >

    < i d t y p e = " i n t e ge r " > 1 < / i d >

    Wunderloop

    Rails enruta esta peticion a la accion show. Como hemos preferido XMLen el campo Accept de la cabecera HTTP nuestro metodo respond to ejecutael bloque correspondiente y el recurso accedido se convierte a XML en la

    respuesta.De hecho curl no solo nos sirve para probar los diferentes formatos de res-puesta - tambien es muy util para enviar verbos HTTP que no son soportadospor los navegadores. La siguiente peticion, por ejemplo, borrara el proyectonumero 1:

    > c u rl - X D E LE T E h t tp : / / l o c al h os t : 3 0 00 / p r o je c ts / 1

    = >

    Y ou a re b e in g < a h r ef = " h t tp : / / l o ca l h os t : 3 0 00 / p r o je c ts " >

    redirected .

    Esta vez la peticion utiliza el verbo DELETE. El dispatcher de Rails evaluael verbo y encamina la peticion al metodo ProjectsController.destroy. Observe-se que la URL es identica a la que se ha usado en la anterior peticion con curl,siendo la unica diferencia que esta vez se ha usado otro verbo HTTP.

    1.7.4. Especificacion del formato por la URL de la peticion

    La segunda manera de pedir un formato especfico de respuesta es codi-ficandolo en la URL. (Si borramos el ultimo recurso de proyecto en el ejemplo

    previo tendremos que ir a la aplicacion Ontrack y volver a crear otro ahora)

  • 7/22/2019 Restful Rails Es

    17/41

    1.8. URLS Y VISTAS REST 11

    Para mostrar el proyecto 1 y para solicitar la respuesta en formato XML basta

    con abrir la siguiente direccion en el navegador:

    h t t p : / / l o c a l h o s t : 3 0 0 0 / p r o j e c t s / 1 . x m l

    Figura 1.3: El proyecto Wunderloop en XML

    Atencion, usuarios de Mac: Esta peticion es mas facil de comprobaren Firefox que en Safari porque este navegador simplemente ignora el XML

    devuelto. Firefox, por el contrario, formatea el XML (ver la figura 1.3).Hasta ahora hemos aprendido como funcionan los controladores REST y

    que aspecto tienen las URLs. En las dos proximas secciones veremos comousar y generar estas URLs en las vistas y controladores.

    1.8. URLs y vistas REST

    Las vistas representan la interfaz entre la aplicacion y sus usuarios, queinteractuan con ella utilizando enlaces y botones. Tradicionalmente en Railsse generaban los enlaces utilizando el helper link to, que esperaba un hash

    conteniendo el controlado y la accion as como parametros opcionales para lapeticion:

    l i nk _ to : c o n t ro l le r = > " p r o je c ts " ,

    : a ct io n = > " s ho w ", : id = > p ro je ct

    = >

    < a h r e f = "/ p r o j e c t s / s h o w / 1 " > S h ow < / a >

    Se ve inmediatamente que este uso tradicional de link to no encaja muybien con la nueva filosofa REST porque en ella se especifica que las URLsidentifican al recurso y la accion se determina con el verbo HTTP utilizado. Loque necesitamos es que los enlaces y botones pasen el verbo HTTP apropiado

    junto con la URL.

  • 7/22/2019 Restful Rails Es

    18/41

    12 CAPITULO 1. RAILS Y REST

    Rails propone la siguiente solucion: se sigue usando el metodo link to para

    generar el enlace, pero el hash es sustituido por una llamada a un metodo dePath. Los metodos de path crean enlaces de destino que link to colocara en elatributo href del enlace generado. Como primer ejemplo crearemos un enlacea la accion show del controlador ProjectsController. En vez de especificar elcontrolador, accion e id de proyecto en un hash utilizaremos project path():

    l i n k _ to " S h o w " , p r o j e c t _p a t h ( p r o j e c t )

    = >

    < a h r e f = " / p r o j ec t s / 1 " > S h ow < / a >

    El atributo href del metodo tradicional link to esta compuesto de un con-trolador, una accion y un identificador de proyecto. En su lugar, project pathconstruye un path REST que consiste solo en el controlador y el identificadordel proyecto. Como los enlaces usan el verbo HTTP GET por defecto, cuandoel usuario haga clic en el enlace Rails reconoce que el proyecto en cuestiondebera ser mostrado y se ejecutara la accion show.

    Para cada tipo recurso en nuestra aplicacion Rails generara automatica-mente los siete metodos de path estandar que se muestran en la tabla 1.2.

    Cuadro 1.2: Metodos de path

    Metodo de path Verbo Path Accion solicitadaprojects path GET /projects indexproject path(1) GET /projects/1 shownew pro ject path GET /pro jects/new newedit project path(1) GET /projects/1;edit editprojects path POST /projects createproject path(1) PUT /projects/1 updateproject path(1) DELETE /projects/1 destroy

    Cada metodo de path ira asociado con un verbo HTTP, lo que significa

    que este es el metodo HTTP que se enviara al servidor cuando se pulse sobreel enlace o boton. Algunas de las peticiones (show, update) seran transmitidaspor defecto con el verbo HTTP adecuado (es decir, GET o POST). Otras(create, delete) tienen que ser tratadas de forma especial (utilizando camposocultos) porque, como ya se ha mencionado, el navegador no utiliza los verbosPUT y DELETE. Aprenderemos mas acerca de estos casos especiales y suimplementacion en las secciones 1.8.3 y 1.8.2.

    Examinando la tabla puede verse que los cuatro verbos HTTP no sonsuficientes como para mapear todas las acciones CRUD. Los dos primerosmetodos, projects path y project path(1), funcionan bien con GET y puedenser mapeados directamente a sus acciones apropiadas. Sin embargo, las cosas

    no estan tan claras para new project path y edit project path.

  • 7/22/2019 Restful Rails Es

    19/41

    1.8. URLS Y VISTAS REST 13

    1.8.1. New y Edit

    Un clic sobre el enlace New se transmite al servidor usando el metodo GET.El siguiente ejemplo muestra que el path generado consiste en el controladorProjectsController y la accion new que es la que se va a invocar:

    l i n k _t o " N e w " , n e w _ p r o j e ct _ p a t h

    = >

    < a h r e f = "/ p r o j e c t s / n e w " > N ew < / a >

    Constitutye esto una fisura en la filosofa REST? A primera vista, tal vez.Pero, en perspectiva, resulta claro que new no es una accion REST/CRUD- no modifica ninguno de los datos de la aplicacion, sino que mas bien se

    trata de un preparativo para la creacion de un nuevo recurso. La autenticaaccion CRUD es create, que se ejecuta cuando se enva el formulario new. Elidentificador de recurso no aparece en la URL puesto que el recurso todavano existe.

    Lo mismo ocurre con el metodo edit project path - hace referencia a unrecurso concreto, pero no es una accion CRUD. edit project path se empleapara preparar la verdadera llamada CRUD que se producira cuando se enveel metodo update. La diferencia entre edit project path y new project pathes que edit project path necesita el id de proyecto a manipular. Siguiendola convencion REST, el id aparece despues del controlador: /projects/1. Sinembargo, si se enviase este path al servidor con un GET la llamada sera despa-

    chada a la accion show action. Para distinguir la accion edit, edit project pathsimplemente extiende el atributo href generado de una manera especial. Estees el aspecto del enlace HTML finalmente generado:

    l i n k _t o " E d i t " , e d i t _ p r o j ec t _ p a t h ( p r o j e c t )

    = >

    < a h r e f = "/ p r o j e c t s / 1 ; e d i t " > E d it < / a >

    No hay ningun problema en que new y edit incluyan la accion en la URLporque no son realmente acciones REST/CRUD de verdad. El mismo principiose utiliza para escribir acciones que utilicen otros nombres que no sean losnombres CRUD estandar (como veremos en la seccion1.12).

    1.8.2. Metodos de Path en los formularios: Create y Update

    Tradicionalmente, los formularios se creaban usando los helpers form tago form for, especificando la accion a invocar cuando se pulsa el boton de envo:

    < % f o r m _ fo r : p r o je c t , @ p r oj e c t ,

    : ur l = > { : a ct io n = > " c r ea te " } d o | f | %>

    .. .

    < % end %>

    En una aplicacion REST el hash :url se rellena con el valor devuelto por

    alguno de los metodos de path:

  • 7/22/2019 Restful Rails Es

    20/41

    14 CAPITULO 1. RAILS Y REST

    project path for the new form

    project path(:id) for the edit form

    El nuevo formulario

    El formulario se transmite al servidor mediante POST. La peticion deproject path sin ningun id da como resultado el path /projects que cuando seenva usando POST provoca la ejecucion de la accion create:

    f o rm _ fo r ( : p ro je c t , : u r l = > p r o je c t s_ p a th ) d o | f | . ..

    = >

    < f o r m a c t i o n = " / p r o j e c t s " m e t h od = " p o s t " >

    El formulario Edit

    De acuerdo con la filosofa REST la modificacion de un recurso se realizamediante PUT pero, como ya sabemos, los navegadores no soportan ni PUTni DELETE. La solucion que ofrece Rails es utilizar una clave method en elhash :html de form for:

    f o r m _ fo r ( : p r o j ec t , : u r l = > p r o j e c t _p a t h ( @ p r o j e c t ) ,

    : ht ml = > { : m et ho d = > : p ut } ) do | f| . ..

    = >

    < f o r m a c t i o n = " / p r o j e c t s / 1 " m e t h o d = " p o s t " >

    < d i v s t y le = " m a r g i n : 0 ; p a d d i n g : 0 " >

    < i n pu t n am e = " _ m et h od " t yp e = " h id d en " v a lu e = " p ut " / >

    Rails genera un campo oculto method que contendra el verbo HTTPapropiado (put). El dispatcher examinara este campo y pasara la peticion ala accion update.

    1.8.3. Destroy

    Observerse que el metodo usado en los enlaces tanto para mostrar como

    para borrar un proyecto es project path:

    l i n k _ to " S h o w " , p r o j e c t _p a t h ( p r o j e c t )

    l i nk _ to " D e s tr o y " , p r oj e c t_ p a th ( p r o j ec t ) , : m e t ho d = > : d e le t e

    La unica diferencia es que el enlace a destroy utiliza el parametro :methodpara especificar el metodo HTTP a usar (en este caso :delete). Debido a que elnavegador no soporta el verbo DELETE, Rails generara el siguiente fragmentode codigo Javascript que se ejecutara al hacer clic en el enlace:

    l i nk _ to " D e s tr o y " , p r oj e c t_ p a th ( p r o j ec t ) , : m e t ho d = > : d e le t e

    = >

    < a h r e f = " / p r o j ec t s / 1 "

  • 7/22/2019 Restful Rails Es

    21/41

    1.9. METODOS DE URL EN EL CONTROLADOR 15

    o n c l i ck = " v a r f = d o c u m en t . c r e a t e E l e m e n t ( f or m ) ;

    f . s t y l e . d i s p l ay = n o ne ; t h i s . p a r e n t No d e . a p p e n d C h i l d ( f ) ;f . m e th o d = P OS T ; f . a c ti o n = t hi s . h re f ;

    v a r m = d o c u m en t . c r e a t e E l e m e n t ( i n pu t ) ;

    m. se tAtt rib ute ( ty pe , hi dd en ) ;

    m. se tAtt rib ute ( na me , _m et ho d );

    m. se tAtt rib ute ( va lu e , de le te ) ;

    f . a p p e n d C h i l d ( m ) ;

    f . s u b m i t ( ) ;

    r e t u rn f a l se ; " > D e s t r oy < / a >

    Este pequeno script crea un formulario al vuelo y garantiza que se envael metodo DELETE en el campo oculto method. Nuevamente, el dispatcherde Rails comprueba el contenido de este campo y sabe que la petici on se debe

    encaminar hacia la accion destroy.

    1.9. Metodos de URL en el controlador

    Igual que los enlaces y acciones de envo de las vistas REST se crean con laayuda de nuevos helpers, los controladores tienen que tener tambien cuidadocuando hagan redirecciones. Rails define para esto metodos de URL, existiendoun metodo URL para cada metodo de path:

    project url for project pathoprojects url for projects path.Al contrario que los metodos de path los metodos de URL crean URLs

    completas incluyendo el protocolo, el host, el puerto y la direccion:

    project_url(1)

    = >

    " h t t p : / / l o c a l h o s t : 3 0 0 0 / p r o j e c t s / 1 "

    projects_url

    = >

    " h t t p : / / l o c a l h o s t : 3 0 0 0 / p r o j e c t s "

    Los metodos de URL se usan dentro de los controladores de una aplica-

    cion REST en los mismos lugares donde tradicionalmente se usaba redirect topasandole un hash con controlador/accion/parametros. Por tanto, lo siguiente:

    r e d ir e ct _ t o : c o n tr o ll e r = > " p r o je c ts " , : a c t io n = > " s h ow " ,

    : i d = > @ p ro j ec t . i d

    en una aplicacion REST se convierte en:

    r e d i r e ct _ t o p r o j e c t_ u r l ( @ p r o j e c t )

    Un ejemplo de esto lo podemos encontrar en el metodo destroy, donde seutiliza projects url sin parametro alguno para redirigir al listado de todos los

    proyectos despues de que se haya borrado uno:

  • 7/22/2019 Restful Rails Es

    22/41

    16 CAPITULO 1. RAILS Y REST

    Listado 1.3: ontrack/app/controllers/projects controller.rb

    d e f d e s t r oy@ p r o j ec t = P r o j e ct . f i n d ( p a r a m s [ : i d ] )

    @project.destroy

    r e sp o n d_ t o d o | f o r ma t |

    f o rm a t . h tm l { r e di r e ct _ t o p r o je c t s_ u r l }

    f or ma t .x ml { h e ad : o k }

    en d

    en d

    1.10. Rutas REST

    Hasta ahora llevamos explicado el concepto REST as como unos cuantosmetodos nuevos que hay que usar en los enlaces, formularios y controladores.Sin embargo, aun no hemos explicado de donde surgen todos estos metodos: desu existencia y de la gestion adecuada de las peticiones REST es responsableuna nueva entrada en el fichero de rutas de Rails, config/routes.rb:

    ma p . re sources : projects

    Esta entrada ha sido puesta ah por el generador scaffold resource, y crealas rutas necesarias para solicitar las acciones REST de ProjectsController.

    Ademas, resources genera los metodos de path y URL para el recursoProject con los que ya hemos estado experimentando en este captulo:

    ma p . re sources : projects

    = >

    Ruta Helper generado

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    p ro je ct s p ro je ct s_ ur l , p ro je ct s_ pa th

    p ro je ct p ro je ct _u rl ( id ), p ro je ct _p at h( id )

    n e w _p r o je c t n e w_ p ro j ec t _u r l , n e w _p r o je c t _p a t h

    e d i t _ p r oj e c t e d i t _ p r o je c t _ u r l ( i d ) , e d i t _ p r o j ec t _ p a t h ( i d )

    1.10.1. Convenciones

    Como consecuencia de desarrollar empleando rutas REST, tenemos quecumplir con las convenciones de nombrado de las acciones CRUD. La siguientellamada a link to y el HTML generado lo muestran:

    l i n k _ to " S h o w " , p r o j e c t _p a t h ( p r o j e c t )

    = >

    < a h r e f = " / p r o j ec t s / 1 " > S h ow < / a >

    Ni la llamada a link to ni el codigo HTML generado incluyen el nombre dela accion que hay que invocar. El dispatcher de Rails sabe que la ruta /projec-

    ts/:id debe enviarse a la accion show de ProjectsController si la peticion fue

  • 7/22/2019 Restful Rails Es

    23/41

    1.10. RUTAS REST 17

    enviada con el verbo GET, lo que implica que el controlador debe tener una

    accion con el nombre show. La misma convencion se cumple para las accio-nes index, update, create, destroy, new y edit - todo controlador REST debeimplementar estos metodos.

    1.10.2. Ajustes

    Las rutas REST pueden adaptarse a los requisitos especficos de nuestraaplicacion con ayuda de las siguientes opciones:

    :controller. El controlador a usar

    :path prefix. Prefijo de la URL (incluyendo cualquier variable que sea

    necesaria)

    :name prefix. Prefijo de los helpers de ruta creado

    :singular. Forma singular del nombre de recurso

    La siguiente entrada crea rutas para un nuevo recurso Sprint. Un sprint, enel contexto de gestion agil de proyectos, es sinonimo de iteracion y se mapea almodelo ActiveRecord Iteration (que presentaremos en el siguiente apartado):

    ma p . resour ces : sp rin ts ,

    : c o n t ro l le r = > " o n t ra c k " ,

    : p a t h _ p r e f i x = > " / o n t r a c k / : p r o j e c t_ i d " ,

    : n a m e _p r e fi x = > " o n t ra c k_ "

    La opcion path prefix se utiliza para dar formato de la URL, en nues-tro ejemplo, cada URL comienza con /ontrack seguida del identificador deproyecto. Tambien especificamos que el controlador responsable sera Ontrack-Controller. As, la URL

    h t t p : / / l o c a l h o s t : 3 0 0 0 / o n t r a c k / 1 / s p r i n t s

    se encamina de acuerdo con el mapa anterior a la acci on index de Ontra-

    ckController. Otro ejemplo es la URL

    h t t p : / / l o c a l h o s t : 3 0 0 0 / o n t r a c k / 1 / s p r i n t s / 1

    que se encamina hacia la accion show del controlador OntrackController.

    De la misma manera que path prefix define el formato de la URL, na-me prefix hace que los metodos helper generados empiecen por ontrack . Porejemplo:

    o n t r a c k _ s p r i n t s _ p a t h ( 1 )

    = >

    / o n t r a c k / 1 / s p r i n t s

  • 7/22/2019 Restful Rails Es

    24/41

    18 CAPITULO 1. RAILS Y REST

    o

    o n t r a c k _ e d it _ s p r i n t _ p a th ( 1 , 1 )

    = >

    / o n t r a c k / 1 / s p r i n t s / 1 ; e d i t

    1.11. Recursos anidados

    El desarrollo REST se pone realmente interesante cuando se emplean losdenominados recursos anidados, donde se hace patente la importancia de lasURLs limpias. Ademas los recursos anidados nos ayudaran a entender mejor

    los conceptos del paradigma REST.Los recursos anidados son recursos fuertemente acoplados en el sentido deque muestran una relacion de padres e hijos. En el contexto de Rails estoquiere decir que se trata de modelos que representan relaciones uno-a-muchos,tales como Projectsy Iterationsen Ontrack. Los controladores REST anidadossiguen siendo responsables de manipular un unico tipo de recurso, pero en elcaso del controlador del hijo tambien leen el modelo del recurso padre.

    El enfoque REST de Rails refleja la relacion entre recursos anidados en susURLs y mantiene el principio de URLs limpias. Describiremos este principiocon el ejemplo de las iteraciones y proyectos en Ontrack. Por supuesto, hemosde empezar con la generacion del recurso Iteration y la creacion de la tabla

    iterations en la base de datos:

    > r u by s c ri p t / g en e ra t e s c a ff o l d_ r e so u r ce i t er a ti o n n a me : s t r in g \

    s t a r t : d a te e n d : d a t e p r o j e c t_ i d : i n t e g e r

    > r a ke d b : m ig r at e

    Los proyectos tienen una relacion uno-a-muchos con respecto a las itera-ciones. Esta relacion se implementa en el modelo:

    Listado 1.4: ontrack/app/models/project.rb

    c l as s P r oj e ct < A c t iv e R ec o r d :: B a se

    h a s _ m an y : i t e r a t i o n s

    en d

    Listado 1.5: ontrack/app/models/iteration.rb

    c l as s I t er a ti o n < A c ti v e Re c o rd : : B a se

    b e l o n g s_ t o : p r o j e c t

    en d

    Ademas de crear modelo, controlador y vistas, el generador tambien creauna nueva ruta en config/routes.rb:

    ma p . re sources : it eration s

  • 7/22/2019 Restful Rails Es

    25/41

    1.11. RECURSOS ANIDADOS 19

    Igual que con la linea para projects, esta sentencia genera las nuevas rutas y

    helpers para la manipulacion del recurso Iteration. No obstante las iteracionessolo tienen sentido en el contexto de un proyecto concreto - y esto es algoque las rutas y helpers recien creados no tienen en cuenta. Por ejemplo, elhelper new iteration path devolvera el path /iterations/new, que no aportainformacion sobre el proyecto al que pertenece la nueva iteraci on.

    La idea de los recursos anidados consiste, en esencia, en tener en cuentaque un recurso hijo (en este caso, una iteraci on) no puede existir fuera delcontexto de algun recurso padre al que pertenece (en este caso, un proyecto).Rails trata de reflejar esto en el uso de URLs y el controlador del recurso hijo.Y para que todo esto funcione se necesita cambiar la entrada generada delrecurso en config/routes.rb:

    ma p . resour ces : itera tions

    por:

    ma p . resour ces : projects do | projects |

    p r o j e ct s . r e s o u r c e s : i t e r a t i o n s

    en d

    Esta lnea indica que Iteration es un recurso anidado y genera las rutasapropiadas que permiten manipular iteraciones unicamente en el contexto de

    un proyecto. Las rutas generadas tienen el siguiente formato:

    / p r o j e c t / : p r o j e c t _ i d / i t e r a t i o n s

    / p r o j e c t / : p r o j e c t _ i d / i t e r a t i o n s / : i d

    Por ejemplo, la URL

    h t t p : / / l o c a l h o s t : 3 0 0 0 / p r o j e c t s / 1 / i t e r a t i o n s

    hace que se ejecute la accion index del controlador IterationsController,obteniendo el identificador del proyecto por medio del parametro de la peticion

    :project id. Notese como la URL claramente indica la asociacion subyacente:

    / p r o j e c t s / 1 / i t e r a t i on s < = > P r o j e c t . f i n d ( 1 ) . i t e r a t i o n s

    Las URLs REST anidadas siguen siendo URLs limpias: hacen referencia arecursos, no acciones. El hecho de que un recurso este anidado viene indicadopor dos URLs REST que aparecen una detras de otra en una unica URL. Porejemplo he aqu una peticion a la accion show de una iteracion concreta:

    h t t p : / / l o c a l h o s t : 3 0 0 0 / p r o j e c t s / 1 / i t e r a t i o n s / 1

  • 7/22/2019 Restful Rails Es

    26/41

    20 CAPITULO 1. RAILS Y REST

    1.11.1. Adaptacion de los controladores

    El controlador generado IterationsControllerno sabe automaticamente quees responsable de un recurso anidado y que con cada peticion tambien debeaveriguar el identificador del proyecto padre. Por ejemplo, la accion indexsigue cargando todas las iteraciones almacenadas aun cuando la URL clara-mente indica que solo se deberan cargar todas las iteraciones de un proyectoespecfico.

    Listado 1.6: ontrack/app/controllers/iterations controller.rb

    d ef i n de x

    @ i t e r a ti o n s = I t e r a ti o n . f i n d ( : a l l )

    r e sp o n d_ t o d o | f o r ma t |f o rm a t . h tm l # i n de x . r h tm l

    f or ma t . xm l { r en de r : x ml = > @ it er a ti on s . t o_ xm l }

    en d

    en d

    Es necesario cambiar la accion para que solo se carguen las iteraciones delproyecto correspondiente:

    Listado 1.7: ontrack/app/controllers/iterations controller.rb

    d ef i n de x

    p r o j ec t = P r o j ec t . f i n d ( p a r a m s [ : p r o j e c t _ id ] )@ i t e r a ti o n s = p r o j ec t . i t e r a t i o n s . f i n d ( : a l l )

    .. .

    en d

    Dado que toda accion del controlador IterationsController solo puede fun-cionar adecuadamente con un prefijo /projects/:project id: es necesario quequede definido el proyecto padre que define el ambito de la iteracion o itera-ciones que queremos manipular. Pero esto quiere decir tambien que hay quereescribir no solo la accion index sino tambien las acciones create (veanse lassecciones create 1.11.3) y update (seccion 1.11.4).

    1.11.2. Nuevos parametros en los helpers de path y URL

    La entrada del recurso en config/routes.rb para las iteraciones no solo ge-nera nuevas rutas sino tambien nuevos helpers. Y como en el caso de las rutasestos helpers esperan un identificador de proyecto como primer parametro. Porejemplo el path que denota el listado de todas las iteraciones de un proyectose genera con el helper iterations path. Los nombres de los helpers para recur-sos anidados son identicos a los nombres de los helpers para los recursos noanidados, lo unico que cambia es el numero de parametros que requieren loshelpers. Los helpers de los recursos anidados siempre esperaran el identificadordel recurso contenedor como primer parametro, en este caso el identificador

    del proyecto. Aqu, por ejemplo, el enlace iterations (que aparece en la vista

  • 7/22/2019 Restful Rails Es

    27/41

    1.11. RECURSOS ANIDADOS 21

    index de ProjectsController) muestra todas las iteraciones del proyecto es-

    cogido. Aqu la URL para el listado de iteraciones se genera por el helperiterations path, que espera el parametro con el identificador del proyecto:

    l i n k _t o " I t e r a t i o n s " , i t e r a t i o ns _ p a t h ( p r o j e c t )

    = >

    < a h r e f = "/ p r o j e c t s / 1 / i t e r a t i o n s " > I t e ra t i o ns < / a >

    Para entenderlo mejor miraremos el enlace donde realmente se usa, en lavista ProjectsController:

  • 7/22/2019 Restful Rails Es

    28/41

    22 CAPITULO 1. RAILS Y REST

    Listado 1.8: ontrack/app/views/projects/index.rhtml

    .. .< % f or p ro je ct i n @ pr oj ec ts %>

    < t r >

    < t d > < % = h p r o j e c t . n a m e % >

    < t d > < % = h p r o j e c t . d e s c % >

    < t d > < % = l i n k _ t o " I t e r a t io n s " , i t e r a t i o ns _ p a t h ( p r o j e c t ) % >

    < td > < % = l i nk _ to " S h ow " , p r o je c t _p a t h ( p ro j ec t ) % >< /t d >

    < t d > < % = l i n k _ t o " E d i t " , e d i t _ p r o j e c t _ p at h ( p r o j e c t ) % >

    < t d > < % = l i n k _ t o " D e s t r oy " , p r o j e c t _p a t h ( p r o j e c t ) ,

    : c on fi rm = > " A re y ou s ur e ?" , : m et ho d = > : d el et e % >

    < % end %>

    .. .

    Consecuencia del nuevo parametro no es que solo se han roto algunas ac-ciones del controlador, sino tambien muchas de las vistas generadas automati-camente para las iteraciones. Por ejemplo, la vista index contiene una tablacon todas las iteraciones y cada iteracion tiene tres enlaces:

    Listado 1.9: ontrack/app/views/iterations/index.rhtml

    .. .

    < % f or i te ra ti on i n @ i te ra t io ns %>

    < t d > < % = h i t e r a t i o n . n a m e % >

    < t d > < % = h i t e r a t i o n . s t a r t % >

    < t d > < % = h i t e r a t i o n . e n d % > < td > < % = l i nk _ to " S h ow " , i t e ra t i on _ p at h ( i t e ra t i on ) % >

    < t d > < % = l i n k _ t o " E d i t " , e d i t _ i t e r a t i o n _ p at h ( i t e r a t i o n ) % >

    < t d > < % = l i n k _ t o " D e s t r oy " , i t e r a t i on _ p a t h ( i t e r a t i o n ) ,

    : c on fi rm = > " A re y ou s ur e ?" ,

    : m e th o d = > : d e l et e % >< /t d >

    < % end %>

    .. .

    Todos los enlaces comienzan con el id de la iteracion como primer y unicoparametro. Esto ya no funciona porque el primer parametro de un helper paralas iteraciones debera ser el identificador de proyecto. El cambio necesariotiene el siguiente aspecto:

    Listado 1.10: ontrack/app/views/projects/index.rhtml

    .. .

    < % f or i te ra ti on i n @ i te ra t io ns %>

    < t d > < % = h i t e r a t i o n . n a m e % >

    < t d > < % = h i t e r a t i o n . s t a r t % >

    < t d > < % = h i t e r a t i o n . e n d % >

    < td > < % = l i nk _ to " S h ow " ,

    i t e r a t i o n_ p a t h ( i t e r a t i o n . p r o je c t , i t e r a ti o n ) % >

    < td > < % = l i nk _ to " E d it " ,

    e d i t _ i t e r a ti o n _ p a t h ( i t e r a t i on . p r o j e ct , i t e r a ti o n ) % >

  • 7/22/2019 Restful Rails Es

    29/41

    1.11. RECURSOS ANIDADOS 23

    < td > < % = l i nk _ to " D e s tr o y " ,

    i t e r a t i on _ p a t h ( i t e r a t i o n . p r oj e c t , i t e r a ti o n ) ,: c on fi rm = > " A re y ou s ur e ?" ,

    : m e th o d = > : d e l et e % >

    < % end %>

    .. .

    Una manera alternativa de corregir la lista de parametros de los helpersde los recursos anidados es pasar los identificadores necesarios como un hash:

    i t e r a t i o n_ p a t h ( : p r o j e c t _ i d = > i t e r a ti o n . p r o j ec t , : i d = > i t e r a ti o n )

    lo cual hace el codigo mas legible cuando no es evidente con que tipo deobjeto esta relacionada la iteracion.

    1.11.3. Creando nuevas iteraciones

    Otra accion que solo funciona en el contexto de un proyecto previamen-te escogido es la de anadir nuevas iteraciones. Para gestionar esto, solamentetenemos que anadir un enlace New Iteration a la vista index de ProjectsCon-troller:

    Listado 1.11: ontrack/app/views/projects/index.rhtml

    .. .< % f or p ro je ct i n @ pr o je ct s %>

    < t d > < % = h p r o j e c t . n a m e % >

    < t d > < % = h p r o j e c t . d e s c % >

    < t d > < % = l i n k _ t o " I t e r a t io n s " , i t e r a t i o ns _ p a t h ( p r o j e c t ) % >

    < td > < % = l i nk _ to " S h ow " , p r o je c t _p a t h ( p ro j ec t ) % >< /t d >

    < t d > < % = l i n k _ t o " E d i t " , e d i t _ p r o j e c t _ p at h ( p r o j e c t ) % >

    < t d > < % = l i n k _ t o " D e s t r oy " , p r o j e c t _p a t h ( p r o j e c t ) ,

    : c on fi rm = > " A re y ou s ur e ?" ,

    : m e t ho d = > : d e l et e % >< /t d >

    < td > < % = l i nk _ to " N ew I t e ra t io n " ,

    n e w _ i t e r a t io n _ p a t h ( p r o j e c t ) % >

    < % end %>

    .. .

    Para el metodo de path utilizaremos new iteration path que genera parael proyecto con id 1 el siguiente HTML:

    l i n k _t o " N e w I t e r a t io n " , n e w _ i t e r a ti o n _ p a t h ( p r o j e c t )

    = >

    < a h r e f = "/ p r o j e c t s / 1 / i t e r a t i o n s / n e w " > N ew i t e ra t i on < / a >

    El enlace lleva a la accion new de IterationsController. La accion recibe el

    valor 1 por medio del parametro project id, que es el identificador del proyecto

  • 7/22/2019 Restful Rails Es

    30/41

    24 CAPITULO 1. RAILS Y REST

    actual. De esta manera el identificador del proyecto esta disponible en la vista

    new de IterationsControllery puede ser usado all por el helper iterations pathresponsable de la creacion del formulario para la nueva iteracion. El formulariogenerado contiene una ruta anidada en el atributo action que contiene el iddel proyecto para el que se debera crear la nueva iteracion:

    Listado 1.12: ontrack/app/views/iterations/new.rhtml

    < % f o rm _ fo r (

    :iteration ,

    : u r l = > i t e ra t i on s _ pa t h ( p a ra m s [ : p ro j ec t _ id ] ) ) d o | f | %>

    .. .

    < % end %>

    = >

    < f o r m a c t i on = " / p r o j e c t s / 1 / i t e r a t i o ns " m e t h od = " p o s t " >

    El uso de params[:project id] en iterations path es opcional porque Railsautomaticamente pone el parametro project id como el atributo action, lo quequiere decir que

    f o r m _ fo r ( : i t e r a t io n , : u r l = > i t e r a t i on s _ p a t h )

    tiene el mismo efecto.El encaminamiento REST asegura que la accion del formulario /projec-

    ts/1/iterations, en combinacion del verbo HTTP POST resulta en la ejecucion

    de la accion create action de IterationsController. El metodo HTTP (met-hod=post) de la etiqueta form fue creado por el helper por defecto, dado queno se especifico ningun verbo HTTP de manera explcita y post es el valor pordefecto.

    Ademas de los parametros del formulario la accion create obtiene el iden-tificador del proyecto por medio del parametro project id de la peticion, porconsiguiente hay que cambiar el metodo de forma que la iteracion recien creadase asigne al proyecto correcto:

    Listado 1.13: ontrack/app/controllers/iterations controller.rb

    1 d ef c r ea t e

    2 @ i t e r a ti o n = I t e r a t io n . n e w ( p a r a m s [ : i t e r a t i on ] )3 @ i t e r a ti o n . p r o j e c t = P r o j e ct . f i n d ( p a r a m s [ : p r o j e c t _ i d ] )45 r e sp o n d_ t o d o | f o r ma t |6 i f @ i t e r a ti o n . s a v e7 f l as h [ : n ot i ce ] = " I t e ra t io n w as s u c ce s s fu l l y c r ea t ed . "8 f o rm a t . h tm l {9 r e d i r e c t_ t o i t e r a t i on _ u r l ( @ i t e r a t i o n . p r oj e c t ,

    10 @iteration)}11 f or ma t .x ml {12 head :created ,13 : l o c a t i o n = > i t e r a t i on _ u r l ( @ i t e r a t i o n . p r oj e c t ,14 @iteration)}15 else

    16 f or ma t . ht ml { r en de r : a ct io n = > " n ew " }

  • 7/22/2019 Restful Rails Es

    31/41

    1.11. RECURSOS ANIDADOS 25

    17 f or ma t . xm l { r en de r : x ml = > @ i te ra ti o n . er ro rs . t o_ xm l }

    18 en d19 en d20 en d

    En la linea 3 se asigna el proyecto explcitamente. Tambien se le ha anadidoel identificador de proyecto al helper iteration url en las lneas 8 y 11.

    Para que el anadir nuevas iteraciones funcione hay que extender los enlaceEdit y Back de la vista show del IterationsController para incluir el identifi-cador del proyecto.

    Listado 1.14: ontrack/app/views/iterations/show.rhtml

    .. .

    < % = l i n k _t o " E d i t " , e d i t _ i t e r a ti o n _ p a t h ( @ i t e r a t i on . p r o j e ct ,

    @ i t e r a ti o n ) %>

    < % = l i nk _ to " B a ck " , i t e ra t i on s _ pa t h ( @ i t er a t io n . p r o je c t ) %>

    Esta vista se genera despues de la creacion de una nueva iteracion y lanzarauna excepcion si no le pasasemos el identificador del proyecto.

    1.11.4. Edicion de las iteraciones

    Para editar iteraciones, hay que hacer dos cambios sobre el codigo genera-

    do. El helper form for en la vista edit del controlador IterationsController solorecibe el id de la iteracion:

    form_for(: iteration ,

    : u r l = > i t e r a t i on _ p a t h ( @ i t e r a t i o n ) ,

    : ht ml = > { : m et ho d = > : p ut }) d o | f |

    sin embargo, hacen falta tanto el identificador de proyecto como el de laiteracion:

    form_for(

    :iteration ,: u r l = > i t e r a t i o n_ p a t h ( p a r a m s [ : p r o j e c t _ id ] , @ i t e r a ti o n ) ,

    : ht ml = > { : m et ho d = > : p ut }) do | f|

    Es necesario un cambio similar en la accion update que se llama desde elformulario el metodo iteration url de la lnea 7 solo recibe el identificadorde la iteracion:

    Listado 1.15: ontrack/app/controllers/iterations controller.rb

    1 d e f u p d a te2 @ i t e r at i o n = I t e r a ti o n . f i n d ( p a r a m s [ : i d ] )3

    4 r e sp o nd _ t o d o | f o r ma t |

  • 7/22/2019 Restful Rails Es

    32/41

    26 CAPITULO 1. RAILS Y REST

    5 i f @ i t e r a ti o n . u p d a t e _ a t t r i b u t es ( p a r a ms [ : i t e r a t i o n ] )

    6 f l as h [ : n o ti c e ] = " I t e ra t io n w as s u cc e s sf u l ly u p da t ed . "7 f o rm a t . h tm l { r e d ir e c t_ t o i t e ra t i on _ u rl ( @ i t e r at i on ) }8 f or ma t .xm l { h ea d : ok }9 else

    10 f or ma t . ht ml { r en de r : a ct io n = > " e di t " }11 f o rm a t . xm l { r e n d er : x m l = > @ i t e r at i on . e r r o rs . t o _ xm l }12 en d13 en d14 en d

    Igual que antes, hay que cambiar la lnea 7:

    f o r m at . h t m l { r e d i r e c t_ t o i t e r a t i on _ u r l ( @ i t e r a t i o n . p r o je c t ,

    @ i t er a ti o n ) }

    Tras todos estos cambios las vistas de create y update y sus acciones de-beran por fin funcionar. Pueden crearse y editarse las iteraciones pero paraestar absolutamente seguros hemos de examinar IterationsControllery sus vis-tas respectivas comprobando todos los helpers de path y URL buscando losque no reciban un identificador de proyecto y cambiandolo como hemos hechocon las vistas anteriores.

    1.12. Definicion de otras acciones

    La entrada resources del fichero de rutas genera rutas y helpers para lasacciones CRUD. Pero como se pueden craer rutas y helpers para otras ac-ciones que tambien pertenezcan al controlador? Por ejemplo veamos la nuevaaccion close de ProjectsController. Esta accion se va a utilizar para cerrar unproyecto, es decir, para marcarlo como finalizado.

    Empezaremos on la migracion de la base de datos:

    > r u b y s c r i pt / g e n e r a t e m i g r a ti o n a d d _ c l o s e d _t o _ p r o j e c t s

    e x i s ts d b / m i g r a t e

    c r e a te d b / m i g r a t e / 0 03 _ a d d _ c l o s e d_ t o _ p r o j e c t s . r b

    Listado 1.16: ontrack/db/migrate/003 add closed to projects.rb

    c l a ss A d d C l o s e d T oP r o j e c t s < A c t i v e Re c o r d : : M i g r a t i o n

    d ef s e lf . u p

    a d d _ c o lu m n : p r o j ec t s , : c l o se d , : b o o l ea n , : d e f a u l t = > f a l s e

    en d

    d e f s e l f . d o wn

    r e m o v e _ co l u m n : p r o j ec t s , : c l o s e d

    en d

    en d

    r a k e d b : m i g r a te

  • 7/22/2019 Restful Rails Es

    33/41

    1.12. DEFINICION DE OTRAS ACCIONES 27

    A continuacion crearemos un enlace close en la vista index de Projects-

    Controller:

    Listado 1.17: ontrack/app/views/projects/index.rhtml

    < % f or p ro je ct i n @ pr o je ct s %>

    < t r i d = " p r o je c t _ < % = p r o j e ct . i d % >" >

    < t d > < % = h p r o j e c t . n a m e % >

    < td > < % = l i nk _ to " S h ow " , p r o je c t _p a t h ( p ro j ec t ) % >

    .. .

    < td > < % = l i nk _ to " C l os e " , < W H I CH _ H EL P E R ? > % >

    < % end %>

    Surgen dos cuestiones a la hora de anadir este enlace:

    1. Que metodo HTTP debera usarse para enviar la accion close?

    2. Como se puede generar un helper que cree la ruta a la acci on close?

    Dado que close no es una accion CRUD estandar, Rails por defecto nosabe que verbo HTTP debera usarse. Close es una accion especializada delproyecto, una especie de actualizacion del registro de un proyecto, as queconforme a los principios REST debera ser enviada con POST.

    Definiremos la ruta y el helper correspondiente en config/routes.rb con laayuda del hash member en la llamada a resources para projects. Este hashconsiste en pares metodo-accion y especifica que accion debe o puede llamarsecon cada verbo HTTP 6.

    Los valores permitidos son :get, :put, :post, :delete y :any. Si una accionaparece marcada con :any, significa que puede llamarse a la accion con cual-quier verbo HTTP. En nuestro ejemplo close debera solicitarse via POST,as que cambiaremos la entrada en resources tal y como se muestra a conti-nuacion:

    ma p . resour ces : pro jec ts , : membe r = > { : cl os e = > : pos t }

    Tras escribir esta entrada ya podemos usar el nuevo helper close project pathpara crear el enlace a Close que mencionabamos antes:

    < t d > < % = l i n k _ t o " C l o se " , c l o s e _ p r o je c t _ p a t h ( p r o j e c t ) % >

    Sin embargo cuando pulsemos el enlace obtendremos un error:

    n o r o ut e f o un d t o m a tc h " / p r oj e ct s / 1 ; c lo s e " w i th { : m e th o d = >: g e t }

    6Rails protege estas rutas con restricciones HTTP, de forma que si se solicita una accion

    con el verbo incorrecto se lanza una excepcion RoutingError.

  • 7/22/2019 Restful Rails Es

    34/41

    28 CAPITULO 1. RAILS Y REST

    La ruta existe, pero la nueva entrada en resources solo permite las peti-

    ciones via POST. Rails rechaza los otros verbos HTTP (como GET, que es elque se ha usado en el enlace anterior). Lo que necesitamos es algo parecido alenlace destroy: un helper que genere un formulario que se enve va POST alservidor. Por suerte, Rails ofrece el helper button to para hacer exactamenteesto.

    < td > < % = b u t t o n _ t o " C l o s e " , c l o s e _ p r o je c t _ p a t h ( p r o j e c t ) % >

    = >

    < f o r m m e t h o d = " p o s t " a c t i on = " / p r o j e c t s / 1 ; c l o s e "

    class="button -to">

    < d iv > < i n p ut t y p e = " s u b m it " v a l ue = " C l o s e " / > < / d iv >

    Lo unico que falta es la accion close en ProjectsController:

    Listado 1.18: ontrack/app/controllers/projects controller.rb

    d ef c l os e

    r e sp o n d_ t o d o | f o r ma t |

    i f P r o j ec t . f i n d ( p a r a m s [ : i d ] ) . u p d a t e _ a t t ri b u t e ( : c l o se d , t r u e )

    f l as h [ : n o ti c e ] = " P r o je c t w as s u c ce s s fu l l y c l os e d . "

    f o rm a t . h tm l { r e d ir e c t_ t o p r o je c t s_ p a th }

    f or ma t .xm l { h ea d : ok }

    else

    f l as h [ : n o ti c e ] = " E r ro r w h il e c l os i ng p r oj e ct . "

    f o rm a t . h tm l { r e d ir e c t_ t o p r o je c t s_ p a th }

    f or ma t .xm l { h ea d 5 00 }

    en d

    en d

    en d

    En la llamada a resources ademas de :member pueden especificarse lasclaves :collection y :new. :collection es necesaria cuando, en lugar de sobre ununico recurso, la accion sea realizada una coleccion de recursos de ese tipoparticular. Un ejemplo es la solicitud de un listado de proyectos como un feedRSS:

    ma p . re sources : pro je cts , : coll ection = > { : rs s = > : ge t }

    - - > G E T / p r o je c ts ; r s s ( m a ps o n to t he # r ss a c ti o n )

    La clave :new se utiliza con acciones que actuan sobre recursos nuevos queaun no han sido almacenados:

    ma p . re sources : pro je cts , : ne w = > { : validate = > : po st }

    - - > P OS T / p r o je c ts / n e w ; v al i da t e ( m a ps o n to t he # v a l id a te a c ti o n )

  • 7/22/2019 Restful Rails Es

    35/41

    1.13. DEFINICION DE NUESTROS PROPIOS FORMATOS 29

    1.12.1. Seguro que no nos repetimos?

    El parrafo anterior suena como una violacion del principio de no repeti-cion: las acciones ya no estan solamente implementadas en el controlador, sinoque tambien aparecen en el fichero de rutas. Como alternativa a los patronesREST descritos arriba se pueden invocar las acciones no REST de la maneratradicional utilizando la accion y el identificador de proyecto:

    < % = l in k_ to " C lo se " , : a ct io n = > " c lo se " , : id = > p ro je ct %>

    Las rutas necesarias para esto deberan seguir estando definidas siempre ycuando no se haya borrado la entrada map.connect :controller/:action/:id enel fichero de rutas. Pero la ruta antigua solo funcionara si no se ha modificado

    la llamada a resources para projects como se describio anteriormente.

    1.13. Definicion de nuestros propios formatos

    El metodo respond to por defecto solo reconoce los siguientes formatos:

    r e sp o n d_ t o d o | w a nt s |

    wants.text

    wants.html

    wants.js

    wants.ics

    wants.xml

    wants.rss

    wants.atom

    wants.yaml

    en d

    Para extender esto podemos registrar nuestros propios formatos como tiposMIME. Supongamos que hemos desarrollado una aplicacion PIM y queremosdevolver las direcciones por medio del microformato vcard format7. Para hacer-lo primero tenemos que registrar el nuevo formato en fichero de configuraci onconfig/environment.rb:

    M i m e : : T y pe . r e g i s t e r " a p p l i c a t i o n / v c a rd " , : v c a r d

    Ahora podemos ampliar la accion show del controlador AddressesContro-ller de forma que pueda devolver direcciones el formato vcard si el cliente losolicita:

    d ef s h ow

    @ a d d r es s = A d d r e ss . f i n d ( p a r a m s [ : i d ] )

    r e sp o nd _ t o d o | f o r ma t |

    f o rm a t . v ca r d { r e nd e r : x ml = > @ a dd r es s . t o _ vc a rd }

    .. .

    7

    http://microformats.org/wiki/hcard

  • 7/22/2019 Restful Rails Es

    36/41

    30 CAPITULO 1. RAILS Y REST

    en d

    en d

    Por supuesto, el metodo to vcard no es un metodo estandar de ActiveRe-cord y deberamos implementarlo cumpliendo la especificacion vcard (RFC2426)Si se implementa correctamente, la llamada a la siguiente URL debera devol-ver una direccion en formato XML conforme a vcard:

    h t t p : / / l o c a l h o s t : 3 0 0 0 / a d d r e s s e s / 1 . v c a r d

    1.14. REST y AJAX

    En cuanto al desarrollo de aplicaciones AJAX basadas en REST no haymuchas novedades. Se pueden usar los helpers asncronos ya conocidos y pasaral parametro :url el metodo de path en lugar de un hash con controlador yaccion. El siguiente fragmento de codigo convierte el enlace destroy de la vistaindex en ProjectsController en un enlace AJAX:

    l i n k_ t o _r e m ot e " D e s tr o y " , : u r l = > p r o je c t _p a t h ( p ro j ec t ) ,

    : m e t ho d = > : d e le t e

    = >

    < a h r e f = " # " o n c l ic k = " n e w A j a x . R e q u es t ( " / p r o j e c t s / 1 " ,

    { a s y n c h r o n o u s : t ru e , e v a l S c ri p t s : t r ue , m e t h od : " d e l e t e " } ) ;

    r e t u rn f a l se ; " > A s y n c D e st r o y < / a >

    Consejo: incluyanse las libreras Javascript necesarias si no se desea pasarun cuarto de hora averiguando por que no funciona el enlace. Una forma dehacerlo es llamar a javascript include tag en el fichero del layout projects.rhtmldel proyecto ProjectsController:

    Listado 1.19: ontrack/app/views/layouts/projects.rhtml

    < % = j a v as c r ip t _ in c l ud e _ ta g : d e f au l ts %>

    .. .

    El enlace lleva a la accion destroy de ProjectsController. Desde el pun-to de vista de la logica de negocio el metodo ya lo hace todo correctamente:elimina el proyecto escogido. Lo que falta es una entrada adicional en el blo-que respond to para devolver al cliente el nuevo formato solicitado, en estecaso Javascript. El siguiente fragmento de codigo muestra la nueva version dedestroy:

    Listado 1.20: ontrack/app/controllers/projects controller.rb

    d e f d e s t r oy

    @ p r o j ec t = P r o j e ct . f i n d ( p a r a m s [ : i d ] )

  • 7/22/2019 Restful Rails Es

    37/41

    1.15. PRUEBAS DEL CODIGO 31

    @project.destroy

    r e s po n d_ t o d o | f o rm a t |

    f o rm a t . h tm l { r e d ir e c t_ t o p r o je c ts _ u rl }

    f or ma t . js # d ef au lt t e mp la te d e st ro y . rj s

    f or ma t .x ml { h ea d : ok }

    en d

    en d

    El unico cambio es la nueva entrada format.js en el bloque respond to.Dado que la nueva entrada no tiene bloque asociado para ejecutar Rails actuade la manera estandar y procesa una plantilla RJS de nombre destroy.rjs:

    Listado 1.21: ontrack/app/views/projects/destroy.rjs

    p a g e . r e m o ve " p r o j e c t _ # { @ p r o j ec t . i d } "

    La plantilla anterior elimina el elemento con el id project ID del arbol DOMdel navegador. Para que esto funcione en la vista index de ProjectsControllerhay que anadir un identificador unico a cada fila:

    Listado 1.22: ontrack/app/views/projects/index.rhtml

    i d = " p r o je c t _ < % = p r o j e ct . i d % >" >

    Esta extension de ProjectsController sirve como ejemplo de como las apli-caciones REST cumplen con el principio DRY y requieren menor cantidad decodigo. Una unica lnea en el controlador hace que la misma accion sea capazde manejar peticiones Javascript!

    Ademas el ejemplo muestra una regla general para el desarrollo de con-troladores REST: implementar la logica fuera del bloque respond to lleva amenos repeticiones en el codigo resultante.

    1.15. Pruebas del codigo

    No importa como de excitante sea el desarrollo REST con Rails, las pruebasde codigo deberan dejarse de lado los tests. Que hemos estado desarrollandodemasiado sin correr nuestros test unitarios sera patente cuando finalmenteejecutemos los tests con rake8:

    > r ak e

    .. .

    Started

    EEEEEEE.......

    8Atencion, si aun no se ha hecho habra que crear la base de datos ontrack test para

    pruebas

  • 7/22/2019 Restful Rails Es

    38/41

    32 CAPITULO 1. RAILS Y REST

    Las buenas noticias son que todas las pruebas unitarias y la prueba funcio-

    nal ProjectsControllerTest siguen funcionando. Las malas noticias: las sietespruebas de IterationsControllerTest estan rotas.

    Si todos los tests de un unico caso de prueba fallan es un claro sntomade que algo fundamental anda mal. En nuestro caso el error es obvio: el casode prueba fue creado por el generador de andamiaje para iteraciones sin unproyecto padre. Extendimos las iteraciones para hacerlas pertenecer a un pro-yecto cuando anadimos toda la funcionalidad en IterationsController y ahoratodas las acciones esperan el parametro anadido :project id. Para arreglarloextenderemos el hash de la peticion en todos los metodos de prueba con elparametro project id. Por ejemplo, veamos el test test should get edit:

    Listado 1.23: ontrack/test/functional/iterations controller test.rbd e f t e s t _ s h o u ld _ g e t _ e d i t

    g et : e di t , : id = > 1 , : p r oj ec t_ i d = > p ro je ct s ( : on e )

    a s s e r t _ r es p o n s e : s u c c e s s

    en d

    Adicionalmente, el controlador IterationsControllerTest debe tabien crearlos datos de test de projects:

    f i x t u re s : i t e r a ti o n s , : p r o j e c t s

    Tras estos cambios solo nos quedaran por pasar los tests test should create iteration

    y test should update iteration. En ambos casos la razon es que hay un as-sert redirected to equivocado:

    a s s e r t _ r e di r e c t e d _ t o i t e r a t i o n_ p a t h ( a s s i g n s ( : i t e r a t i on ) )

    Lo que pasa es obvio: hemos cambiado todas las redirecciones en Iterations-Controller de forma que el primer parametro es el identificador de proyecto.El aserto solo comprueba si hay un identificador de iteracion en la redireccion.En este caso, el controlador esta bien y tenemos que adaptar el test:

    a s s e r t _ r e di r e c t e d _ t o i t e r a t i o n_ p a t h ( p r o j e c t s ( : o n e ) ,

    a s s i g n s ( : i t e r a t i o n ) )

    Por cierto: el uso de metodos de path en los asertos de redireccion es launica diferencia entre las pruebas funcionales REST y las pruebas funcionalestradicionales.

    1.16. Clientes REST: ActiveResource

    Suele mencionarse con frecuencia ActiveResource junto con REST. Acti-veResource es una librera Rails para el desarrollo de clientes de servicio webbasados en REST, tales clientes utilizan los cuatro verbos HTTP tpicos para

    comunicarse con el servidor.

  • 7/22/2019 Restful Rails Es

    39/41

    1.16. CLIENTES REST: ACTIVERESOURCE 33

    ActiveResource no es parte de Rails 1.2 pero esta disponible en la rama de

    desarrollo y puede instalarse usando svn9

    :

    > c d o n tr a ck / v e n do r

    > m v r a il s r ai ls - 1 .2

    > s vn c o h t tp : / / d ev . r u b y on r a il s . o rg / s v n / r ai l s / t ru n k r a il s

    ActiveResource abstrae los recursos web desde el punto de vista del clientecomo clases que heredan de ActiveResource::Base. Por ejemplo modelaremos elrecurso Project (con el que trabajabamos en el lado del servidor anteriormente)como sigue:

    r e q u ir e " a c t i v e r e s o u r ce / l i b / a c t i v e _ r e s o u r c e "

    c l as s P r oj e ct < A c t iv e R es o u rc e : : B as e

    s e l f . s i te = " h t t p : / / l o c a l ho s t : 3 0 0 0 "

    en d

    Se importa de manera explcita la librera ActiveResource. Adicionalmentese especifica la URL del servicio en la variable de clase site. La clase Projectabstrae la parte de cliente del servicio tan bien que el programador tiene la im-presion que esta trabajando con una clase ActiveRecord normal. Por ejemploeste metodo find solicita un recurso con un identificador dado al servidor:

    w u nd e r lo o p = P r oj e ct . f i nd 1

    p u t s w u n d e r lo o p . n a m e

    La llamada a find ejecuta una peticion REST con el verbo GET:

    G E T / p r o j e ct s / 1 . x m l

    El servidor devuelve la respuesta en XML. El cliente genera, a partir delXML, un objeto ActiveResource wunderloop que ofrece como un modelo Ac-tiveRecord metodos para acceder a todos sus atributos. Pero, como se hacepara modificar un recurso?

    w u nd e r lo o p . n am e = " W u n d er l oo p C o nn e ct "wunderloop.save

    La llamada a save convierte el recurso a XML y lo enva por medio dePUT al servidor:

    P U T / p r o j e ct s / 1 . x m l

    Si cogemos el navegador web y recargamos el listado de proyectos, veremosque el proyecto modificado debera aparecer con su nuevo nombre.

    Crear nuevos recursos es tan facil como recuperarlos y modificarlos:

    9

    http://subversion.tigris.org/

  • 7/22/2019 Restful Rails Es

    40/41

    34 CAPITULO 1. RAILS Y REST

    b e l ly b u tt o n = P r oj e ct . n e w (: n a me = > " B e l l yb u t to n " )

    bellybutton.save

    El nuevo proyecto se transmite al servidor en XML por medio de POST yse almacena en la base de datos:

    P O S T / p r o j e ct s . x m l

    Si ve vuelve a cargar el listado de proyectos en el navegador aparecera elproyecto recien creado. La ultima de las cuatro operaciones CRUD que tene-mos que repasar es el borrado de proyectos:

    b e l l y b u t t o n . d e s t r o y

    La invocacion de destroy se transmite con DELETE y hace que se borreel proyecto en el servidor:

    D E L E TE / p r o j e c t s / 2 . x m l

    ActiveResource utiliza los cuatro verbos HTTP al estilo REST, ofrecien-do una abstraccion muy buena de los recursos REST en el lado del cliente.Ademas muchos de los metodos ya conocidos de ActiveRecord funcionan conActiveResource, tales como encontrar las instancias de un recurso:

    P r o j e ct . f i n d ( : a l l ) . e a c h d o | p |

    p u ts p . n am e

    en d

    Creemos que ActiveResource proporciona una muy buena base para eldesarrollo de sistemas debilmente acoplados en Ruby. Es una buena idea echarun vistazo en la rama trunk y experimentar con las clases basicas de Active-Resource.

    1.17. Conclusiones

    No hay por que aplicar REST a rajatabla: las soluciones hbridas son masfaciles de implementar, y por lo general uno esta en mitad de un proyectocuando aparecen nuevas funcionalidades en Rails. En este caso no es ningunproblema desarrollar modelos REST sencillos y sus controladores para adquirirexperiencia. Por el contrario, si se empieza una aplicacion desde cero es mejorplantearse desarrollarla en torno a REST desde el principio. Las ventajas sonclaras: una arquitectura limpia, menos codigo y capacidad multicliente.

  • 7/22/2019 Restful Rails Es

    41/41

    Bibliografa

    [1] Ralf Wirdemann, Thomas Baustert: Rapid Web Development mit Rubyon Rails, 2. Auflage, Hanser, 2007

    [2] Dave Thomas, David Heinemeier Hansson: Agile Web Development withRails, Second Edition, Pragmatic Bookshelf, 2006

    [3] Curt Hibbs: Rolling with Ruby on Rails Part 1,http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html

    [4] Curt Hibbs: Rolling with Ruby on Rails Part 2,http://www.onlamp.com/pub/a/onlamp/2005/03/03/rails.html

    [5] Amy Hoy: Really Getting Started in Rails,http://www.slash7.com/articles/2005/01/24/really-getting-started-in-rails.html

    [6] Roy Fielding: Architectural Styles and the Design of Network-based Soft-ware Architectures,http://www.ics.uci.edu/ fielding/pubs/dissertation/top.htm