SlideShare una empresa de Scribd logo
1 de 59
Descargar para leer sin conexión
10 cosas de Rails que 
deberías saber 
Carlos Sánchez & Gabriel Ortuño 
MADRID · NOV 21-22 · 2014
MADRID · NOV 21-22 · 2014 
Carlos Sánchez Pérez 
Person.new( 
name: "Carlos Sánchez Pérez", 
job: "ASPgems", 
twitter: "carlossanchezp", 
github: "carlossanchezp", 
Blog: carlossanchezperez.wordpress.com")
MADRID · NOV 21-22 · 2014 
Gabriel Ortuño 
Person.new( 
name: "Gabriel Ortuño", 
job: "jobandtalent", 
web: "arctarus.com", 
twitter: "arctarus", 
github: "arctarus")
MADRID · NOV 21-22 · 2014 
Madrid.rb 
Group.new( 
name: "Madrid.rb", 
google_group: "madrid-rb", 
twitter: "madridrb", 
vimeo: "madridrb") 
¡El último jueves de cada mes en el Irish Rover!
MADRID · NOV 21-22 · 2014 
Ruby on Rails
MADRID · NOV 21-22 · 2014 
Rails 4 Features
MADRID · NOV 21-22 · 2014 
Hoja de Ruta 
1. ActiveSupport::Concern 
2. ActiveModel::Validator 
3. ActiveModel::Model 
4. ActiveSupport::Notifications 
5. ActionController::Renderer 
6. ActionController::Responder 
7. ActionController::Live 
8. ActionView::Resolver 
9. ActionMailer::Interceptor 
10. RackMiddleware
1. ActiveSupport::Concern 
¿Qué es? 
➔ Simple Syntactic Sugar sobre modulos de Ruby 
➔ Forma estándar de extender clases desde Rails 4.0 
¿Para qué se usa? 
➔ Agrupa métodos que definen una responsabilidad 
➔ Mejora cohesión 
➔ Permite reutilización 
MADRID · NOV 21-22 · 2014
# app/models/message.rb 
class Message < ActiveRecord::Base 
default_scope -> { where(trashed: false) } 
scope :trashed, -> { where(trashed: true) } 
MADRID · NOV 21-22 · 2014 
def trash 
update_attribute :trashed, true 
end 
end
MADRID · NOV 21-22 · 2014 
# app/models/concerns/trashable.rb 
module Trashable 
extend ActiveSupport::Concern 
included do 
default_scope -> { where(trashed: false) } 
scope :trashed, -> { where(trashed: true) } 
end 
def trash 
update_attribute :trashed, true 
end 
end
MADRID · NOV 21-22 · 2014 
# app/models/message.rb 
class Message < ActiveRecord::Base 
include Trashable, Subscribable, Commentable 
end 
# app/models/post.rb 
class Post < ActiveRecord::Base 
include Trashable, Commentable 
end
2. ActiveModel::Validator 
¿Qué es? 
➔ Es una clase base para implementar 
validadores que pueden ser usados por 
ActiveModel 
¿Para qué sirve? 
➔ Permite extraer lógica de validación de una 
MADRID · NOV 21-22 · 2014 
forma sencilla y reutilizable
MADRID · NOV 21-22 · 2014 
# app/models/user.rb 
class User < ActiveRecord::Base 
validates_format_of :email, with: 
A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]+z/ 
end
# lib/email_validator.rb 
class EmailValidator < ActiveModel::EachValidator 
MADRID · NOV 21-22 · 2014 
def validate_each(record, attribute, value) 
message = options.fetch :message, I18n.t("validators.email") 
unless value =~ /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})z/i 
record.errors[attribute] << message 
end 
end 
end
class Person < ActiveRecord::Base 
validates :email, presence: true, email: true 
end 
MADRID · NOV 21-22 · 2014
person = Person.new(email: 'user@gmail.com') 
person.valid? 
# ActiveModel ejecuta algo como.... 
validator = EmailValidator.new 
validator.validate_each(person, :email, 'user@gmail.com') 
MADRID · NOV 21-22 · 2014
3. ActiveModel::Model 
¿Qué es? 
➔ Incluir funcionalidades de ActiveModel::Model sobre 
MADRID · NOV 21-22 · 2014 
clases de Ruby 
➔ Naming, Translation, Validation, Conversions. 
¿Para qué se usa? 
➔ Crear una clase con validaciones 
➔ Utilizarla en las vistas
MADRID · NOV 21-22 · 2014 
class Contact 
include ActiveModel::Model 
attr_accessor :name, :email, :message 
validates :name, presence: true 
validates :email, presence: true, email: true 
validates :message, presence: true 
end
class ContactsController < ApplicationController 
def new... 
def create 
@contact = Contact.new(params[:contact]) 
if @contact.valid? 
ContactMailer.new_contact(@contact).deliver 
redirect_to root_path 
MADRID · NOV 21-22 · 2014 
else 
render :new 
end 
end 
end
MADRID · NOV 21-22 · 2014 
<h1>Contact Us</h1> 
<%= form_for @contact do |f| %> 
<%= f.label :name %> 
<%= f.text_field :name %> 
<%= f.label :email %> 
<%= f.email_field :email %> 
<%= f.label :message %> 
<%= f.text_area :message %> 
<%= f.submit %> 
<% end %>
4. ActiveSupport::Notifications 
¿Qué es? 
➔ Envio de notificaciones cuando se producen acciones 
MADRID · NOV 21-22 · 2014 
estándar. 
¿Para qué se usa? 
➔ Imagina que nos preguntamos “¿Por qué nuestra 
página es tan lenta?" 
➔ Cómo podemos utilizar las notificaciones para obtener 
las métricas.
# config/initializers/notification.rb 
ActiveSupport::Notifications.subscribe "process_action. 
action_controller" do|name,start,finish,id,payload| 
MADRID · NOV 21-22 · 2014 
PageRequest.create! do |page_request| 
page_request.path = payload[:path] 
page_request.page_duration = (finish - start) * 1000 
page_request.view_duration = payload[:view_runtime] 
page_request.db_duration = payload[:db_runtime] 
end 
end
MADRID · NOV 21-22 · 2014
MADRID · NOV 21-22 · 2014 
class Product < ActiveRecord::Base 
def self.search_by_name(text) 
ActiveSupport::Notifications.instrument( 
"products.search_by_name", 
search: text) 
where("name LIKE ?", "%#{text}%") 
end 
end
MADRID · NOV 21-22 · 2014 
# config/initializers/notification.rb 
ActiveSupport::Notifications.subscribe "products.search_by_name" 
do |name, start, finish, id, payload| 
Rails.logger.debug "SEARCH: #{payload[:search]}" 
end
5. ActionController::Renderer 
¿Qué es? 
➔ Un hook que expone el método render para 
MADRID · NOV 21-22 · 2014 
personalizar su comportamiento. 
¿Para qué se usa? 
➔ Nos permite devolver respuestas con formatos 
personalizados como csv, pdf, zip, etc.
MADRID · NOV 21-22 · 2014 
# app/controllers/csvable_controller.rb 
def show 
@csvable = Csvable.find(params[:id]) 
respond_to do |format| 
format.html 
format.csv { render csv: @csvable, filename: @csvable.name } 
end 
end
# lib/renderers/csv_renderer.rb 
ActionController::Renderers.add :csv do |obj, options| 
filename = options.fetch(:filename, 'data') 
str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s 
send_data str, type: Mime::CSV, 
disposition: "attachment; filename=#{filename}.csv" 
MADRID · NOV 21-22 · 2014 
end 
# config/initializer/mime_types.rb 
Mime::Type.register "text/csv", :csv
6. ActionController::Responder 
¿Qué es? 
➔ Abstrae como funciona los controllers según: 
◆ Tipo de request: HTML, XML, JSON 
◆ Verbo http usando: GET, POST, PUT, PATCH, DELETE 
◆ Estado del recurso: válido, con errores 
¿Para qué se usa? 
➔ Evita que repitamos lógica entre controladores 
➔ FlashResponder, HttpCacheResponder... 
MADRID · NOV 21-22 · 2014
MADRID · NOV 21-22 · 2014 
def create 
@user = User.new(params[:user]) 
respond_to do |format| 
if @user.save 
flash[:notice] = 'User was successfully created.' 
format.html { redirect_to @user } 
format.xml { render xml: @user, status: :created, 
location: @user } 
else 
format.html { render action: "new" } 
format.xml { render xml: @user.errors, 
status: :unprocessable_entity } 
end 
end 
end
MADRID · NOV 21-22 · 2014 
class UsersController < ApplicationController 
respond_to :html, :xml 
def create 
@user = User.new(params[:user]) 
flash[:notice] = 'User was successfully created.' if @user.save 
respond_with @user 
end 
end
# lib/flash_responder.rb 
class FlashResponder < ActionController::Responder 
def to_html 
MADRID · NOV 21-22 · 2014 
set_flash_message! unless get? 
super 
end 
private 
def set_flash_message! 
status = has_errors? ? :alert : :notice 
return if controller.flash[status].present? 
message = i18n_lookup(status) 
controller.flash[status] = message if message.present? 
end 
end
# app/controllers/application_controller.rb 
class ApplicationController < ActionController::Base 
self.responder = FlashResponder 
respond_to :html 
end 
MADRID · NOV 21-22 · 2014
7. ActionController::Live 
¿Qué es? 
➔ Módulo que permite el envío datos en streaming. 
➔ Requiere el uso un servidor como de Puma o Thin 
➔ ActionController::Live::SSE (Server Side Events) 
¿Para qué se usa? 
➔ Envio de datos al clientes sin necesidad de iniciar una 
MADRID · NOV 21-22 · 2014 
nueva request. 
ActionController::Live::SS
class MessagesController < ApplicationController 
MADRID · NOV 21-22 · 2014 
include ActionController::Live 
def events 
3.times do |n| 
response.stream.write "#{n}...nn" 
sleep 2 
end 
ensure 
response.stream.close 
end 
end
class MessagesController < ApplicationController 
include ActionController::Live 
MADRID · NOV 21-22 · 2014 
def create 
attributes = params.require(:message).permit(:content, :name) 
@message = Message.create!(attributes) 
$redis.publish('messages.create', @message.to_json) 
end 
end
MADRID · NOV 21-22 · 2014 
# app/controllers/messages_controller.rb 
def events 
response.headers['Content-Type'] = 'text/event-stream' 
sse = SSE.new(response.stream, event: "live.messages") 
$redis.psubscribe('messages.create') do |on| 
on.pmessage do |pattern, event, data| 
sse.write(data, event: event, retry: 500) 
end 
end 
ensure 
sse.close 
end
# app/assets/javascript/messages.js.coffee 
source = new EventSource('/messages/events') 
source.addEventListener 'live.messages', (e) -> 
message = $.parseJSON(e.data).message 
$('#chat').append($('<li>'). 
text("#{message.name}: #{message.content}")) 
MADRID · NOV 21-22 · 2014
8. ActionView::Resolver 
¿Qué es? 
➔ Es el responsable de encontrar el template que debe 
MADRID · NOV 21-22 · 2014 
ser renderizado. 
¿Para qué se usa? 
➔ Obtener templates directamente de la base de datos. 
➔ Modificar el directorio de vistas a renderizar en caso de 
no existir para el controlador actual. 
ActionController::Live::SS
# lib/admin/resolver.rb 
class Admin::Resolver < ::ActionView::FileSystemResolver 
def initialize 
MADRID · NOV 21-22 · 2014 
super("app/views") 
end 
def find_templates(name, prefix, partial, details) 
super(name, "admin/defaults", partial, details) 
end 
end
# app/controllers/admin/application_controller.rb 
class Admin::ApplicationController < ActionController::Base 
MADRID · NOV 21-22 · 2014 
append_view_path Admin::Resolver.new 
end
class SqlResolver < ActionView::Resolver 
def find_templates(name, prefix, partial, details) 
MADRID · NOV 21-22 · 2014 
conditions = { 
path: normalize_path(name, prefix, partial), 
locale: normalize_array(details[:locale]).first, 
format: normalize_array(details[:formats]).first, 
handler: normalize_array(details[:handlers]), 
partial: partial || false 
} 
::SqlTemplate.where(conditions).map do |record| 
initialize_template(record) 
end 
end 
end
9. ActionMailer::Interceptor 
¿Qué es? 
➔ Son hooks en el proceso de enviar emails 
➔ Podríamos decir que ActionMailer ofrece una forma de 
manipular los atributos de nuestros emails justo antes de su 
envío. 
¿Para qué se usa? 
➔ Un ejemplo sería si tenemos correos electrónicos de usuarios 
reales, modificar el destinatario y el asunto de un email de 
desarrollo. 
MADRID · NOV 21-22 · 2014
MADRID · NOV 21-22 · 2014 
class EnvironmentInterceptor 
def self.delivering_email(message) 
message.to = "myemail@example.com" 
message.subject = "#{Rails.env} #{message.subject}" 
end 
end
MADRID · NOV 21-22 · 2014 
# Ahora registramos nuestro interceptor: 
# config/initializers/mail.rb 
require 'environment_interceptor' 
unless Rails.env.production? 
ActionMailer::Base.register_interceptor(EnvironmentInterceptor) 
end
10. Rack Middleware 
¿Qué es? 
➔ Clase ruby que intercepta una request dentro de una 
Rack app y la procesa para acabar devolviendo una 
response. 
➔ Es una implementación de Pipeline Design Pattern 
¿Para que se usa? 
➔ Modificar cabeceras de la respuesta, caching, manage 
MADRID · NOV 21-22 · 2014 
exceptions, almacenar cookies, etc
MADRID · NOV 21-22 · 2014 
Rack 
Rack proporciona una interfaz 
mínima entre servidores web 
y frameworks Ruby
$ bin/rake middleware 
use Rack::Lock 
use Rack::Runtime 
use Rack::MethodOverride 
use ActionDispatch::RequestId 
use Rails::Rack::Logger 
use ActionDispatch::ShowExceptions 
use ActionDispatch::DebugExceptions 
use ActionDispatch::RemoteIp 
use ActionDispatch::Reloader 
use ActionDispatch::Callbacks 
use ActiveRecord::Migration::CheckPending 
use ActiveRecord::ConnectionAdapters::ConnectionManagement 
use ActiveRecord::QueryCache 
... 
MADRID · NOV 21-22 · 2014
MADRID · NOV 21-22 · 2014 
Simplest Rack Middleware 
class RackMiddleware 
def initialize(app) 
@app = app # Rack app 
end 
def call(env) 
status, headers, response = @app.call(env) 
... 
[status, headers, response] 
end 
end
require 'digest/md5' 
module Rack 
# Automatically sets the ETag header on all String bodies 
class ETag 
MADRID · NOV 21-22 · 2014 
def initialize(app) 
@app = app 
end 
def call(env) 
status, headers, body = @app.call(env) 
if !headers.has_key?('ETag') 
parts = [] 
body.each { |part| parts << part.to_s } 
headers['ETag'] = %("#{Digest::MD5.hexdigest(parts.join(""))}") 
[status, headers, parts] 
else 
[status, headers, body] 
end 
end 
end 
end
MADRID · NOV 21-22 · 2014 
# Rack::Etag 
def call(env) 
status, headers, body = @app.call(env) 
if !headers.has_key?('ETag') 
parts = [] 
body.each { |part| parts << part.to_s } 
etag = %("#{Digest::MD5.hexdigest(parts.join(""))}") 
headers['ETag'] = etag 
[status, headers, parts] 
else 
[status, headers, body] 
end 
end
MADRID · NOV 21-22 · 2014 
# config/application.rb 
# Push Rack::ETag at the bottom 
config.middleware.use Rack::ETag 
# Add Rack::ETag after ActiveRecord::QueryCache. 
config.middleware.insert_after ActiveRecord::QueryCache, 
Rack::ETag
Rails es adaptable a tus necesidades 
MADRID · NOV 21-22 · 2014
Domina las herramientas 
MADRID · NOV 21-22 · 2014 
que usas
MADRID · NOV 21-22 · 2014 
¡¡Gracias!!
MADRID · NOV 21-22 · 2014 
Referencias
ActiveSupport::Concern 
● Put chubby models on a diet with concerns : https://signalvnoise.com/posts/3372-put-chubby-models- 
MADRID · NOV 21-22 · 2014 
on-a-diet-with-concerns 
ActiveModel::Validator 
● Seven useful validator: http://viget.com/extend/seven-useful-activemodel-validators 
ActiveModel::Model 
● ActiveModel::Model [Rails 4 Countdown to 2013]: http://blog.remarkablelabs. 
com/2012/12/activemodel-model-rails-4-countdown-to-2013 
ActionController::Responder 
● http://blog.plataformatec.com.br/2009/08/embracing-rest-with-mind-body-and-soul/ 
● https://github.com/plataformatec/responders
ActionView::Resolver 
● Plataformatec: http://blog.plataformatec.com.br/2011/04/default-views-in-rails-3-0-with-custom-resolvers/ 
ActionController::Live 
● Railscast #401: http://railscasts.com/episodes/401-actioncontroller-live 
● Tenderlove, Is it live?: http://tenderlovemaking.com/2012/07/30/is-it-live.html 
Rack Middlewares 
● Railscast #151: http://railscasts.com/episodes/151-rack-middleware 
● Stackoverflow: http://stackoverflow.com/questions/2256569/what-is-rack-middleware 
● Amberit: https://www.amberbit.com/blog/2011/07/13/introduction-to-rack-middleware/ 
MADRID · NOV 21-22 · 2014
MADRID · NOV 21-22 · 2014 
¿Preguntas?

Más contenido relacionado

Destacado

TDD in the Web with Python and Django
TDD in the Web with Python and DjangoTDD in the Web with Python and Django
TDD in the Web with Python and DjangoCarlos Ble
 
Big data amb Cassandra i Celery ##bbmnk
Big data amb Cassandra i Celery ##bbmnkBig data amb Cassandra i Celery ##bbmnk
Big data amb Cassandra i Celery ##bbmnkSanti Camps
 
Introduccio a python
Introduccio a pythonIntroduccio a python
Introduccio a pythonSanti Camps
 
Knowing your Garbage Collector / Python Madrid
Knowing your Garbage Collector / Python MadridKnowing your Garbage Collector / Python Madrid
Knowing your Garbage Collector / Python Madridfcofdezc
 
BDD - Test Academy Barcelona 2017
BDD - Test Academy Barcelona 2017BDD - Test Academy Barcelona 2017
BDD - Test Academy Barcelona 2017Carlos Ble
 
Volunteering assistance to online geocoding services through a distributed kn...
Volunteering assistance to online geocoding services through a distributed kn...Volunteering assistance to online geocoding services through a distributed kn...
Volunteering assistance to online geocoding services through a distributed kn...José Pablo Gómez Barrón S.
 
#DataBeers: Inmersive Data Visualization con Oculus Rift
#DataBeers: Inmersive Data Visualization con Oculus Rift#DataBeers: Inmersive Data Visualization con Oculus Rift
#DataBeers: Inmersive Data Visualization con Oculus RiftOutliers Collective
 
El arte oscuro de estimar v3
El arte oscuro de estimar v3El arte oscuro de estimar v3
El arte oscuro de estimar v3Leonardo Soto
 
A Folksonomy of styles, aka: other stylists also said and Subjective Influenc...
A Folksonomy of styles, aka: other stylists also said and Subjective Influenc...A Folksonomy of styles, aka: other stylists also said and Subjective Influenc...
A Folksonomy of styles, aka: other stylists also said and Subjective Influenc...Natalia Díaz Rodríguez
 
Conferencia Big Data en #MenorcaConnecta
Conferencia Big Data en #MenorcaConnectaConferencia Big Data en #MenorcaConnecta
Conferencia Big Data en #MenorcaConnectaSanti Camps
 
PyQgis gpul-lab Univerisity of A Coruña 20160413
PyQgis gpul-lab Univerisity of A Coruña 20160413PyQgis gpul-lab Univerisity of A Coruña 20160413
PyQgis gpul-lab Univerisity of A Coruña 20160413Luigi Pirelli
 

Destacado (19)

TDD in the Web with Python and Django
TDD in the Web with Python and DjangoTDD in the Web with Python and Django
TDD in the Web with Python and Django
 
Big data amb Cassandra i Celery ##bbmnk
Big data amb Cassandra i Celery ##bbmnkBig data amb Cassandra i Celery ##bbmnk
Big data amb Cassandra i Celery ##bbmnk
 
Introduccio a python
Introduccio a pythonIntroduccio a python
Introduccio a python
 
Python and MongoDB
Python and MongoDB Python and MongoDB
Python and MongoDB
 
Knowing your Garbage Collector / Python Madrid
Knowing your Garbage Collector / Python MadridKnowing your Garbage Collector / Python Madrid
Knowing your Garbage Collector / Python Madrid
 
BDD - Test Academy Barcelona 2017
BDD - Test Academy Barcelona 2017BDD - Test Academy Barcelona 2017
BDD - Test Academy Barcelona 2017
 
Volunteering assistance to online geocoding services through a distributed kn...
Volunteering assistance to online geocoding services through a distributed kn...Volunteering assistance to online geocoding services through a distributed kn...
Volunteering assistance to online geocoding services through a distributed kn...
 
#DataBeers: Inmersive Data Visualization con Oculus Rift
#DataBeers: Inmersive Data Visualization con Oculus Rift#DataBeers: Inmersive Data Visualization con Oculus Rift
#DataBeers: Inmersive Data Visualization con Oculus Rift
 
El arte oscuro de estimar v3
El arte oscuro de estimar v3El arte oscuro de estimar v3
El arte oscuro de estimar v3
 
Zotero
ZoteroZotero
Zotero
 
A Folksonomy of styles, aka: other stylists also said and Subjective Influenc...
A Folksonomy of styles, aka: other stylists also said and Subjective Influenc...A Folksonomy of styles, aka: other stylists also said and Subjective Influenc...
A Folksonomy of styles, aka: other stylists also said and Subjective Influenc...
 
Madrid SPARQL handson
Madrid SPARQL handsonMadrid SPARQL handson
Madrid SPARQL handson
 
Conferencia Big Data en #MenorcaConnecta
Conferencia Big Data en #MenorcaConnectaConferencia Big Data en #MenorcaConnecta
Conferencia Big Data en #MenorcaConnecta
 
Presentacion scraping
Presentacion scrapingPresentacion scraping
Presentacion scraping
 
Grunt.js introduction
Grunt.js introductionGrunt.js introduction
Grunt.js introduction
 
PyQgis gpul-lab Univerisity of A Coruña 20160413
PyQgis gpul-lab Univerisity of A Coruña 20160413PyQgis gpul-lab Univerisity of A Coruña 20160413
PyQgis gpul-lab Univerisity of A Coruña 20160413
 
Charla mspba
Charla mspbaCharla mspba
Charla mspba
 
Guía de Python
Guía de Python Guía de Python
Guía de Python
 
Bucles con Scratch
Bucles con ScratchBucles con Scratch
Bucles con Scratch
 

Similar a 10 cosas de rails que deberías saber

ASP.NET vNext... Desarrollo cross platform
ASP.NET vNext... Desarrollo cross platformASP.NET vNext... Desarrollo cross platform
ASP.NET vNext... Desarrollo cross platformEduard Tomàs
 
Tecnologías para microservicios
Tecnologías para microserviciosTecnologías para microservicios
Tecnologías para microserviciosPedro J. Molina
 
WordPress como back-end de nuestras apps
WordPress como back-end de nuestras appsWordPress como back-end de nuestras apps
WordPress como back-end de nuestras appsJaime Fernández
 
Carrera de fondo - La continuada lucha de AngularJS - CodeMotion 2015
Carrera de fondo - La continuada lucha de AngularJS - CodeMotion 2015Carrera de fondo - La continuada lucha de AngularJS - CodeMotion 2015
Carrera de fondo - La continuada lucha de AngularJS - CodeMotion 2015José Manuel García García
 
Aplicaciones escalables en la nube: mentiras y verdades
Aplicaciones escalables en la nube: mentiras y verdadesAplicaciones escalables en la nube: mentiras y verdades
Aplicaciones escalables en la nube: mentiras y verdadesEnrique Catala Bañuls
 
Cuando los desarrolladores conocieron SSAS, Business Intelligence y Big Data
Cuando los desarrolladores conocieron SSAS, Business Intelligence y Big DataCuando los desarrolladores conocieron SSAS, Business Intelligence y Big Data
Cuando los desarrolladores conocieron SSAS, Business Intelligence y Big DataRuben Pertusa Lopez
 
App todo gas: WordPress no es solo para web
App todo gas: WordPress no es solo para webApp todo gas: WordPress no es solo para web
App todo gas: WordPress no es solo para webPaco Marchante
 
Descubriendo Ruby on Rails (Desarrollo Agil de Aplicaciones Web)
Descubriendo Ruby on Rails (Desarrollo Agil de Aplicaciones Web)Descubriendo Ruby on Rails (Desarrollo Agil de Aplicaciones Web)
Descubriendo Ruby on Rails (Desarrollo Agil de Aplicaciones Web)lenny
 
Descubriendo Ruby On Rails (Desarrollo Agil De Aplicaciones Web)
Descubriendo Ruby On Rails (Desarrollo Agil De Aplicaciones Web)Descubriendo Ruby On Rails (Desarrollo Agil De Aplicaciones Web)
Descubriendo Ruby On Rails (Desarrollo Agil De Aplicaciones Web)INSIGNIA4U
 
Presentación Ruby on Rails en Softare Freedom Day 09 Buenos Aires
Presentación Ruby on Rails en Softare Freedom Day 09 Buenos AiresPresentación Ruby on Rails en Softare Freedom Day 09 Buenos Aires
Presentación Ruby on Rails en Softare Freedom Day 09 Buenos Airespeterpunk
 
Balotario resuelto
Balotario resueltoBalotario resuelto
Balotario resueltoAlexiToxD
 
Presentacion Ruby on Rails en Universidad Autónoma 2009
Presentacion Ruby on Rails en Universidad Autónoma 2009Presentacion Ruby on Rails en Universidad Autónoma 2009
Presentacion Ruby on Rails en Universidad Autónoma 2009Nelson Rojas Núñez
 
Introducción a NodeJS
Introducción a NodeJSIntroducción a NodeJS
Introducción a NodeJSBEEVA_es
 
Desarrollo de aplicaciones web usando Catalyst y jQuery
Desarrollo de aplicaciones web usando Catalyst y jQueryDesarrollo de aplicaciones web usando Catalyst y jQuery
Desarrollo de aplicaciones web usando Catalyst y jQueryJavier P.
 
Programa en Rails como si Jugases con Lego. Javier Ramirez
Programa en Rails como si Jugases con Lego. Javier RamirezPrograma en Rails como si Jugases con Lego. Javier Ramirez
Programa en Rails como si Jugases con Lego. Javier Ramirezjavier ramirez
 

Similar a 10 cosas de rails que deberías saber (20)

ASP.NET vNext... Desarrollo cross platform
ASP.NET vNext... Desarrollo cross platformASP.NET vNext... Desarrollo cross platform
ASP.NET vNext... Desarrollo cross platform
 
Tecnologías para microservicios
Tecnologías para microserviciosTecnologías para microservicios
Tecnologías para microservicios
 
Codemotion 2014 Scala @real life
Codemotion 2014 Scala @real lifeCodemotion 2014 Scala @real life
Codemotion 2014 Scala @real life
 
Scala @ Real Life Codemotion 2014
Scala @ Real Life Codemotion 2014Scala @ Real Life Codemotion 2014
Scala @ Real Life Codemotion 2014
 
WordPress como back-end de nuestras apps
WordPress como back-end de nuestras appsWordPress como back-end de nuestras apps
WordPress como back-end de nuestras apps
 
Carrera de fondo - La continuada lucha de AngularJS - CodeMotion 2015
Carrera de fondo - La continuada lucha de AngularJS - CodeMotion 2015Carrera de fondo - La continuada lucha de AngularJS - CodeMotion 2015
Carrera de fondo - La continuada lucha de AngularJS - CodeMotion 2015
 
Aplicaciones escalables en la nube: mentiras y verdades
Aplicaciones escalables en la nube: mentiras y verdadesAplicaciones escalables en la nube: mentiras y verdades
Aplicaciones escalables en la nube: mentiras y verdades
 
Cuando los desarrolladores conocieron SSAS, Business Intelligence y Big Data
Cuando los desarrolladores conocieron SSAS, Business Intelligence y Big DataCuando los desarrolladores conocieron SSAS, Business Intelligence y Big Data
Cuando los desarrolladores conocieron SSAS, Business Intelligence y Big Data
 
App todo gas: WordPress no es solo para web
App todo gas: WordPress no es solo para webApp todo gas: WordPress no es solo para web
App todo gas: WordPress no es solo para web
 
Del infierno al cielo
Del infierno al cieloDel infierno al cielo
Del infierno al cielo
 
Descubriendo Ruby on Rails (Desarrollo Agil de Aplicaciones Web)
Descubriendo Ruby on Rails (Desarrollo Agil de Aplicaciones Web)Descubriendo Ruby on Rails (Desarrollo Agil de Aplicaciones Web)
Descubriendo Ruby on Rails (Desarrollo Agil de Aplicaciones Web)
 
Descubriendo Ruby On Rails (Desarrollo Agil De Aplicaciones Web)
Descubriendo Ruby On Rails (Desarrollo Agil De Aplicaciones Web)Descubriendo Ruby On Rails (Desarrollo Agil De Aplicaciones Web)
Descubriendo Ruby On Rails (Desarrollo Agil De Aplicaciones Web)
 
6.angular js
6.angular js6.angular js
6.angular js
 
Presentación Ruby on Rails en Softare Freedom Day 09 Buenos Aires
Presentación Ruby on Rails en Softare Freedom Day 09 Buenos AiresPresentación Ruby on Rails en Softare Freedom Day 09 Buenos Aires
Presentación Ruby on Rails en Softare Freedom Day 09 Buenos Aires
 
Servicios web
Servicios webServicios web
Servicios web
 
Balotario resuelto
Balotario resueltoBalotario resuelto
Balotario resuelto
 
Presentacion Ruby on Rails en Universidad Autónoma 2009
Presentacion Ruby on Rails en Universidad Autónoma 2009Presentacion Ruby on Rails en Universidad Autónoma 2009
Presentacion Ruby on Rails en Universidad Autónoma 2009
 
Introducción a NodeJS
Introducción a NodeJSIntroducción a NodeJS
Introducción a NodeJS
 
Desarrollo de aplicaciones web usando Catalyst y jQuery
Desarrollo de aplicaciones web usando Catalyst y jQueryDesarrollo de aplicaciones web usando Catalyst y jQuery
Desarrollo de aplicaciones web usando Catalyst y jQuery
 
Programa en Rails como si Jugases con Lego. Javier Ramirez
Programa en Rails como si Jugases con Lego. Javier RamirezPrograma en Rails como si Jugases con Lego. Javier Ramirez
Programa en Rails como si Jugases con Lego. Javier Ramirez
 

Último

institucion educativa la esperanza sede magdalena
institucion educativa la esperanza sede magdalenainstitucion educativa la esperanza sede magdalena
institucion educativa la esperanza sede magdalenajuniorcuellargomez
 
INSTITUCION EDUCATIVA LA ESPERANZA SEDE MAGDALENA
INSTITUCION EDUCATIVA LA ESPERANZA SEDE MAGDALENAINSTITUCION EDUCATIVA LA ESPERANZA SEDE MAGDALENA
INSTITUCION EDUCATIVA LA ESPERANZA SEDE MAGDALENAdanielaerazok
 
Institucion educativa la esperanza sede la magdalena
Institucion educativa la esperanza sede la magdalenaInstitucion educativa la esperanza sede la magdalena
Institucion educativa la esperanza sede la magdalenadanielaerazok
 
Buscadores, SEM SEO: el desafío de ser visto en la web
Buscadores, SEM SEO: el desafío de ser visto en la webBuscadores, SEM SEO: el desafío de ser visto en la web
Buscadores, SEM SEO: el desafío de ser visto en la webDecaunlz
 
COMPETENCIAS CIUDADANASadadadadadadada .pdf
COMPETENCIAS CIUDADANASadadadadadadada .pdfCOMPETENCIAS CIUDADANASadadadadadadada .pdf
COMPETENCIAS CIUDADANASadadadadadadada .pdfOscarBlas6
 
NUVO PROGRAMAS DE ESCUELAS NUEVO-ACUERDO-CTE.pdf
NUVO PROGRAMAS DE ESCUELAS NUEVO-ACUERDO-CTE.pdfNUVO PROGRAMAS DE ESCUELAS NUEVO-ACUERDO-CTE.pdf
NUVO PROGRAMAS DE ESCUELAS NUEVO-ACUERDO-CTE.pdfisrael garcia
 
12 Clasificacion de las Computadoras.pdf
12 Clasificacion de las Computadoras.pdf12 Clasificacion de las Computadoras.pdf
12 Clasificacion de las Computadoras.pdfedwinmelgarschlink2
 
Guia para el registro en el sitio slideshare.pdf
Guia para el registro en el sitio slideshare.pdfGuia para el registro en el sitio slideshare.pdf
Guia para el registro en el sitio slideshare.pdflauradbernals
 

Último (8)

institucion educativa la esperanza sede magdalena
institucion educativa la esperanza sede magdalenainstitucion educativa la esperanza sede magdalena
institucion educativa la esperanza sede magdalena
 
INSTITUCION EDUCATIVA LA ESPERANZA SEDE MAGDALENA
INSTITUCION EDUCATIVA LA ESPERANZA SEDE MAGDALENAINSTITUCION EDUCATIVA LA ESPERANZA SEDE MAGDALENA
INSTITUCION EDUCATIVA LA ESPERANZA SEDE MAGDALENA
 
Institucion educativa la esperanza sede la magdalena
Institucion educativa la esperanza sede la magdalenaInstitucion educativa la esperanza sede la magdalena
Institucion educativa la esperanza sede la magdalena
 
Buscadores, SEM SEO: el desafío de ser visto en la web
Buscadores, SEM SEO: el desafío de ser visto en la webBuscadores, SEM SEO: el desafío de ser visto en la web
Buscadores, SEM SEO: el desafío de ser visto en la web
 
COMPETENCIAS CIUDADANASadadadadadadada .pdf
COMPETENCIAS CIUDADANASadadadadadadada .pdfCOMPETENCIAS CIUDADANASadadadadadadada .pdf
COMPETENCIAS CIUDADANASadadadadadadada .pdf
 
NUVO PROGRAMAS DE ESCUELAS NUEVO-ACUERDO-CTE.pdf
NUVO PROGRAMAS DE ESCUELAS NUEVO-ACUERDO-CTE.pdfNUVO PROGRAMAS DE ESCUELAS NUEVO-ACUERDO-CTE.pdf
NUVO PROGRAMAS DE ESCUELAS NUEVO-ACUERDO-CTE.pdf
 
12 Clasificacion de las Computadoras.pdf
12 Clasificacion de las Computadoras.pdf12 Clasificacion de las Computadoras.pdf
12 Clasificacion de las Computadoras.pdf
 
Guia para el registro en el sitio slideshare.pdf
Guia para el registro en el sitio slideshare.pdfGuia para el registro en el sitio slideshare.pdf
Guia para el registro en el sitio slideshare.pdf
 

10 cosas de rails que deberías saber

  • 1. 10 cosas de Rails que deberías saber Carlos Sánchez & Gabriel Ortuño MADRID · NOV 21-22 · 2014
  • 2. MADRID · NOV 21-22 · 2014 Carlos Sánchez Pérez Person.new( name: "Carlos Sánchez Pérez", job: "ASPgems", twitter: "carlossanchezp", github: "carlossanchezp", Blog: carlossanchezperez.wordpress.com")
  • 3. MADRID · NOV 21-22 · 2014 Gabriel Ortuño Person.new( name: "Gabriel Ortuño", job: "jobandtalent", web: "arctarus.com", twitter: "arctarus", github: "arctarus")
  • 4. MADRID · NOV 21-22 · 2014 Madrid.rb Group.new( name: "Madrid.rb", google_group: "madrid-rb", twitter: "madridrb", vimeo: "madridrb") ¡El último jueves de cada mes en el Irish Rover!
  • 5. MADRID · NOV 21-22 · 2014 Ruby on Rails
  • 6. MADRID · NOV 21-22 · 2014 Rails 4 Features
  • 7. MADRID · NOV 21-22 · 2014 Hoja de Ruta 1. ActiveSupport::Concern 2. ActiveModel::Validator 3. ActiveModel::Model 4. ActiveSupport::Notifications 5. ActionController::Renderer 6. ActionController::Responder 7. ActionController::Live 8. ActionView::Resolver 9. ActionMailer::Interceptor 10. RackMiddleware
  • 8. 1. ActiveSupport::Concern ¿Qué es? ➔ Simple Syntactic Sugar sobre modulos de Ruby ➔ Forma estándar de extender clases desde Rails 4.0 ¿Para qué se usa? ➔ Agrupa métodos que definen una responsabilidad ➔ Mejora cohesión ➔ Permite reutilización MADRID · NOV 21-22 · 2014
  • 9. # app/models/message.rb class Message < ActiveRecord::Base default_scope -> { where(trashed: false) } scope :trashed, -> { where(trashed: true) } MADRID · NOV 21-22 · 2014 def trash update_attribute :trashed, true end end
  • 10. MADRID · NOV 21-22 · 2014 # app/models/concerns/trashable.rb module Trashable extend ActiveSupport::Concern included do default_scope -> { where(trashed: false) } scope :trashed, -> { where(trashed: true) } end def trash update_attribute :trashed, true end end
  • 11. MADRID · NOV 21-22 · 2014 # app/models/message.rb class Message < ActiveRecord::Base include Trashable, Subscribable, Commentable end # app/models/post.rb class Post < ActiveRecord::Base include Trashable, Commentable end
  • 12. 2. ActiveModel::Validator ¿Qué es? ➔ Es una clase base para implementar validadores que pueden ser usados por ActiveModel ¿Para qué sirve? ➔ Permite extraer lógica de validación de una MADRID · NOV 21-22 · 2014 forma sencilla y reutilizable
  • 13. MADRID · NOV 21-22 · 2014 # app/models/user.rb class User < ActiveRecord::Base validates_format_of :email, with: A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]+z/ end
  • 14. # lib/email_validator.rb class EmailValidator < ActiveModel::EachValidator MADRID · NOV 21-22 · 2014 def validate_each(record, attribute, value) message = options.fetch :message, I18n.t("validators.email") unless value =~ /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})z/i record.errors[attribute] << message end end end
  • 15. class Person < ActiveRecord::Base validates :email, presence: true, email: true end MADRID · NOV 21-22 · 2014
  • 16. person = Person.new(email: 'user@gmail.com') person.valid? # ActiveModel ejecuta algo como.... validator = EmailValidator.new validator.validate_each(person, :email, 'user@gmail.com') MADRID · NOV 21-22 · 2014
  • 17. 3. ActiveModel::Model ¿Qué es? ➔ Incluir funcionalidades de ActiveModel::Model sobre MADRID · NOV 21-22 · 2014 clases de Ruby ➔ Naming, Translation, Validation, Conversions. ¿Para qué se usa? ➔ Crear una clase con validaciones ➔ Utilizarla en las vistas
  • 18. MADRID · NOV 21-22 · 2014 class Contact include ActiveModel::Model attr_accessor :name, :email, :message validates :name, presence: true validates :email, presence: true, email: true validates :message, presence: true end
  • 19. class ContactsController < ApplicationController def new... def create @contact = Contact.new(params[:contact]) if @contact.valid? ContactMailer.new_contact(@contact).deliver redirect_to root_path MADRID · NOV 21-22 · 2014 else render :new end end end
  • 20. MADRID · NOV 21-22 · 2014 <h1>Contact Us</h1> <%= form_for @contact do |f| %> <%= f.label :name %> <%= f.text_field :name %> <%= f.label :email %> <%= f.email_field :email %> <%= f.label :message %> <%= f.text_area :message %> <%= f.submit %> <% end %>
  • 21. 4. ActiveSupport::Notifications ¿Qué es? ➔ Envio de notificaciones cuando se producen acciones MADRID · NOV 21-22 · 2014 estándar. ¿Para qué se usa? ➔ Imagina que nos preguntamos “¿Por qué nuestra página es tan lenta?" ➔ Cómo podemos utilizar las notificaciones para obtener las métricas.
  • 22. # config/initializers/notification.rb ActiveSupport::Notifications.subscribe "process_action. action_controller" do|name,start,finish,id,payload| MADRID · NOV 21-22 · 2014 PageRequest.create! do |page_request| page_request.path = payload[:path] page_request.page_duration = (finish - start) * 1000 page_request.view_duration = payload[:view_runtime] page_request.db_duration = payload[:db_runtime] end end
  • 23. MADRID · NOV 21-22 · 2014
  • 24. MADRID · NOV 21-22 · 2014 class Product < ActiveRecord::Base def self.search_by_name(text) ActiveSupport::Notifications.instrument( "products.search_by_name", search: text) where("name LIKE ?", "%#{text}%") end end
  • 25. MADRID · NOV 21-22 · 2014 # config/initializers/notification.rb ActiveSupport::Notifications.subscribe "products.search_by_name" do |name, start, finish, id, payload| Rails.logger.debug "SEARCH: #{payload[:search]}" end
  • 26. 5. ActionController::Renderer ¿Qué es? ➔ Un hook que expone el método render para MADRID · NOV 21-22 · 2014 personalizar su comportamiento. ¿Para qué se usa? ➔ Nos permite devolver respuestas con formatos personalizados como csv, pdf, zip, etc.
  • 27. MADRID · NOV 21-22 · 2014 # app/controllers/csvable_controller.rb def show @csvable = Csvable.find(params[:id]) respond_to do |format| format.html format.csv { render csv: @csvable, filename: @csvable.name } end end
  • 28. # lib/renderers/csv_renderer.rb ActionController::Renderers.add :csv do |obj, options| filename = options.fetch(:filename, 'data') str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s send_data str, type: Mime::CSV, disposition: "attachment; filename=#{filename}.csv" MADRID · NOV 21-22 · 2014 end # config/initializer/mime_types.rb Mime::Type.register "text/csv", :csv
  • 29. 6. ActionController::Responder ¿Qué es? ➔ Abstrae como funciona los controllers según: ◆ Tipo de request: HTML, XML, JSON ◆ Verbo http usando: GET, POST, PUT, PATCH, DELETE ◆ Estado del recurso: válido, con errores ¿Para qué se usa? ➔ Evita que repitamos lógica entre controladores ➔ FlashResponder, HttpCacheResponder... MADRID · NOV 21-22 · 2014
  • 30. MADRID · NOV 21-22 · 2014 def create @user = User.new(params[:user]) respond_to do |format| if @user.save flash[:notice] = 'User was successfully created.' format.html { redirect_to @user } format.xml { render xml: @user, status: :created, location: @user } else format.html { render action: "new" } format.xml { render xml: @user.errors, status: :unprocessable_entity } end end end
  • 31. MADRID · NOV 21-22 · 2014 class UsersController < ApplicationController respond_to :html, :xml def create @user = User.new(params[:user]) flash[:notice] = 'User was successfully created.' if @user.save respond_with @user end end
  • 32. # lib/flash_responder.rb class FlashResponder < ActionController::Responder def to_html MADRID · NOV 21-22 · 2014 set_flash_message! unless get? super end private def set_flash_message! status = has_errors? ? :alert : :notice return if controller.flash[status].present? message = i18n_lookup(status) controller.flash[status] = message if message.present? end end
  • 33. # app/controllers/application_controller.rb class ApplicationController < ActionController::Base self.responder = FlashResponder respond_to :html end MADRID · NOV 21-22 · 2014
  • 34. 7. ActionController::Live ¿Qué es? ➔ Módulo que permite el envío datos en streaming. ➔ Requiere el uso un servidor como de Puma o Thin ➔ ActionController::Live::SSE (Server Side Events) ¿Para qué se usa? ➔ Envio de datos al clientes sin necesidad de iniciar una MADRID · NOV 21-22 · 2014 nueva request. ActionController::Live::SS
  • 35. class MessagesController < ApplicationController MADRID · NOV 21-22 · 2014 include ActionController::Live def events 3.times do |n| response.stream.write "#{n}...nn" sleep 2 end ensure response.stream.close end end
  • 36. class MessagesController < ApplicationController include ActionController::Live MADRID · NOV 21-22 · 2014 def create attributes = params.require(:message).permit(:content, :name) @message = Message.create!(attributes) $redis.publish('messages.create', @message.to_json) end end
  • 37. MADRID · NOV 21-22 · 2014 # app/controllers/messages_controller.rb def events response.headers['Content-Type'] = 'text/event-stream' sse = SSE.new(response.stream, event: "live.messages") $redis.psubscribe('messages.create') do |on| on.pmessage do |pattern, event, data| sse.write(data, event: event, retry: 500) end end ensure sse.close end
  • 38. # app/assets/javascript/messages.js.coffee source = new EventSource('/messages/events') source.addEventListener 'live.messages', (e) -> message = $.parseJSON(e.data).message $('#chat').append($('<li>'). text("#{message.name}: #{message.content}")) MADRID · NOV 21-22 · 2014
  • 39. 8. ActionView::Resolver ¿Qué es? ➔ Es el responsable de encontrar el template que debe MADRID · NOV 21-22 · 2014 ser renderizado. ¿Para qué se usa? ➔ Obtener templates directamente de la base de datos. ➔ Modificar el directorio de vistas a renderizar en caso de no existir para el controlador actual. ActionController::Live::SS
  • 40. # lib/admin/resolver.rb class Admin::Resolver < ::ActionView::FileSystemResolver def initialize MADRID · NOV 21-22 · 2014 super("app/views") end def find_templates(name, prefix, partial, details) super(name, "admin/defaults", partial, details) end end
  • 41. # app/controllers/admin/application_controller.rb class Admin::ApplicationController < ActionController::Base MADRID · NOV 21-22 · 2014 append_view_path Admin::Resolver.new end
  • 42. class SqlResolver < ActionView::Resolver def find_templates(name, prefix, partial, details) MADRID · NOV 21-22 · 2014 conditions = { path: normalize_path(name, prefix, partial), locale: normalize_array(details[:locale]).first, format: normalize_array(details[:formats]).first, handler: normalize_array(details[:handlers]), partial: partial || false } ::SqlTemplate.where(conditions).map do |record| initialize_template(record) end end end
  • 43. 9. ActionMailer::Interceptor ¿Qué es? ➔ Son hooks en el proceso de enviar emails ➔ Podríamos decir que ActionMailer ofrece una forma de manipular los atributos de nuestros emails justo antes de su envío. ¿Para qué se usa? ➔ Un ejemplo sería si tenemos correos electrónicos de usuarios reales, modificar el destinatario y el asunto de un email de desarrollo. MADRID · NOV 21-22 · 2014
  • 44. MADRID · NOV 21-22 · 2014 class EnvironmentInterceptor def self.delivering_email(message) message.to = "myemail@example.com" message.subject = "#{Rails.env} #{message.subject}" end end
  • 45. MADRID · NOV 21-22 · 2014 # Ahora registramos nuestro interceptor: # config/initializers/mail.rb require 'environment_interceptor' unless Rails.env.production? ActionMailer::Base.register_interceptor(EnvironmentInterceptor) end
  • 46. 10. Rack Middleware ¿Qué es? ➔ Clase ruby que intercepta una request dentro de una Rack app y la procesa para acabar devolviendo una response. ➔ Es una implementación de Pipeline Design Pattern ¿Para que se usa? ➔ Modificar cabeceras de la respuesta, caching, manage MADRID · NOV 21-22 · 2014 exceptions, almacenar cookies, etc
  • 47. MADRID · NOV 21-22 · 2014 Rack Rack proporciona una interfaz mínima entre servidores web y frameworks Ruby
  • 48. $ bin/rake middleware use Rack::Lock use Rack::Runtime use Rack::MethodOverride use ActionDispatch::RequestId use Rails::Rack::Logger use ActionDispatch::ShowExceptions use ActionDispatch::DebugExceptions use ActionDispatch::RemoteIp use ActionDispatch::Reloader use ActionDispatch::Callbacks use ActiveRecord::Migration::CheckPending use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache ... MADRID · NOV 21-22 · 2014
  • 49. MADRID · NOV 21-22 · 2014 Simplest Rack Middleware class RackMiddleware def initialize(app) @app = app # Rack app end def call(env) status, headers, response = @app.call(env) ... [status, headers, response] end end
  • 50. require 'digest/md5' module Rack # Automatically sets the ETag header on all String bodies class ETag MADRID · NOV 21-22 · 2014 def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) if !headers.has_key?('ETag') parts = [] body.each { |part| parts << part.to_s } headers['ETag'] = %("#{Digest::MD5.hexdigest(parts.join(""))}") [status, headers, parts] else [status, headers, body] end end end end
  • 51. MADRID · NOV 21-22 · 2014 # Rack::Etag def call(env) status, headers, body = @app.call(env) if !headers.has_key?('ETag') parts = [] body.each { |part| parts << part.to_s } etag = %("#{Digest::MD5.hexdigest(parts.join(""))}") headers['ETag'] = etag [status, headers, parts] else [status, headers, body] end end
  • 52. MADRID · NOV 21-22 · 2014 # config/application.rb # Push Rack::ETag at the bottom config.middleware.use Rack::ETag # Add Rack::ETag after ActiveRecord::QueryCache. config.middleware.insert_after ActiveRecord::QueryCache, Rack::ETag
  • 53. Rails es adaptable a tus necesidades MADRID · NOV 21-22 · 2014
  • 54. Domina las herramientas MADRID · NOV 21-22 · 2014 que usas
  • 55. MADRID · NOV 21-22 · 2014 ¡¡Gracias!!
  • 56. MADRID · NOV 21-22 · 2014 Referencias
  • 57. ActiveSupport::Concern ● Put chubby models on a diet with concerns : https://signalvnoise.com/posts/3372-put-chubby-models- MADRID · NOV 21-22 · 2014 on-a-diet-with-concerns ActiveModel::Validator ● Seven useful validator: http://viget.com/extend/seven-useful-activemodel-validators ActiveModel::Model ● ActiveModel::Model [Rails 4 Countdown to 2013]: http://blog.remarkablelabs. com/2012/12/activemodel-model-rails-4-countdown-to-2013 ActionController::Responder ● http://blog.plataformatec.com.br/2009/08/embracing-rest-with-mind-body-and-soul/ ● https://github.com/plataformatec/responders
  • 58. ActionView::Resolver ● Plataformatec: http://blog.plataformatec.com.br/2011/04/default-views-in-rails-3-0-with-custom-resolvers/ ActionController::Live ● Railscast #401: http://railscasts.com/episodes/401-actioncontroller-live ● Tenderlove, Is it live?: http://tenderlovemaking.com/2012/07/30/is-it-live.html Rack Middlewares ● Railscast #151: http://railscasts.com/episodes/151-rack-middleware ● Stackoverflow: http://stackoverflow.com/questions/2256569/what-is-rack-middleware ● Amberit: https://www.amberbit.com/blog/2011/07/13/introduction-to-rack-middleware/ MADRID · NOV 21-22 · 2014
  • 59. MADRID · NOV 21-22 · 2014 ¿Preguntas?