Skip to content

Latest commit

 

History

History
1096 lines (725 loc) · 31.3 KB

es-rubything.textile

File metadata and controls

1096 lines (725 loc) · 31.3 KB

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Start off with some headers

Title: Taller de Ruby/Rails
Author: DevChix Uruguay y Amigos
Generator: text

%css

body {
font-family: ‘Helvetica Neue’, Helvetica, sans-serif;
}

.slide h2 {
font-size: 24pt;
}

table td {
padding: .5em;
border: 1px solid #ccc;
}

%end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Start Presentation

Aprendiendo Ruby and Rails

Buenos Días!

SKIP
Algo que decir que quiere ser una nota privada.
END

Presentaciones

  • Devchix : @devchix y www.devchix.com
  • RailsBridge en la comunidad Ruby/Rails
  • PyStar en la comunidad Python
  • En Montevideo gente de Cubox, WyeWorks y Moove-it

Agenda del Día

  • 9:00 Presentaciones
  • 9:30 – 13:00 Instalación del ambiente de trabajo
  • 10:30 -11:30 Introducción a Ruby
  • 11:30 -12:00 Ruby Koans
  • 12:00 -1:00 Almuerzo
  • 1:00 – Rails parte 1
  • 2:45 -3:00 Descanso
  • 3:00 -4:30 Rails parte 2
  • 4:30 Y ahora? Contribuyendo con Rails

Qué Temas Vamos a Cubrir?

  • Ruby
  • Instalando el ambiente de trabajo
  • Sintaxis y operaciones simples en Ruby
    • Objetos, clases, modulos y métodos
    • Testing en Ruby
    • Bloques y estructuras de control
    • Expresiones regulares
    • Excepciones
  • Una introducción a Rails
    • Un tour desde la consola de Rails
    • Modelos
    • Vistas
    • Controladores

Ruby

  • Originado en Japón a mediados de los 90, su creador es Yukihiro “Matz” Matsumoto. Está inspirado en Perl, Lisp entre otros lenguajes
  • “I wanted a scripting language that was more powerful than Perl, and more object-oriented than Python. That’s why I decided to design my own language”.
  • Ruby es un lenguaje
    • dinamico
    • reflexivo
    • orientado a objetos
    • open source
  • Hay diferentes implementaciones del lenguaje
    • MRI (mat’z ruby interpreter) es la referencia que hay de Ruby. Está escrito en C
    • JRuby es una implementación hecha en Java
    • IronRuby corre sobre .NET. Es desarrollado por Microsoft bajo la Apache License.
    • Rubinius esta hecho en Ruby
  • Versiones
    • 1.8.7
    • 1.9.2 <— recomendada

Porque Ruby?

  • “Lenguajes de Programación deben sentirse natural para los programadores.”
  • La comunidad de Ruby en Montevideo está creciendo
  • Tiene RubyGems que es el sistema usado para empaquetar y distribuir código Ruby
  • Rails es un web framework bastante popular construido sobre Ruby
  • En 10 años se han agregado una gran cantidad de clases y modulos nativos al lenguaje.
  • Tiene buenas herramientas para testing como RSpec y Cucumber.

Instalando el ambiente de trabajo

  • Todos se sienten comodos manejando una terminal?
  • En linux ó Mac (tener el sistema actualizado e instalado curl y git)
    • RVM: Te permite manejar multiples interpretes de Ruby en la misma máquina y fácilmente cambiar entre versiones.
      • bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
      • Seguir las instrucciones para agregar rvm al .bashrc
      • source $HOME/.rvm/scripts/rvm
      • rvm notes
  • En Windows hay que instalar primero Ruby, a no ser que usen RailsInstaller que ya instala todo
    • Ruby: Vamos a usar la version 1.9.2 y el interprete MRI
      • Ir a http://rubyinstaller.org y descargar la versión de Ruby mediante el botón Download.
      • Ejecutarla y comenzar la intalación
    • Mediante Rails installer

Instalando el ambiente de trabajo

  • En Linux ó Mac
    • Ruby: para este taller usaremos mri y la versión 1.9.2
      • rvm install 1.9.2
      • mirar rvm help para ver que más se puede hacer

Instalando el ambiente de trabajo

  • En Windows
    • PIK: Te permite manejar multiples interpretes de Ruby en la misma máquina y fácilmente cambiar entre versiones.
      • Descargar la última versión http://github.com/vertiginous/pik/downloads
      • Seguir los pasos de la instalación
      • Deslogueate o reinicia windows para integrar pik al ambiente.
      • En una terminal
        • pik add
        • pik list
        • pik use 192
        • ruby -v
    • Ó Ruby Installer: Un ejecutable que instala Ruby y Ruby Gems
      • Descargar la ultima verisón de http://rubyinstaller.org
      • Seguir los pasos de la instalación
      • Instalar pik mediante @gem install pik

Instalando el ambiente de trabajo

  • Instalar Ruby Gems
    • En Linux
      • @apt-get install rubygems
    • En Windows RubyInstaller ya viene con Ruby Gems
  • Rails: Vamos a usar la version 3.1
    • @gem install rails
  • Editores: Trabajen en el que se sientan más comodos
    • VIM
    • Textmate
    • Emacs
    • Gedit
    • Eclipse
    • NetBeans
    • RubyMine

Abriendo el interprete de Ruby

Abrir una terminal y ejecutar irb.

Jugar un poco:

1
4 + 3 
"hat" 
[1, 2, 3, "happy"].each { |i| puts i }

>> es donde ingresas comandos y en => va a aparecer la respuesta.

irb tiene un historial de comandos. Usen las flechitas para navegarlo.

Datos Básicos de Ruby

% TODO more table

Integers 1, 2, 3
Strings "chicken"
Booleans true, false
Symbols :chicken
Arrays [1, 7, "cake"]
Hashes {:chicken => "chicken", :sillyexample => :chicken}

En Ruby casi todo es un objeto. A un objeto se le puede enviar los mensajes a los que el objeto puede responder. A grandes rasgos a esto le llamamos “duck typing”. Si un objeto camina como un pato y habla como un pato, entonces el interprete lo trata como un pato.
Juega con la terminal!

% Esto no está muy claro <<—- MIRAR COMO INCLUIR LA EIGENCLASS
% Las estructuras de control no son objetos ni mensajes que se envian a otros objetos, por eso la aclaracion de casi todo, en algún que otro lenguaje esto si se cumple.
% La definicion de Duck Typing no es “El tipo del objeto es definido por lo que el objeto puede hacer”.
% Duck Typing indica que a un objeto le podemos enviar los mensajes a los que el objeto puede responder, sin importar el tipo del objeto. Comunmente se dice: “Si camina como un pato y habla como un pato, entonces es un pato”
% Si por tipo del objeto entendemos “Lo que el objeto puede hacer”, entonces cabe la pregunta “Que es lo que puede hacer el objeto?”, la respuesta sería: “Todo lo que hace es recibir mensajes, los mensajes que puede recibir estan determinados por los métodos del objeto”. Quién determina los métodos del objeto? La clase del objeto.

% Cuál es la clase de un objeto? Depende, puede ser la clase a partir de la cual se creó el objeto, o la clase Singleton del objeto (clase Eigen, es una clase anónima).
% O sea que el tipo de un objeto es la clase del objeto.

% Ejemplos:

% bc. irb> names = [‘jessie’, ‘john’]
% irb> numbers = [1, 2, 3, 4]
% irb> def numbers.multiply
% irb> inject(:*)
% irb> end

% La clase de names es Array y no contiene el método multiply
% La clase de numbers es una clase Singleton, única al objeto, que contiene la definición del método multiply.

Datos Básicos en Ruby

  • En Java min = Math.abs(num)
  • En Ruby postive = num.abs
  • En C strlen(name)
  • En Ruby name.lenght

Le enviamos un mensaje al propio objeto. Y lo mismo aplica a toods los objetos en Ruby.

En Ruby, NIL es un objeto que representa ausencia de valor.

Operaciones basicas en ruby

2 + 2 4
3 * 3 9
"chicken".reverse "nekcihc"
"chicken".length 7
2 + 2 == 4 true
2 + 2 == 5 false
[1, 2, 3].include?(2) true

Y que es lo que hace "chicken".reverse.length ?
Y "puppy".include?("p")?

Interpolación de Expresiones

Algo que Ruby hace con strings entre comillas dobles es interpolacion de expresiones. Es decir, dentro de un string la secuencia #{expression} es reemplazada por el valor de la expresión.

Por ejemplo, prueba

@"Nuestro array es #{[1,2,3]}"@

Ó

var = [1,2,3,4,5,6]
"Nuestro array es #{var}"

Variables

Las variables son implícitas y declaradas.

Qué pasa en cada paso?

thing = "chicken"
thing
thing.reverse
thing
thing = thing.reverse

Variables

Intenten.

awesome_list = [5,2,1,8]
awesome_list.sort!
awesome_list

Como paso esto? Acciones que terminen con un ! “cambian” los datos!
Esto es una convención de Ruby, pero una buena a seguir.

Convenciones para Variables y Alcance

  • locales: comienzan con minúscula o guión bajo
  • globales: comienzan con $
  • de instancia: comienzan con @
  • de clase: comienzan con @@
  • de más de una palabra se escriben con guión bajo. Ej. user_name
  • constantes en mayúscula

Hay tres lugares donde el alcance cambia: las definiciones de clases (class), las definiciones de modulos (module) y los métodos (def)

Símbolos

Son etiquetas que no hay que pre-declarar y que son únicas. Empieza con : y es seguido por un nombre. Ruby garantiza que en cualquier parte del programa en donde aparezca el símbolo va a tener el mismo valor. Son usualmente usados como llaves de un hash.

Por ejemplo:

  • :norte
  • :sur

Hashes

  • También es un tipo nativo del lenguaje.
  • Al igual que los arrays son colecciones indexadas.
  • Las llaves de los arrays deben ser integer pero los hashes pueden tener cualquier objeto como llave.
  • Pueden contener diferentes tipos de elemento en el mismo array/hash.
  • Por defecto el valor para nil en un hash es false. Se puede cambiar al crear el hash.
  • En Ruby 1.9 se introduce un nuevo sintaxis para hashes
frutas_color = {
  naranja:  "naranja",
  frutilla: "rojo",
  banana:   "amarillo
}

frutas_color[:frutilla] produce "rojo"

También conocidos como Map, Associative Array, Dictionary, Key/Value Pair Store

Hashes

Consideremos un sistema de rating de libros:

  • Usamos valores numericos 0-5 para valorar un libro que hemos leido.
  • :not_rated va a representar un libro que aún no ha sido valorado.
  • Vamos a guardar los datos en un hash.

Crea un hash y agregale algunos libros, por ejemplo:

books = { "Left Hand of Darkness"        => 5,
              "The Word for World Is Forest" => 5,
              "Nevermind the Pollacks"       => 0,
              "Only Revolutions"             => :not_rated 
	    }

Hashes

Vamos a obtener el rating de un libro en particular con

books["Left Hand of Darkness"]

También podemos guardar valores con

books["Only Revolutions"] = 3

Agregamos un libro de la misma forma

books["White Teeth"] = 4

Y con books vemos todo el hash

Jueguen con el hash en irb

Métodos

40.reverse

Qué pasa?

Ruby dijo NoMethodError: undefined method `reverse' for 40:Fixnum

Significa que reverse no es un método que podamos aplicar al número 40

métodos

Los métodos son invocados al enviarles un mensaje al objeto. El mensaje contiene el nombre del método asi como cualquier parametro que este necesite.

Si quieren ver los métodos de un objeto pueden escribir 40.methods.sort

Objetos

Nuevamente, todo lo que manipulas en Ruby es un objeto y los resultados de esas manipulaciones tambien son objetos. Cada objeto tiene un identificador único.

Un objeto son los datos asi como tambien los métodos que se le puede aplicar.

Un objeto es una estructura con identidad, estado y un comportamiento definidos.

Como averiguamos la clase origen de un objeto? Sólo hay que preguntarle!

40.class

Clases & Métodos

Aprendamos la sintaxis mediante un ejemplo:

class Counter
end

Qué podemos hacer con Counter?

c = Counter.new

% Step 1 %

Clases & Métodos

Aprendemos la sintaxis mediante un ejemplo:

class Counter
attr_accessor :value
end

Ahora intentemos

c = Counter.new
c.value
c.value = 10
c.value

Qué pasa? Que es lo que hace attr_accessor :value ?

Clases & Métodos

Aprendemos la sintaxis mediante un ejemplo:

class Counter
  attr_accessor :value

  def initialize
    @value = 0
  end
end

Nuevamente

c = Counter.new
c.value

initialize le da instrucciones a new de como crear un objeto

% Step 2 %

Clases & Métodos

Aprendamos la sintaxis mediante un ejemplo:

class Counter
  attr_accessor :value

  def initialize
    @value = 0
  end

  def increment
    @value = @value + 1
  end
end

Clases & Métodos

Estas definiciones de un método son equivalentes:


  def increment x
    x + 1
  end

  def increment(x)
    return x + 1;
  end

  def increment(x); x + 1; end

Clases

Usemos nuestra clase Counter:

count = Counter.new
count.increment
count.increment
count.value
count.class
count.methods.sort
count.respond_to?(:increment)

Ejercicio

Vamos a agregar un método Counter.increment_by que tome un argumento por el cual incrementar el contador.

No hay que empezar desde cero; podemos sólo abrir la clase

% Sería bueno aclarar que abrir una clase es una mala práctica, que si bien es útil y rapido en algunos casos, existen otras prácticas mejores para agregar nuevo comportamiento a una clase.

class Counter

def increment_by(n)
  # fill in here
end

end

Prueba el código que escribiste:

c = Counter.new
c.increment_by(5)
c.value

Clases

También se puede agregar métodos a clases ya existentes:

class String
  def chicken?
    self == "chicken"
  end
end
"chicken".chicken?
"puppy".chicken?

self es una forma de referirse al objeto del cual el método se esta llamando.

En "puppy".chicken?, self es "puppy".

Clases

Si aún no lo han hecho, escriban la clase Counter en su editor favorito y guardenlo en disco. Levantemoslo en la consola de ruby.

class Counter
  attr_accessor :value
  def initialize
    @value = 0
  end
  def increment
    @value = @value + 1
  end
  def increment_by(n)
    @value = @value + n
  end

En la consola: require 'path_to_your_file'

Modulos

Un módulo es básicamente una clase que no puede ser instanciada.

Control de Acceso

Ruby tiene tres niveles de protección para constantes y mteodos de clase y modulo.

  • public. Accesible para todo el mundo.
  • protected. Puede ser sólo invocado por objetos la clase definida y sus subclases.
  • private. Puede ser solo llamado en una forma funcional (con un self implicito). Por lo tanto métodos privados solo pueden ser llamados en la clase definida y por los ancestros y descendientes de la clase, pero solo dentro del mismo objeto.

Testing

Automatizar cualquier tarea que se pueda hacer más de una vez es una sabia decisión.

  • no tener que pasar horas buscando un bug en el código que se escribio hace meses
  • escribir codigo mas robusto y de mejor calidad
  • el código se hace más mantenible
  • más productividad a largo plazo sobre la aplicación

Testing

Ahora escribiremos una clase para testearlo automáticamente.

require 'test/unit'
  require 'counter'
  class TestCounter < Test::Unit::TestCase
    def test_increment
      assert_equal(1, Counter.new().increment())
    end
  end

Escribanlo en un archivo test_counter.rb y ejecutenlo.

Ejercicio

Escribir un test para increment_by.

Ejercicio

Agregar un método a String que devuelva si un string es palindromo o no.

Un palindromo es cualquier cadena de caracteres que se lea igual de adelante para atras que de atras para adelante.

Para empezar tipear lo siguiente en la linea de comandos:

class String
  def palindrome?

y terminarlo! Pruebenlo con "abba".palindrome? y "puppy".palindrome?

Más sobre las clases nativas de Ruby

http://rubydoc.info/stdlib/core/

Otras son: Array, Enumerable, Fixnum, Float, Hash, NilClass, String, Time

Bloques

Algunos métodos también pueden tener asociados bloques como si fueran parametros.

list.each {|p| code} corre code en cada elemento de list

list = [1,2,3,4]
list.each { |n| puts (n + 1) }
  • Un bloque es un pedazo de código asociado a un contexto de variables.
  • Puede tener dos sintaxis
    • Cuando es sólo una linea { |arg1, arg2, ..| code }
    • { |v| v.palindrome? }
    • { |x, y| x * y }
    • Cuando es más de una linea
      bc.. do |arg|
      code
      end

Bloques

Para nuestro ejemplo de los libros.

reviews = Hash.new(0)
books.values.each { |rate| reviews[rate] = reviews[rate] + 1 }
reviews

Qué contiene reviews?

reviews[5]

Bloques

Y en caso que el bloque tenga más de una linea

reviews = Hash.new(0)
books.values.each do |rate|
  reviews[rate] = reviews[rate] + 1
  # more code can go here...
end

Bloques y Callbacks

Se pueden usar bloques para implementar callbacks, para pasar pedazos de código e implementar iteradores.

Por ejemplo,

def call_block
  puts "Comienzo del método"
  yield
  yield
  puts "Fin del método"
end

call_block { puts "En el bloque" } produce:

Comienzo del método
En el bloque
En el bloque
Fin del método

yield invoca al bloque asociado con la llamada al método que lo contiene

Lambdas y Procs

Los bloques no son objetos pero pueden ser convertidos en objectos mediante la clase Proc. Hay varias formas de convertir un bloque en un objeto Proc:

  • Pasando un bloque a un método cuyo último parametro es prefijado con un ampersand.
def método(p1, p2, &bloque)
  puts bloque.inspect
end
método(1,2) { "un bloque" }
método(3,4)
  • Llamando Proc.new
Proc.new{ "un bloque" }

Lambdas y Procs

  • Llamando a el método Object#lambda asocia un bloque con la llamada lambda{ “un bloque” }
  • En 1.9 usando la sintaxis
lam =->(p1,p2) {p1 + p2}
lam.call(4,3)

Lambdas y Procs

Diferencias entre Procs y Lambdas:

  • Return keyword.
    • En un lambda, return retorna desde el lambda.
    • En un proc el return retorna desde el alcance donde el proc fue definido.
  • Argumentos.
    • Si se llama a un lambda con una aridad incorrecta entonces falla con ArgumentError.
    • Los Proc son más flexibles y toman la cantidad de argumentos necesaria llenando los no dados con nil.

Estructuras de Control

Ruby provee las clasicas estructuras de control como los if y while loops.

Sintaxis if

if true
  1
else 
  2
end

ó

código if true

Estructuras de control

Sintaxis while

while true
  do some code
end

ó

some_code while true

Iteradores

3.times{ puts "Hola mundo!" }
5.downto(1){|i| puts "Cuenta regresiva #{i}."}
animals = ["gato", "perro", "caballo"]
animals.each do |animal|
  puts "Tenemos un #{animal}."
end
my_hash = {:type => "cat",
              :name => "Beckett",
	      :breed => "alley cat"}
my_hash.each do |key, value|
  puts "My #{key.to_s} is #{value}" 
end
my_hash.each_pair{|k,v| puts "key: #{k} con su valor #{v}"}

Expresiones Regulares

  • Ruby las tiene nativo en el lenguaje
  • La sintaxis es /pattern/
  • Una expresión regular también es un objeto. Son instancias de la clase Regexp

Por ejemplo, /P(ython|erl)/ matchea los strings que contengan Python o Perl

Excepciones

Información de una excepción viene encapsulada en un objeto de clase Exception o alguno de sus “hijos”.

Para manejar excepciones:

begin
# .. procesar
rescue
# .. manejar el error
ensure
# ..codigo que siempre se ejecuta (por ejemplo f.close para un archivo f)
end

Para levantar excepciones con Object#raise :
raise ArgumentError, "Name too big", caller

Ruby Koans

Son ejercicios para aprender/practicar Ruby. Aconsejables para cualquier nivel. Tiene también ejercicios sobre metaprogramación.

Descargarlos desde “http://rubykoans.com/”http://rubykoans.com

Descanso para el Almuerzo

Introduccion a Rails

  • Rails es un framework para construir aplicaciones web
  • Está estructurado usando una arquitectura llamada MVC: Model-View-Controller
  • MVC separa diferentes partes de la lógica de la aplicación en secciones en función de para que son usadas.

¿Por qué Rails?

  • Convenciones sobre configuraciones
    • Crear una aplicación Web implica tomar muchas decisiones.
    • Rails tiene una opinión sobre cómo habria que desarrollar aplicaciones web.
    • Esto hace que algunas las tareas que sigan sus convenciones sean muy sencillas (y las que no sigan las convenciones de Rails lleven un poco más de trabajo)
  • Comunidad y Herramientas
    Existe una comunidad muy activa entorno a Rails y podemos aprovecharla para consultar y usar las herramientas desarrolladas.

Escribir en una consola:

  1. cd microrant
  2. bundle install
  3. rake db:migrate
  4. rails server
  5. Abrir http://localhost:3000 en tu navegador

Microrant – (micro quejas)

  • Twitter?
  • 10 caracteres para expresar tu ira
  • Actividades basicas: create, read, update, delete (CRUD)
  • Ir a http://localhost:3000/users/new para crear un nuevo usuario con tu nombre
  • Luego ir a /rants/new y crear un nuevo rant
    • Rants también pueden ser editados y borrados!
  • Qué hay detrás de escenas?
    • Rails trae clases que nos permiten obtener y manipular datos fácilmente
    • La lógica de la aplicación se escribe en Ruby común y corrriente, y un modulo llamado ActiveRecord hace todo el trabajo de conexión a la base de datos

En el Backstage

Organización por defecto de Rails:

app/

—> controllers/

—> helpers/

—> mails/

—> models/

—> views/

config/

—> database.yml

—> routes.rb

En La Consola

  • Cerrar el servidor Rails con Ctrl-C
  • rails console
  • Puedes modificar los datos usando las clases Rant y User
  • La clase User tiene atributos id y name
  • La clase Rant tiene atributos id, message y user_id

En La Consola

Como podemos ver un rant luego que fue creado?

r = Rant.find(1)
r.message
r.user_id

Y como podemos modificarlo?

r.message = "RANTING!"
r.save

Necesitamos guardar (save) los cambios luego que terminamos de editarlo.
Tambien podemos modificar directamente con update_attribute(:message, "RANTING"). Si quieren ver mas métodos, consulten la documentación de Rails.

Donde Estan Mis Cosas

Los modelos en Rails tienen métodos de busqueda incorporados que ayuda a obtener los registros desde la base de datos.

  • Rant.all
  • Rant.order("created_at DESC")
  • Rant.first
  • Rant.where("user_id = 1")
  • Rant.where(:user_id => 1)
  • Rant.where(:user_id => 1).order("created_at DESC")

Observa la sentencia de SQL generado con el método to_sql

En La Consola

Intentemos crear un nuevo Rant para user_id 1


rant = Rant.new
rant.user = User.find(1)
rant.message = "WHAT IS TH"
rant.save

No tuvimos que setearle el valor de id al mensaje!
Esto fue automaticamente hecho por new.

Guardamos (save) el registro cuando terminamos, para poder crearlo, al igual que cuando estabamos editándolo.

En la Consola

Hay una mejor manera de crear un rant

User.find(1).rants.create(:message => "E POINT!?")

De esta forma no tenemos que usar save para guardar pues usamos create—quien combina new y save en un sólo paso.

Mirando a los Modelos

Abrir los archivos user.rb y rant.rb en el directorio models/

class Rant < ActiveRecord::Base
  belongs_to :user

  validates :user, :presence => true
  validates :message, :presence => true, :length => { :maximum => 10 }
end

Mirando a los Modelos (User)

class User < ActiveRecord::Base
  has_many :rants

  validates :name, :presence => true
end

Ejercicios

Algunas personas están escribiendo rants en minúsculas!

Vamos a escribir un método para convertir todos los rants a mayúsuculas.
Primero encuentren el archivo rant.rb en el directorio de modelos de Rails.

class Rant < ActiveRecord::Base
  before_save :convert_message_to_uppercase
  def convert_message_to_uppercase
  ...

Rails tiene muchas extensiones a las clases de Ruby para hacer que las tareas comunes sean sencillas. Miren en http://api.rubyonrails.org/classes/ActiveSupport/Multibyte/Chars.html y encuentren el helper que necesitan para este ejercicio.

Una vez que lo hicieron prueben escribir un rant en minúsculas para ver qué pasa.
Esta vez utilicen un método de Ruby? Miren en: http://www.ruby-doc.org/core-1.9.2/String.html y busquen si hay un método de instancia que permite pasar a minúsculas un String.

Ejercicios

Pueden querer trabajar con sus datos en algún otro formato. Vuelvan a la consola de Rails y escriban un programa que cree un hash que contenga mensajes rant junto con el nombre del usuario que lo escribió.

Como era que se creaba un Hash?

  • Vimos Hash.new pero también se puede crear con {}.
  • Intenta new_hash = {}

El resultado debería ser algo como:

=> {"RANTING!"=>"caylee", "WTF"=>"audrey"}

Pueden usar un iterador para mostrarlo como una serie de strings formateados?

Callbacks

El código que aparece en before_save usa un callback. Rails define varios callbacks que nos permiten cambiar la entrada a un modelo antes o después de acciones como save, create, update y delete.

before_save :geocode_address
after_create :notify_admins
before_validate :check_over_some_other_details

Control de Calidad

Las validaciones dan un wrapper sencillo para chequear si un atributo en particular está presente, si esta en el formato correcto u otros requerimientos antes que la aplicación guarde los datos. La aplicación de microrant ya tiene algunos de éstos. Miren en los modelos Rant y User para ver cuáles hemos incluído.

Pueden pensar de algunas otras validaciones que podamos querer usar? Intenten cambiar el largo de un mensaje de Rant válido.

Mostrando los Datos

Rails automáticamente crea vistas con contenido usando el comando scaffold. Miren lo que tenemos en /app/views

Estos archivos usan el sistema de templating llamado ERB que convierte líneas de Ruby en la vista en HTML estático para desplegar. Una línea típica de ERB podria ser como esto:

5 + 1 = < %= 5 + 1 %>

Se vería así:

5 + 1 = 6

Documentación sobre la sintaxis de ERB: http://ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html

Ejercicio 1 (ERB)

El sistema de scaffolding es rápido de usar, pero no siempre lindo. Nuestra lista de rants tiene al user_id para la persona que lo dijo pero no su nombre. Cambien eso.

Ir a /app/views/rants/ y abran el archivo index.html. Por defecto, el scaffolder hace que la vista index muestre una lista de registros relacionados al tipo del modelo. Encuentren la línea que muestra el id del usuario y cámbienla para mostrar el nombre de usuario.

Ejercicio 2 (ERB)

Modifiquen el archivo index.html de rants, para que muestre “No hay rants” en vez de la tabla, en caso de que no existan rants.

Ejercicio 3 (ERB)

En la página index de usuarios, agreguemos una columna a la tabla para mostrar cuantos rants cada persona ha escrito. ActiveRecord hace que esto sea muy fácil con un método llamado count que se puede enviar a una colección de registros para obtener el count de la base de datos en vez de todos los registros. Por ejemplo User.count o Rants.count.

Layouts

Ir a app/views/layouts/application.html

  • En application.html está el template de la aplicación.
  • Esta página es la que permite tener un esquema html común a todas las paginas
  • El método yield pasa la ejecución al template que se quiere ver
  • En este caso el template que hemos estado viendo es index.html

Layouts Especificos

  • Crear un archivo en app/views/layouts/users.html y escribir:
< h1> Esto es solo para los Usuarios < /h1>
< %= yield %>
  • Ejemplo de convención sobre configuración

Rutas

Como sabe Rails que a que página ir cuando visitas http://localhost:3000/rants/new ?

Rails primero busca las páginas estáticas en public/ y luego ejecutan las reglas

Abrir /config/routes.rb para ver como funciona.

Rutas

Observar la linea resources :users
Ejecutar rake routes y analizar que devuelve? Como se relaciona con la linea de routes.rb?

Nos falta la C de MVC

Ahora que hemos visto y editado modelos y vistas, vamos a ir a mirar los archivos de controladores en nuestro proyecto.

Qué hace un controlador?

  • Conecta la vista y el modelo, llamando a métodos en los modelos para obtener los datos necesitados en la vista y permitiendote acceder parametros de entrada como los de un formulario.
  • Responde al request HTTP del navegador y renderea el tipo pedido de salida (en nuestros scaffolds es html o xml pero otros como json pueden ser facilmente agregandos — API instantanea!)
  • También en el controlador es donde se deberia agregar los controles de acceso, como por ejemplo solo permitir que el usuario que escribio el rant pueda eliminarlo.

Ejercicio

Modificar el código para no permitir escribir más de 3 rants por dia.

Ejercicio – Solucion (Parte I)

  • Agregar el siguiente código en el users_controller.rb de la carpeta app/controllers

bc..
before_filter :no_quejarse_demasiado, :only => [:new, :create]

def no_quejarse_demasiado user = User.find(params[:id]) if user.rants.where(created_at > 1.day.ago).count > 3 redirect_to :index, :notice => “Has escrito demasiados rants hoy!” end end

Ejercicio – Solución (Parte II)

En app/views/layouts/application.html.erb agregar arriba de yield

bc..

< %= flash[:notice] %>

Picando tu propio código

  • Ir al directorio donde puedas crear una aplicación nueva de Rails
  • Correr rails new betterrant
  • Ir al directorio creado cd betterrant
bundle install
rails generate scaffold User name:string
rails generate scaffold Rant user_id:integer message:string
rake db:migrate

En este momento puedes iniciar el servidor y mirar que hay

Resumen

  • Hemos visto lo básico del lenguaje Ruby
    • Si quieren repasarlo, Try Ruby es una aplicación web para jugar con Ruby

% Algo más sobre lo que vimos %

Resumen

  • Hemos aprendido sobre una pequeña aplicación Rails: microrants
    • Un tutorial que pueden mirar es Rails For Zombies
    • Y en más detalle pueden encontrar Ruby Guides
    • ActiveRecord nos permite manipular datos persistidos como si fueran objetos comunes
    • Los archivos .erb nos permiten integrar el código Ruby con html
    • Scaffolding nos da una forma de automatizar el comienzo de un proyecto Rails

Más Para Leer

Grupos de Usuarios y Desarrolladores

  • Participa en el grupo de Ruby de Uruguay. Comparte lista de correo con los usuarios de Ruby de América del Sur. http://rubysur.org/
  • Otras listas de correo
    • ruby-talk@ruby-lang.org (en ingles)
    • ruby-doc@ruby-lang.org (en ingles) sobre documentación
    • ruby-core@ruby-lang.org (en ingles) sobre implemantación del core de ruby
    • ruby-dev@ruby-lang.org (en ingles) para desarrolladores de ruby
    • RubyConf Uruguay 2011 el próximo fin de semana.

Contribuir con Ruby y con Rails

  • Reportar Bugs en Ruby
    • El tracking system está en http://redmine.ruby-lang.org
    • Antes de reportarlo navega los bugs ya reportados para ver si tu bug ya existe. También proba nuevas versiones de ruby por si eso lo soluciona.
    • También es una buena idea enviar una pregunta sobre el bug a la lista de correo ruby-talk.
    • Cuando envias un bug es una buena idea incluir el resultado de ejecutar ruby -v, el sistema operativo y además la problematica del código.
  • Ayudar con la documentación
    • Hacer traducción
    • Mejorar la documentación
    • Hay un sistema llamado RDoc
    • ri es un visor en la consola para esa misma documentación. Tipea ri ClassName para encontrar la documentación de esa clase