• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Rails intro
 

Rails intro

on

  • 1,159 views

Diapositivas de la introducción al lenguaje ruby en el curso de extensión universitaria "Desarrollo Web Avanzado" del programa de Extensión Universitaria de la Universidad de Oviedo (2010)

Diapositivas de la introducción al lenguaje ruby en el curso de extensión universitaria "Desarrollo Web Avanzado" del programa de Extensión Universitaria de la Universidad de Oviedo (2010)

Statistics

Views

Total Views
1,159
Views on SlideShare
1,149
Embed Views
10

Actions

Likes
0
Downloads
24
Comments
0

2 Embeds 10

http://www.linkedin.com 8
http://coderwall.com 2

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • DRY Las responsabilidades se definen en un sitio, en el resto de la aplicación se generan automáticamente mediante metaprogramación. Esto permite que si hay un cambio en el lugar donde se define dicha responsabilidad, los demás lugares permanecerán sincronizados.\n\nConvention Over Configuration es otro principio que guarda relación con lo anterior. Imaginemos dos subsistemas dentro de nuestra aplicación, por ejemplo la capa de modelo donde se definen las entidades y la capa de persistencia. Cuando nuestro modelo tenga que ser recuperado de la base de datos, se sabrá qué columnas de qué tabla contienen los valores de los atributos que hay que cargar en el modelo. Ésto se debe a que se sigue una convención de nombrado. Por ejemplo, si tenemos una entidad persona en el modelo, El sistema lo almacenará por omisión en una tabla PERSONAS en la base de datos. Si la convención no nos gusta, lo cambiaremos mediante configuración, por ejemplo indicando en qué tabla de la base de datos queremos almacenar las entidades Persona. Esto nos permite un mayor grado de integración con sistemas legacy.\n
  • A diferencia de Struts, se define un controlador para la interacción con cada modelo.\n
  • \n
  • A diferencia de Struts, se define un controlador para la interacción con cada modelo.\n
  • Crear una aplicación de rails, y ver la estructura de directorios.\n
  • estructura de directorios: comentar.\n
  • ¿Qué acabamos de crear? Acabamos de crear un proyecto rails. Todos los proyectos rails tienen una estructura similar, necesaria para ser reconocida como aplicación y que ésta funcione correctamente.\nPor el momento nos interesan los directorios app y script, aunque iremos viendo todos mas adelante.\nApp contiene la mayor parte del código de nuestra aplicación (salvo los recursos estáticos tales como css que irán en public) y script contiene una serie de escripts escritos en ruby, que nos permitirán generar componentes de la aplicaición, arrancar servidores de pruebas, instalar scripts, etc.\n
  • ¿Qué acabamos de crear? Acabamos de crear un proyecto rails. Todos los proyectos rails tienen una estructura similar, necesaria para ser reconocida como aplicación y que ésta funcione correctamente.\nPor el momento nos interesan los directorios app y script, aunque iremos viendo todos mas adelante.\nApp contiene la mayor parte del código de nuestra aplicación (salvo los recursos estáticos tales como css que irán en public) y script contiene una serie de escripts escritos en ruby, que nos permitirán generar componentes de la aplicaición, arrancar servidores de pruebas, instalar scripts, etc.\n
  • ¿Qué acabamos de crear? Acabamos de crear un proyecto rails. Todos los proyectos rails tienen una estructura similar, necesaria para ser reconocida como aplicación y que ésta funcione correctamente.\nPor el momento nos interesan los directorios app y script, aunque iremos viendo todos mas adelante.\nApp contiene la mayor parte del código de nuestra aplicación (salvo los recursos estáticos tales como css que irán en public) y script contiene una serie de escripts escritos en ruby, que nos permitirán generar componentes de la aplicaición, arrancar servidores de pruebas, instalar scripts, etc.\n
  • ¿Qué acabamos de crear? Acabamos de crear un proyecto rails. Todos los proyectos rails tienen una estructura similar, necesaria para ser reconocida como aplicación y que ésta funcione correctamente.\nPor el momento nos interesan los directorios app y script, aunque iremos viendo todos mas adelante.\nApp contiene la mayor parte del código de nuestra aplicación (salvo los recursos estáticos tales como css que irán en public) y script contiene una serie de escripts escritos en ruby, que nos permitirán generar componentes de la aplicaición, arrancar servidores de pruebas, instalar scripts, etc.\n
  • \n
  • Comentar como es el control flow:\nCuando se invoca una url llega al componente de enrutado que se configura a través del fichero config/routes.rb. Éste determina que controlador tiene que despachar la petición y dentro de él qué método. Los métodos de un controlador se llaman acciones. En una acción, se procesa un conjunto de datos (el modelo) y tras su finalización se redirige a una vista donde se presentarán esos datos bien en HTML, en XML o en cualquier otro formato.\n\n[Ver el código del controlador, ver que hereda de application controller, que es el controlador base de todos los controladores de la aplicación y ver su código.]\n\nCreamos una acción hola en el controlador, e invoquémosla.\n
  • Por omisión, rails usa la siguiente convención a la hora de invocar acciones de los controladores. Lo siguiente que va después del dominio y path de la aplicación (en nuestro caso es el raiz) es el nombre del controlador. y separado por una barra, el identificador de la acción.\n\nAl invocar la acción, vemos que nos aparece un error porque no se encuentra la vista por omisión.\n\nCreamos la vista.\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Enseñar la migración: Clases que crean la estructura de la base de datos (y en caso necesario los propios datos) y que permiten desarrollar de forma incremental la aplicación. Cuando se ejecuta una migración, estas tienen un timestamp y se aplican en cascada. se puede hacer un rollback volviendo a un estado anterior, cuando esto ocurre, se ejecuta el método down.\n\nCada vez que se crea una migración hay que ejecutar rake db:migrate. Y explicar que es rake y los rakefiles.\n\nAnatomía del controlador. Las acciones y los respond, ver cómo se relaciona eso con routes.rb, que añadió un map.resources :products indicando que la entidad producto es un recurso REST y que por tanto las acciones siguen ese modelo de arquitectura.\n\nEnseñar las vistas y ver como heredan del layout con el mismo nombre, o de application.html.rb si no existe éste.\n\nVer la jerarquía de tests.\n
  • \n
  • \n
  • \n
  • Explicar el helper cycle, y el helper truncate.\nExplicar que dentro de truncate quitan los tags con el gsub.\nExplicar como funciona link_to y las URLs REST.\nExplicar que el link_to de show y el link_to de Destroy apuntan a la misma url, determinada por product, pero que en destroy, al pasar :method, estamos siendo REST compliant y se dirige a una acción distinta dentro del controlador.\n
  • \n
  • \n
  • \n
  • Comentar la herencia de layout. application.html.rb\ny store.index.html.rb\ncomentar como funciona yield y content_for\n\n
  • \n
  • Comprobamos al clicar que no existe la acción add_to_cart definida en el controlador.\n\nAntes de crear el carrito, veamos cómo mantener el estado en nuestra aplicación.\n
  • Comentar que el objeto session es persistente, ya que si residiese en memoria, con una carga de usuarios elevada, podría mermar el rendimiento de la aplicación incluso denegar el servicio.\n\nSi la carga de usuarios crece, y tenemos que escalar horizontalmente (es decir, meter más máquinas) nada garantizaría que diferentes peticiones del mismo usuario lleguen a la misma máquina, y se poducirían inconsistencias (ejemplo de la compra) es por ello que conviene usar persistencia de sesión distribuida. Por ejemplo en base de datos.\n\n[Comentar que DRB es un protocolo para compartir objetos entre procesos ruby]\n\n
  • Si observamos el código de la migración veremos que lo que se persiste es el identificador de sesión y los datos de la sesión como texto. Esto es porque el contenido de la sesión es serializado a YML, que es un formato textual (el equivalente a JSON de ruby) por tanto sólo se podrá guardar en sesión datos que sean serializables. (Un objeto file, por ejemplo, no lo es).\n
  • \n
  • \n
  • Enseñar cómo se haría con partials\n\n "cart_item", :collection => @cart.items) %>\n\n × \n\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Rails intro Rails intro Presentation Transcript

  • DESARROLLO WEB AVANZADODesarrollo rápido con Ruby on Rails Miguel Fernández Fernández
  • Introducción a Ruby On Rails http://rubyonrails.org/
  • Un poco de Historia • David Heinemeier Hansson ( 37 signals ) 2004 (1.0) • Agosto 2006 Apple anuncia su inclusión en Mac OSX 10.5 (v1.2.3) • Última versión estable 2.3.5 • v3.0.0 en preview release (Fusión con Merb)
  • Filosofía• Full stack - Da soporte íntegro al desarrollo Web.• Siguelos principios Convention over Configuration (CoC) y Don’t Repeat Yourself (DRY) (se sirve de las capacidades reflectivas del ruby para esto).
  • Visión arquitectónica (MVC) M ODELS , V IEWS , AND C ONTROLLERS 25 !12*(.%&*1%&)0%1*&34&%# "1()#*(++&*1-)#&*"5#%1.-#617(0&+ #1()#*(++&*1-)8(9&%18-&. ! ()#*(++&* $1,-&.1*&)0&*%1)&:#1$*(.%&*1%5*&&) $ # " ,-&. /(0&+ !"#"$"%& M ODELS , V IEWS , AND C ONTROLLERS 26 ! B2/#;:C Figure 2.1: The Model-View-Controller Architecture !(##)*++,-./01+%#20&+"334#245"0#+678 " "B2/#;:CF;:3%A#20&52:#0211&0 #92:#0211&0;:#&0"5#%<;#(,23&1 $92:#0211&0;:=2>&%=;&< be a view that displays product information on a catalog page and another set A#20& %&?;&<0&:3&0%:&@#$02<%&0%50&&: of views used by administrators to add and edit products. 92:#0211&0 Controllers orchestrate $ application. Controllers receive events from the % the # outside world (normally user input), interact with the model, and display an appropriate view to the user. !;%)1"- D5#;=& This triumvirate—the model, view, and controller—together form an architec- !"#"$"%& 9"0# B&5203 ture known as MVC. Figure 2.1 shows MVC in abstract terms. ?;&< E23&1 MVC was originally intended for conventional GUI applications, where devel- opers found the separation of concerns led to far less coupling, which in turn Figure 2.2: Rails and MVC
  • Visión arquitectónica (vista dinámica)
  • Visión arquitectónica (componentes)Ruby on rails Core Active resource Action pack Active support plugin plugin Action controller Action mailer ... Action view Active record Action webservice
  • Instalación de rails• instalemos rails y todas sus dependencias: • $ sudo apt-get install subversion mysql-server-5.0 mysql-admin libsqlite3-ruby1.8 openjdk-6-jdk • $ sudo apt-get install ruby-full rubygems libmysql-ruby • $ echo "gem: --http-proxy=http://proxy.uniovi.es: 8888" > ~/.gemrc && sudo gem install rails • $ echo "export PATH=$PATH:/var/lib/gems/1.8/bin" >> ~/.bashrc && source ~/.bashrc• instalemos netbeans 6.8 ruby. Nos facilitará la vida.
  • Rails.new (nuestra primera app)$ cd && mkdir workspace && cd workspace~/workspace$ rails holamundo create create app/controllers create app/helpers create app/models create app/views/layouts create config/environments create config/initializers create config/locales create db ...
  • Estructura de un proyecto rails
  • Estructura de un proyecto rails
  • Estructura de un proyecto rails
  • Arrancar WebRick
  • URLs, rutas, controladores y accionesPara escribir nuestra primera aplicación dinámica, tenemosque definir un controlador y una vista. http://railsapi.com/doc/rails-v2.3.5/
  • Invocando a una acción del controlador http://127.0.0.1:3000/saludador/hola aplicación controlador acciónLa convención dice que tras invocar una acción, se redirigirá a la vista controlador/accion dentro del directorio views...
  • Completando la plantilla• Lasplantillas html se definen en un lenguaje llamado ERB. Muy similar a otros lenguajes de plantillas, como JSP.• <% expresión %> encierran expresiones ruby• <%= expresión %> el resultado de su evaluación se inyecta en el html de salida.• Lasvariables de instancia definidas en los controladores están disponibles en la plantilla aun siendo privadas (introspección).• Los métodos definidos en app/helpers/controlador también están disponibles en la plantilla.
  • Completando la plantilla
  • Desarrollo incremental e iterativo• Crearemos una tienda on-line de forma incremental• Abordaremos el desarrollo de un aspecto funcional en cada iteración• Alfinal de cada iteración tendremos algo que funciona.
  • It0 - Creación de la aplicación• Hemos visto como crear una aplicación: rails app_name• Para seguir el ritmo usaremos subversion, al final de cada iteración, actualizaremos a la revisión finalizada.• Inicialmente hacemos un checkout de la versión inicial. • workspace$ svn co file:///home/${USUARIO}/svnrepos/ skateshop/tags/it0 skateshop• Abrimos con netbeans la aplicación.
  • Some folks like to mock up web application page flows using Photoshop, Word,¿En qué consiste? Compradoror (shudder) HTML. I like using a pencil and paper. It’s quicker, and the cus-tomer gets to play too, grabbing the pencil and scribbling alterations right onthe paper.
  • ¿En qué consiste? Vendedor W HAT D EPOT D OES 66 Figure 5.2: Flow of Seller Pages
  • It1. Gestionar los productos• En esta iteración nos encargaremos del alta, baja y modificación de los productos a vender.• Tareas: • A) Preparar las bases de datos (MySQL o SQLite3) • B) Crear el modelo, el controlador y vistas de mantenimento (scaffolding) • C) Añadir nuevos campos • D) Añadir validaciones • E) Darle “un toque” de estilo
  • It1. B) Scaffoldingskateshop$ script/generate scaffold producttitle:string description:text image_url:string • el controlador: products_controller.rb (con acciones de mantenimiento) • las vistas de mantenimiento: una por cada acción (salvo create) y layout común layouts/products.html.erb • el modelo: products.rb y su migración inicial • una ruta nueva en routes.rb • un helper: products_helper.rb • tests (unitarios y funcionales)
  • It1. C) Añadiendo nuevos camposskateshop$ script/generate migrationadd_price_to_product price:decimal class AddPriceToProduct < ActiveRecord::Migration def self.up El nombre importa! si la add_column :products, :price, :decimal, migración empieza por :precision=>8, :scale=>2, :default=>0 create, creará una tabla, si end empieza por add, añadirá def self.down una columna. remove_column :products, :price end endskateshop$ rake db:migrate Es preciso actualizar las vistas, ya que el scaffolding no es dinámico (desde rails 2)
  • It1. D) Añadiendo validaciones Un producto tiene que cumplir que tiene un título, y que no haya más productos con el mismo; una descripción y una url válida para la imagen. Además tenemos que comprobar que el precio es positivo. class Product < ActiveRecord::Base validates_presence_of :title, :description, :image_url validates_uniqueness_of :title validates_numericality_of :price validate :precio_tiene_que_ser_por_lo_menos_un_centimo, :url_tiene_que_ser_una_imagen private def precio_tiene_que_ser_por_lo_menos_un_centimo errors.add(:price, "tiene que ser por lo menos un centimo") unless price >= 0.01 end def url_tiene_que_ser_una_imagen unless /.(gif|jpg|png)$/i === image_url errors.add(:url,"tiene que ser una url para gif, jpg o png") end end endhttp://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html
  • It1. E) Dandole un toque de estiloNecesitamos datos de prueba que se generen de formaautomática. Instalamos random_data y decimos a rails que lause skateshop$ sudo gem install random_dataCreamos una migración que cargue los datos class AddTestData < ActiveRecord::Migration def self.up Product.delete_all images=["tabla.jpg","pantalones.jpg","camiseta.jpg","zapatillas.jpg","gorra.jpg"] images.each do |image| p=Product.new :title=> p.title=image.gsub(".jpg"," ").capitalize p.description=Random.paragraphs(2) p.image_url="./"+image p.price=Random.number(100) p.save end end def self.down Products.delete_all end end
  • It1. E) Dandole un toque de estiloEl listado scaffolded no se adecua a cómo queremos que sevisualicen los datos. Modifiquémoslo y añadamos una hojade estilos <div id="product-list"> <h1>Listing products</h1> <table cellpadding="5" cellspacing="0"> <% for product in @products %> <tr valign="top" class="<%= cycle(par, impar) %>"> <td> <%= image_tag product.image_url, :class => list-image %> </td> <td width="60%"> <span class="list-title"><%=hproduct.title %></span><br /> <%=h truncate(product.description.gsub(/<.*?>/,), 80) %> </td> <td class="list-actions"> <%= link_to Show, product %> <%= link_to Edit, edit_product_path(product) %> <%= link_to Destroy, product, :confirm => "Seguro?", :method=>:delete %> </td> </tr> <% end %> </table> </div>
  • It 2. Confeccionar el catálogo• En esta iteración nos encargaremos de confeccionar el catálogo, creando un controlador y un conjunto de vistas personalizadas. Veremos cómo usar helpers y disparar acciones desde la vista.,• Tareas: • A) Crear el catálogo • B) Diseñar el layout
  • It2 A) Crear el catálogo• El catálogo se mostrará en la home del sitio. class Product < ActiveRecord::Base def self.method_missing sym, args=nil • generamos el controlador store con la pattern=/find_sorted_by_/i if sym.to_s =~ pattern acción index (desde Netbeans para find :all, :order=> variar) sym.to_s.gsub(pattern,"").to_sym else super.method_missing(sym, *args) • modificamos routes.rb para indicar que end end el home es la acción index del #resto de la clase controlador y borrar el fichero end index.html. [check] class StoreController < ApplicationController • En la acción del controlador recuperamos def index todos los productos, para pasarlos a la vista. @products=Product.find_sorted_by_title Lo haremos à-la rails: mediante reflexión end computacional. end
  • It2 A) Crear el catálogo <h1>Product Catalog</h1> <div id="product-catalog"> <% @products.each do |product| %> <div class="product <%=cycle("even","odd")%>"> <div id="product-image"> <%= image_tag product.image_url, :alt=>product.title%> </div>• La vista mostrará el <div id="product-description"> catálogo en forma de <h3 class="product-title"><%=h product.title %></h3> listado <p class="product-description"><%=h truncate(product.description,200,"...") %></p> <span class="price"><%=h product.price%></span> </div> </div> <% end %> </div> <% content_for :extra do %> Powered by Ruby On Rails <%end%>
  • It2 B) Diseñar el layout <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1- transitional.dtd"> <html> <head> <title>Skateshop <%= @page_title && ":: "+@page_title %> </title> <%= stylesheet_link_tag "shop", :media => "all" %></head>• La web necesita de un <body id="store"> diseño consistente <div id="banner"> <%= image_tag("skate_logo.png") %> <%= @page_title || "Skateshop" %>• Debemos de crear un <span id="extra"><%= yield :extra %></span> </div> layout (una plantilla) cuyo <div id="columns"> contenido variará en <div id="side"> función de la vista concreta <a href="http://www....">Home</a><br /> <a href="http://www..../faq">Questions</a><br /> que se esté renderizando. <a href="http://www..../news">News</a><br /> <a href="http://www..../contact">Contact</a><br /> </div> <div id="main"> <%= yield :layout %> </div> </div> </body> </html>
  • It 3. Crear el carrito• En esta iteración veremos cómo gestionar sesiones desde el framework, haciéndolas persistentes. Aplicaremos lo aprendido a la creación de un carrito de la compra. Tareas • A) Añadir productos al carrito • B) Configurar la gestión de Sesiones • C) Confeccionar el carrito • D) Gestionar errores
  • It3 A) Añadir productos al carritoQueremos poder añadir cada producto del catálogo alcarrito.Podemos usar el built-in helper button_to(value,args),similar a link_to<%= button_to "Add to Cart", :action => :add_to_cart, :id => product %>Los helpers built-in que pueden ser usados en las vistasestán definidos en las clasesActionView::Helpers::*Helper
  • It 3. Gestión de sesiones• HTTP es stateless, pero se usan mecanismos. Para simular estados se usan mecanismos como URL rewriting, hidden input fields y cookies.• Rails usa cookies para identificar diferentes peticiones asociadas a la misma sesión de navegación.• El objeto session nos abstrae de este mecanismo (se comporta como un hash).• Por defecto session persiste en disco. Pero hay otros mecanismos: persistencia en memoria, en base de datos, DRb...
  • It 3 B). Configurar la gestión de sesionesUsaremos persistencia de sesiones en base de datos.Rails ofrece una tarea rake para esto. ~/skateshop$ rake db:sessions:create && rake db:migrateAdemás tendremos que indicar en config/environment.rbque queremos usar este tipo de persistencia, ya que eltipo por omisión es en ficheros de texto en disco. config.action_controller.session_store = :active_record_storeLos cambios en otros directorios distintos de app y publicrequieren reiniciar el servidor. Reiniciamos
  • It3 C) Confeccionar el carritoNecesitamos definir una acción en el controlador para obtener el carrito desesión y añadirle productos. class StoreController < ApplicationController def index @products=Product.find_sorted_by_title end def add_to_cart @cart=find_cart @cart.add_product Product.find(params[:id]) end def empty_cart session[:cart]=nil flash[:notice]="Your car is empty" redirect_to :action => :index end private def find_cart session[:cart] ||= Cart.new end end
  • It3 C) Confeccionar el carrito Y definir la propia clase carrito, que es un almacén de productos.class Cart class CartItem attr_reader :product, :quantity attr_reader :items def initialize(product) def initialize @product=product @items=[] @quantity=1 end end def add_product(product) def title item = items.find { |item| item.title==product.title } product.title if item end item.increment_quantity else def price @items << CartItem.new(product) product.price * quantity end end end def increment_quantity def total_price @quantity+=1 @items.sum{ |item| item.price } end end endend
  • It3 C) Confeccionar el carrito Además habrá que definir una vista que nos muestre el carrito.<div class="cart-title">Your Cart</div><table> <% for item in @cart.items %> <tr> <td><%= item.quantity %>&times;</td> <td><%=h item.title %></td> <td class="item-price"><%= en_euros(item.price) %></td> </tr> <% end %> <tr class="total-line"> <td colspan="2">Total</td> <td class="total-cell"><%= en_euros(@cart.total_price) %></td> </tr></table><%= button_to "Empty cart", :action => :empty_cart %>
  • It3 D) Gestionar Errores Echemos un vistazo a los últimos mapeos de routes.rb map.connect :controller/:action/:idAutomáticamente lo que va después de la acción se mapea alparámetro id. http://localhost:3000/store/add_to_cart/fake Couldnt find Product with ID=fake def add_to_cart @cart=find_cart begin @cart.add_product Product.find(params[:id]) rescue ActiveRecord::RecordNotFound => e logger.error("Se intentó acceder al producto con id=#{params[:id]}") flash[:notice]="Oooops, we couldt process your request" redirect_to :action=>:index end end
  • It4. Una pizca de AJAX• En esta iteración aprenderemos a usar renderizado parcial de vistas, a actualizar dinámicamente la página con AJAX, y a manipuilar el DOM.• Tareas: • A) Refactorizar el carrito • B) Carrito basado en AJAX • C) Resaltar los cambios • D) Ocultar el carrito cuando está vacío • E) Hacer que el carrito funcione cuando Javascript está deshabilitado
  • It5. Gestionar la compra• En esta iteración aprenderemos a conectar tablas del modelo con claves ajenas. Usar las relaciones belongs_to y has_many. A crear formularios basados en modelos y a conectar dichos furmularios, con los modelos y las vistas.• Tareas: • A) Caputurar una orden de compra
  • It6. Gestionar los usuarios• En esta iteración aprenderemos a añadir autenticación a una sesión de usuario, a usar transacciones y crear un hook que añade nueva funcionalidad a ActiveRecord• Tareas: • A) Añadir Usuarios • B) Autenticación • C) Controlar el acceso
  • Posibles prácticas• Notable • Crear una pequeña aplicación de gestión básica. • Añadir funcionalidad de subscripción y envío de newsletters a la aplicación existente (http://guides.rubyonrails.org/action_mailer_basics.html) • Añadir cualquier funcionalidad no trivial a la aplicación mediante plugins: (eg. paginación y búsqueda en vistas de listados)• Sobresaliente • Instalar los frameworks de pruebas BDD Rspec y Cucumber y diseñar e implementar un caso de uso dirigido por la prueba. • Crear un plugin de rails (http://guides.rubyonrails.org/plugins.html)
  • Referencias• http://guides.rubyonrails.org/• http://railsapi.com/doc/rails-v2.3.5/• http://www.erikveen.dds.nl/distributingrubyapplications/rails.html• Agile Web Development with Rails, Third Edition (The Pragmatic Bookshelf)• The Rails Way (Addison-Wesley Professional)• Deploying Rails Applications: A Step-By-Step Guide (The Pragmatic Bookshelf)• Rails Cookbook (O`reilly)• Behaviour driven development with RSpec, Cucumber and Friends (The Pragmatic Bookshelf)
  • Graciasmiguelff@innova.uniovi.es