Upload
fernando-calatayud
View
43
Download
0
Embed Size (px)
Citation preview
RUBYIntroducción
FERNANDO
CALATAYUD
Twitter: @fj2cGithub: @fernan2
Hola, me llamo Fernando, y soy programador Ruby
RUBY EN UNA FRASE➤ Ruby es un lenguaje hecho
para optimizar al programador
“Ruby is designed to make programmers happy.”Yukihiro “Matz” Matsumoto
Y POR ESO…➤ Ruby es un lenguaje hecho
para optimizar al programador
➤ Ruby es un lenguaje interpretado
Y POR ESO…➤ Ruby es un lenguaje hecho
para optimizar al programador
➤ Ruby es un lenguaje interpretado
➤ Ruby es dinámicamente tipado
“With great power comes great responsability.”Uncle Ben
Y POR ESO…➤ Ruby es un lenguaje hecho
para optimizar al programador
➤ Ruby es un lenguaje interpretado
➤ Ruby es dinámicamente tipado
➤ Ruby es (relativamente) lento
¿Y eso importa?
¿AHORRAR 0.08 SEGUNDOS ES IMPORTANTE EN TU NEGOCIO?
Y POR ESO…➤ Ruby es un lenguaje hecho
para optimizar al programador
➤ Ruby es un lenguaje interpretado
➤ Ruby es dinámicamente tipado
➤ Ruby es (relativamente) lento
➤ Ruby es un lenguaje Orientado a Objetos
Y POR ESO…➤ Ruby es un lenguaje hecho
para optimizar al programador
➤ Ruby es un lenguaje interpretado
➤ Ruby es dinámicamente tipado
➤ Ruby es (relativamente) lento
➤ Ruby es un lenguaje Orientado a Objetos
➤ Ruby es muy flexible“With great power comes great responsability.” (sí, otra vez!)
¿QUE SIGNIFICA EXACTAMENTE QUE ES FLEXIBLE?➤ Ruby tiene “formas acortadas” para escribir las cosas
tecleando menos.
¿QUE SIGNIFICA EXACTAMENTE QUE ES FLEXIBLE?➤ Ruby tiene “formas acortadas” para escribir las cosas
tecleando menos.
➤ Es frecuente tener la versión acortada para usar con trozos de código pequeños y la “normal” para cuando hay más código.
¿QUE SIGNIFICA EXACTAMENTE QUE ES FLEXIBLE?➤ Ruby tiene “formas acortadas” para escribir las cosas
tecleando menos.
➤ Curiosamente, el beneficio no es que se escribe menos, sino que queda más bonito y se lee mejor.
➤ Conviene seguir una “guía de estilo” para asegurar la consistencia y que no sea un caos:https://github.com/bbatsov/ruby-style-guide
➤ Es frecuente tener la versión acortada para usar con trozos de código pequeños y la “normal” para cuando hay más código.
➤ Una especie de “cadena corta” especialmente eficiente porque es inmutable e internamente funciona como un entero
➤ Además de eficiente… es muy legible, y mola!
:title
SYMBOLS
➤ Una especie de “cadena corta” especialmente eficiente porque es inmutable e internamente funciona como un entero
➤ Además de eficiente… es muy legible, y mola!➤ Hay una versión acortada para arrays de symbols
attributes = %i(title author year description)
SYMBOLS
➤ Una especie de “cadena corta” especialmente eficiente porque es inmutable e internamente funciona como un entero
➤ Además de eficiente… es muy legible, y mola!➤ Hay una versión acortada para arrays de symbols➤ Con frecuencia se usa para key de hashes (pares key-
value), así que… también hay una versión acortada para este caso
SYMBOLS
:key => 'My value'
key: 'My value'
➤ El bucle menos rubyish del mundo (pero funciona):
for i in 0..(subscribers.length - 1) subscribers[i].notifyend
BUCLES
➤ Preferimos trabajar con instancias mejor que índices:
for i in 0..(subscribers.length - 1) subscribers[i].notifyend
BUCLES
for suscriber in subscribers subscriber.notifyend
➤ Preferimos trabajar con instancias mejor que índices.➤ Preferimos “each” en vez de “for” (crea un bloque: scope
propio). Lo que pasa en el “each”, se queda en el “each”:
BUCLES
for suscriber in subscribers subscriber.notifyend
suscribers.each do |subscriber| subscriber.notifyend
➤ Preferimos trabajar con instancias mejor que índices.➤ Preferimos “each” en vez de “for” (crea un bloque: scope
propio). Lo que pasa en el “each”, se queda en el “each”.➤ Si se va a iterar una línea corta, se puede meter todo en
una línea:
BUCLES
suscribers.each { |subscriber| subscriber.notify }
suscribers.each do |subscriber| subscriber.notifyend
➤ Preferimos trabajar con instancias mejor que índices.➤ Preferimos “each” en vez de “for” (crea un bloque: scope
propio). Lo que pasa en el “each”, se queda en el “each”.➤ Si se va a iterar una línea corta, se puede meter todo en
una línea.➤ Si lo único que voy a hacer es llamar un método de la
instancia, ni siquiera necesitaré el bucle:
GREAT!!!!
BUCLES
suscribers.each(&:notify)
suscribers.each { |subscriber| subscriber.notify }
➤ Hay una versión acortada para usar con trozos de código pequeños
if subscriber.valid? subscriber.notifyend
CONDICIONALES
subscriber.notify if subscriber.valid?
➤ Hay una versión acortada para usar con trozos de código pequeños
➤ Se puede usar en su lugar, sin abusar, el operador ternario
timeout = if is_admin ADMIN_TIMEOUT else USER_TIMEOUT end
CONDICIONALES
timeout = is_admin ? ADMIN_TIMEOUT : USER_TIMEOUT
➤ Hay una versión acortada para usar con trozos de código pequeños
➤ Se puede usar en su lugar, sin abusar, el operador ternario➤ Preferimos unless en vez de condiciones negadas (siempre
que no haya else)
CONDICIONALES
if !subscriber.valid? subscriber.rejectend
unless subscriber.valid? subscriber.rejectend
➤ Hay una versión acortada para usar con trozos de código pequeños
➤ Se puede usar en su lugar, sin abusar, el operador ternario➤ Preferimos unless en vez de condiciones negadas (siempre
que no haya else)➤ Si no se trata de condiciones “normales”, sino de
tratamiento de errores, es más expresivo usar “condiciones de salida” que partir el flujo en dos ramas con apariencia de similar jerarquía
CONDICIONALES
(Requisito: los métodos deben devolver nil si fallan)
blog = Blog.find(url)if blog subscription = subscribe(me, blog) if subscription notify_subscription(subscription) else subscription_failed endelse render_404end
CONDICIONALES
blog.find(url) or return render_404subscription = subscribe(me, blog) or return subscription_failednotify_subscription(subscription)
➤ Similares a otros lenguajes.➤ Muy enriquecidos con métodos útiles “de fábrica”.
Consultar documentación https://docs.ruby-lang.org/en/2.3.0/String.html
➤ Se usa interpolación "Nombre: #{user.name}" en vez de suma "Nombre:" + user.name para evitar problemas con nil.
➤ Conversión a entero inteligente: "46-valencia".to_i => 46 ➤ Al interpolar un objeto, se llamará a su método .to_s .
Definiendo este método, tendremos un magnífico “default” de cómo se muestran las instancias de esta clase: "Nombre: #{user}"(podremos definirlo como nombre+apellidos, o nick, o lo
que sea)
STRINGS
➤ Similares a otros lenguajes.➤ Muy enriquecidos con métodos útiles “de fábrica”.
Consultar documentación https://docs.ruby-lang.org/en/2.3.0/Array.html & https://docs.ruby-lang.org/en/2.3.0/Enumerable.html
ARRAYS
➤ Pares de key + value, en los que se busca usando la key para obtener el value asociado
HASHES
{ nil => "No se encuentra", 'A' => "Opción A", 'X' => AMOUNT * RATE}
(Explicación de informático a jefe de proyecto: correcto pero no muy útil)
¿Para qué sirven los hashes?
➤ Pares de key + value, en los que se busca usando la key para obtener el value asociado
➤ Útiles para implementar diccionarios de traducción
HASHES
ORDER_TO_BD = { 'cheap' => 'price', 'expensive' => 'price DESC', 'popular' => 'likes_count DESC'}order = ORDER_TO_BD[param_order] || 'created_at DESC'
PROVINCIA_API = { 'La Coruña' => 'A Coruña', 'Gerona' => 'Girona'}provincia = PROVINCIA_API[provincia_api] || provincia_api
➤ Pares de key + value, en los que se busca usando la key para obtener el value asociado
➤ Útiles para implementar diccionarios de traducción➤ O para convención sobre configuración
HASHES
DEFAULT_PAGINATE = { page: 1, per_page: 25, order: 'created_at'}
def pagination(custom_pagination = {}) options = DEFAULT_PAGINATE.merge(custom_pagination) first = 1 + (options[:page] - 1) * options[:per_page] ...end
➤ Pares de key + value, en los que se busca usando la key para obtener el value asociado
➤ Útiles para implementar diccionarios de traducción➤ O para convención sobre configuración➤ Fácil de convertir desde/hacia JSON, YAML, atributos de un
modelo, campos de la tabla en BD…
HASHES
➤ Se pueden enviar llamadas a atributos o métodos de una instancia componiendo dinámicamente su método
MÉTODOS DINÁMICOS
user.phone_1 = '963112233'user.phone_4 = '666111000'user.phone_2 = '678111000'
phones = (1..4).map do |i| user.send("phone_#{i}")end
=> ['963112233', '678111000', nil, '666111000']
➤ Se pueden enviar llamadas a atributos o métodos de una instancia componiendo dinámicamente su método
➤ Cuidado con la seguridad: si no son constantes, sino parámetros o valores de la BD, hay que usar whitelists
MÉTODOS DINÁMICOS
VALID_SECTIONS = %w(banca bolsa fondos)
def filter_by_section(param_section) return unless param_section.in?(VALID_SECTIONS) Message.send("in_#{param_section}") end
➤ Se pueden enviar llamadas a atributos o métodos de una instancia componiendo dinámicamente su método
➤ Cuidado con la seguridad: si no son constantes, sino parámetros o valores de la BD, hay que usar whitelists
➤ Útil para manejar items con gran cantidad de campos que siguen patrones en su nombre o que se comportan igual
MÉTODOS DINÁMICOS
➤ Se pueden enviar llamadas a atributos o métodos de una instancia componiendo dinámicamente su método
➤ Cuidado con la seguridad: si no son constantes, sino parámetros o valores de la BD, hay que usar whitelists
➤ Útil para manejar items con gran cantidad de campos que siguen patrones en su nombre o que se comportan igual
➤ En ocasiones es un smell: si muchos atributos se comportan de forma repetitiva, quizá se resuelva mejor usando atributos de tipo array, o una tabla con una relación 1-n
MÉTODOS DINÁMICOS
➤ Los métodos en Ruby retornan el valor de la última operación que se hizo
MÉTODOS
Asignación: el valor asignado a la variablereturn unless admin?: nil (default)return “No way!” unless admin?: “No way!”Llamada a otro método: el valor de retorno del otro método
➤ Los métodos en Ruby retornan el valor de la última operación que se hizo
➤ Se pueden pasar parámetros opcionales (al final) poniendo un default
MÉTODOS
def pictures(format, order = 'created_at desc', limit = nil) "Bring #{format} files sort #{order} max #{limit || 'all'}"end
item.pictures('jpg')item.pictures('jpg', 'likes_count desc')item.pictures('jpg', 'created_at desc', 20)
➤ Los métodos en Ruby retornan el valor de la última operación que se hizo
➤ Se pueden pasar parámetros opcionales (al final) poniendo un default
➤ Se puede reducir el acoplamiento (Connascence) con named parameters (aka keyword arguments)
MÉTODOS
def pictures(format:, order: 'created_at desc', limit: nil) "Bring #{format} files sort #{order} max #{limit || 'all'}"end
item.pictures(format: 'jpg')item.pictures(format: 'jpg', order: 'likes_count desc')item.pictures(format: 'jpg', limit: 20)