• Like
  • Save

Loading…

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

Ruby On Rails Intro

  • 3,112 views
Uploaded on

Diapositivas correspondientes a la parte del framework Ruby On Rails del curso de extensión universitaria "Desarrollo Web Avanzado", celebrado en la Escuela Universitaria de Ingeniería Informática de …

Diapositivas correspondientes a la parte del framework Ruby On Rails del curso de extensión universitaria "Desarrollo Web Avanzado", celebrado en la Escuela Universitaria de Ingeniería Informática de Oviedo

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
3,112
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
0
Comments
0
Likes
7

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. DESARROLLO WEB AVANZADO Desarrollo rápido con Ruby on Rails Miguel Fernández Fernández miguel@ThirdWay.es
  • 2. Introducción a Ruby On Rails http://rubyonrails.org/
  • 3. 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)
  • 4. 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).
  • 5. 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/#;:C'F;: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
  • 6. Visión arquitectónica (vista dinámica)
  • 7. 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
  • 8. 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.
  • 9. 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 ...
  • 10. Estructura de un proyecto rails
  • 11. Estructura de un proyecto rails
  • 12. Estructura de un proyecto rails
  • 13. Arrancar WebRick
  • 14. URLs, rutas, controladores y acciones Para escribir nuestra primera aplicación dinámica, tenemos que definir un controlador y una vista. http://railsapi.com/doc/rails-v2.3.5/
  • 15. Invocando a una acción del controlador http://127.0.0.1:3000/saludador/hola aplicación controlador acción La convención dice que tras invocar una acción, se redirigirá a la vista controlador/accion dentro del directorio views...
  • 16. 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.
  • 17. Completando la plantilla
  • 18. 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.
  • 19. 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.
  • 20. Some folks like to mock up web application page flows using Photoshop, Word, ¿En qué consiste? Comprador or (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 on the paper.
  • 21. ¿En qué consiste? Vendedor W HAT D EPOT D OES 66 Figure 5.2: Flow of Seller Pages
  • 22. 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
  • 23. It1. B) Scaffolding skateshop$ script/generate scaffold product title: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)
  • 24. It1. C) Añadiendo nuevos campos skateshop$ script/generate migration add_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 end skateshop$ rake db:migrate Es preciso actualizar las vistas, ya que el scaffolding no es dinámico (desde rails 2)
  • 25. 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 end http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html
  • 26. It1. E) Dandole un toque de estilo Necesitamos datos de prueba que se generen de forma automática. Instalamos random_data y decimos a rails que la use skateshop$ sudo gem install random_data Creamos 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
  • 27. It1. E) Dandole un toque de estilo El listado scaffolded no se adecua a cómo queremos que se visualicen los datos. Modifiquémoslo y añadamos una hoja de 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>
  • 28. 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
  • 29. 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=> sym.to_s.gsub variar) (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
  • 30. 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%>
  • 31. 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>
  • 32. 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
  • 33. It3 A) Añadir productos al carrito Queremos poder añadir cada producto del catálogo al carrito. 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 vistas están definidos en las clases ActionView::Helpers::*Helper
  • 34. 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...
  • 35. It 3 B). Configurar la gestión de sesiones Usaremos persistencia de sesiones en base de datos. Rails ofrece una tarea rake para esto. ~/skateshop$ rake db:sessions:create && rake db:migrate Además tendremos que indicar en config/environment.rb que queremos usar este tipo de persistencia, ya que el tipo por omisión es en ficheros de texto en disco. config.action_controller.session_store = :active_record_store Los cambios en otros directorios distintos de app y public requieren reiniciar el servidor. Reiniciamos
  • 36. It3 C) Confeccionar el carrito Necesitamos definir una acción en el controlador para obtener el carrito de sesió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
  • 37. 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 end end
  • 38. 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 %>
  • 39. It3 D) Gestionar Errores Echemos un vistazo a los últimos mapeos de routes.rb map.connect ':controller/:action/:id' Automáticamente lo que va después de la acción se mapea al parámetro id. http://localhost:3000/store/add_to_cart/fake Couldn't 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 could't process your request" redirect_to :action=>:index end end
  • 40. 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
  • 41. 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
  • 42. 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
  • 43. 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)
  • 44. 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)
  • 45. Gracias
  • 46. DESARROLLO WEB AVANZADO Desarrollo rápido con Ruby on Rails Miguel Fernández Fernández miguel@ThirdWay.es