• 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.

Like this presentation? Why not share!

Ruby On Rails Intro

on

  • 3,556 views

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 ...

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

Statistics

Views

Total Views
3,556
Views on SlideShare
3,554
Embed Views
2

Actions

Likes
7
Downloads
0
Comments
0

1 Embed 2

https://twitter.com 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

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

    Ruby On Rails Intro Ruby On Rails Intro Presentation Transcript

    • DESARROLLO WEB AVANZADO Desarrollo rápido con Ruby on Rails Miguel Fernández Fernández miguel@ThirdWay.es
    • 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/#;: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
    • 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 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/
    • 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...
    • 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? 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.
    • ¿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) 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)
    • 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)
    • 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
    • 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
    • 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>
    • 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=> 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
    • 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 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
    • 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 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
    • 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
    • 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
    • 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/: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
    • 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)
    • Gracias
    • DESARROLLO WEB AVANZADO Desarrollo rápido con Ruby on Rails Miguel Fernández Fernández miguel@ThirdWay.es