O que há de novo no Rails 3 - Ruby on Rails no Mundo Real - 23may2010

2,735 views
2,684 views

Published on

Palestra realizada por Hugo Baraúna (@hugobarauna) no evento Ruby on Rails no Mundo Real, em 23 de Maio de 2010 na cidade de São Paulo.

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,735
On SlideShare
0
From Embeds
0
Number of Embeds
938
Actions
Shares
0
Downloads
31
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

O que há de novo no Rails 3 - Ruby on Rails no Mundo Real - 23may2010

  1. 1. Rails 3 Hugo Baraúna blog.plataformatec.com @hugobarauna
  2. 2. Rails 3 ID blog twitter Hugo Baraúna blog.plataformatec.com @hugobarauna
  3. 3. Quem sou eu? • Hugo Baraúna • 24 anos • Engenharia de Computação na Politécnica da USP • Desenvolvedor Ruby e Rails há mais de 3 anos • Co-fundador e engenheiro da Plataforma Tecnologia Hugo Baraúna blog.plataformatec.com @hugobarauna
  4. 4. Hugo Baraúna blog.plataformatec.com @hugobarauna
  5. 5. Desevolvemos aplicações em Rails Coaching em Consultoria Rails e Agile Hugo Baraúna blog.plataformatec.com @hugobarauna
  6. 6. Arquitetura Rails 3 Rails ActionDispatch ActiveSupport Hugo Baraúna blog.plataformatec.com @hugobarauna
  7. 7. Arquitetura Todo o resto são Rails 3 Railties! Rails ActionDispatch ActiveSupport Hugo Baraúna blog.plataformatec.com @hugobarauna
  8. 8. Arquitetura Todo o resto são Rails 3 Railties! ActiveRecord Rails ActionView ActionDispatch outros... ActiveSupport ActionController ActionMailer Hugo Baraúna blog.plataformatec.com @hugobarauna
  9. 9. Vantagens do Rails 3 Hugo Baraúna blog.plataformatec.com @hugobarauna
  10. 10. Vantagens do Rails 3 Performance Hugo Baraúna blog.plataformatec.com @hugobarauna
  11. 11. Vantagens do Rails 3 Agnóstico Performance Hugo Baraúna blog.plataformatec.com @hugobarauna
  12. 12. Vantagens do Rails 3 Modularidade Agnóstico Performance Hugo Baraúna blog.plataformatec.com @hugobarauna
  13. 13. Instalação guru/code$ gem install tzinfo builder memcache-client rack rack-test rack-mount erubis mail text-format thor bundler i18n guru/code$ gem install rails --pre Hugo Baraúna blog.plataformatec.com @hugobarauna
  14. 14. rails command Rails 2.3 Rails 3 ruby script/server rails server ruby script/console rails console ruby script/generate rails generate ruby script/dbconsole rails dbconsole Hugo Baraúna blog.plataformatec.com @hugobarauna
  15. 15. blog/config.ru require ::File.expand_path('../config/environment', __FILE__) run Blog::Application Hugo Baraúna blog.plataformatec.com @hugobarauna
  16. 16. blog/config.ru require ::File.expand_path('../config/environment', __FILE__) run Blog::Application Hugo Baraúna blog.plataformatec.com @hugobarauna
  17. 17. blog/config/application.rb require File.expand_path('../boot', __FILE__) require 'rails/all' Bundler.require(:default, Rails.env) if defined?(Bundler) module Blog class Application < Rails::Application config.encoding = "utf-8" config.filter_parameters += [:password] end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  18. 18. blog/config/application.rb require File.expand_path('../boot', __FILE__) require 'rails/all' Bundler.require(:default, Rails.env) if defined?(Bundler) module Blog uma Rack App! class Application < Rails::Application config.encoding = "utf-8" config.filter_parameters += [:password] end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  19. 19. blog/config/application.rb require File.expand_path('../boot', __FILE__) require 'rails/all' Bundler.require(:default, Rails.env) if defined?(Bundler) module Blog class Application < Rails::Application config.encoding = "utf-8" config.filter_parameters += [:password] end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  20. 20. blog/config/application.rb require File.expand_path('../boot', __FILE__) require 'rails/all' Bundler.require(:default, Rails.env) if defined?(Bundler) module Blog class Application < Rails::Application config.encoding = "utf-8" config.filter_parameters += [:password] end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  21. 21. blog/config/boot.rb require 'rubygems' # Set up gems listed in the Gemfile. gemfile = File.expand_path('../../Gemfile', __FILE__) begin ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' Bundler.setup rescue Bundler::GemNotFound => e STDERR.puts e.message STDERR.puts "Try running `bundle install`." exit! end if File.exist?(gemfile) Hugo Baraúna blog.plataformatec.com @hugobarauna
  22. 22. blog/config/boot.rb require 'rubygems' # Set up gems listed in the Gemfile. gemfile = File.expand_path('../../Gemfile', __FILE__) begin ENV['BUNDLE_GEMFILE'] = gemfile require 'bundler' Bundler.setup rescue Bundler::GemNotFound => e STDERR.puts e.message STDERR.puts "Try running `bundle install`." exit! end if File.exist?(gemfile) Hugo Baraúna blog.plataformatec.com @hugobarauna
  23. 23. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  24. 24. Hugo Baraúna blog.plataformatec.com @hugobarauna
  25. 25. Biblioteca para gerenciamento de dependências Hugo Baraúna blog.plataformatec.com @hugobarauna
  26. 26. # Gemfile source 'http://rubygems.org' # Bundle edge Rails instead: gem 'rails', :git => 'git://github.com/rails/rails.git' gem 'mysql' gem 'devise', :git => 'git://github.com/plataformatec/ devise.git' gem 'responders', :git => 'git://github.com/plataformatec/ responders.git' group :development do gem 'ruby-debug' end group :test do gem 'rspec' gem 'rspec-rails', '>= 2.0.0.beta' end Hugo Baraúna blog.plataformatec.com @hugobarauna
  27. 27. # Gemfile source 'http://rubygems.org' # Bundle edge Rails instead: gem 'rails', :git => 'git://github.com/rails/rails.git' gem 'mysql' gem 'devise', :git => 'git://github.com/plataformatec/ devise.git' gem 'responders', :git => 'git://github.com/plataformatec/ responders.git' group :development do gem 'ruby-debug' end group :test do gem 'rspec' gem 'rspec-rails', '>= 2.0.0.beta' end Hugo Baraúna blog.plataformatec.com @hugobarauna
  28. 28. # Gemfile source 'http://rubygems.org' # Bundle edge Rails instead: gem 'rails', :git => 'git://github.com/rails/rails.git' gem 'mysql' gem 'devise', :git => 'git://github.com/plataformatec/ devise.git' gem 'responders', :git => 'git://github.com/plataformatec/ responders.git' group :development do gem 'ruby-debug' end group :test do gem 'rspec' gem 'rspec-rails', '>= 2.0.0.beta' end Hugo Baraúna blog.plataformatec.com @hugobarauna
  29. 29. Resolução de dependências Hugo Baraúna blog.plataformatec.com @hugobarauna
  30. 30. Resolução de dependências guru/code$ gem dependency actionpack -v="2.3.5" Gem actionpack-2.3.5 activesupport (= 2.3.5, runtime) rack (~> 1.0.0, runtime) guru/code$ gem dependency thin Gem thin-1.2.7 daemons (>= 1.0.9, runtime) eventmachine (>= 0.12.6, runtime) rack (>= 1.0.0, runtime) Hugo Baraúna blog.plataformatec.com @hugobarauna
  31. 31. Resolução de dependências guru/code$ gem dependency actionpack -v="2.3.5" Gem actionpack-2.3.5 activesupport (= 2.3.5, runtime) rack (~> 1.0.0, runtime) guru/code$ gem dependency thin Gem thin-1.2.7 daemons (>= 1.0.9, runtime) eventmachine (>= 0.12.6, runtime) rack (>= 1.0.0, runtime) Hugo Baraúna blog.plataformatec.com @hugobarauna
  32. 32. Resolução de dependências require "rubygems" require "thin" gem "actionpack", "2.3.5" Hugo Baraúna blog.plataformatec.com @hugobarauna
  33. 33. Resolução de dependências require "rubygems" require "thin" gem "actionpack", "2.3.5" can't activate rack (~> 1.0.0, runtime) for ["actionpack-2.3.5"], already activated rack-1.1.0 for ["thin-1.2.7"] (Gem::LoadError) Hugo Baraúna blog.plataformatec.com @hugobarauna
  34. 34. Gemfile # Gemfile gem "thin" gem "actionpack", "2.3.5" Hugo Baraúna blog.plataformatec.com @hugobarauna
  35. 35. Gemfile # Gemfile gem "thin" gem "actionpack", "2.3.5" guru/code$ bundle list Gems included by the bundle: * actionpack (2.3.5) * activesupport (2.3.5) * daemons (1.0.10) * eventmachine (0.12.10) * rack (1.0.1) * thin (1.2.7) Hugo Baraúna blog.plataformatec.com @hugobarauna
  36. 36. Gemfile # Gemfile gem "thin" gem "actionpack", "2.3.5" guru/code$ bundle list Gems included by the bundle: * actionpack (2.3.5) * activesupport (2.3.5) * daemons (1.0.10) * eventmachine (0.12.10) * rack (1.0.1) * thin (1.2.7) Hugo Baraúna blog.plataformatec.com @hugobarauna
  37. 37. Lock no $LOAD_PATH Hugo Baraúna blog.plataformatec.com @hugobarauna
  38. 38. Esqueci de colocar no config.gem! Hugo Baraúna blog.plataformatec.com @hugobarauna
  39. 39. Esqueci de colocar no config.gem! Hugo Baraúna blog.plataformatec.com @hugobarauna
  40. 40. } guru/code$ gem list *** LOCAL GEMS *** bundler (0.9.25) rake (0.8.7, 0.8.5) Filesystem rdoc (2.5.8) thor (0.13.6) Hugo Baraúna blog.plataformatec.com @hugobarauna
  41. 41. } guru/code$ gem list *** LOCAL GEMS *** bundler (0.9.25) rake (0.8.7, 0.8.5) Filesystem rdoc (2.5.8) thor (0.13.6) # Gemfile gem “rake”, “0.8.5” } Gemfile Hugo Baraúna blog.plataformatec.com @hugobarauna
  42. 42. } guru/code$ gem list *** LOCAL GEMS *** bundler (0.9.25) rake (0.8.7, 0.8.5) Filesystem rdoc (2.5.8) thor (0.13.6) # Gemfile gem “rake”, “0.8.5” } Gemfile rake-0.8.5 } $LOAD_PATH Hugo Baraúna blog.plataformatec.com @hugobarauna
  43. 43. guru/code$ gem list rake (0.8.7, 0.8.5) thor (0.13.6) Hugo Baraúna blog.plataformatec.com @hugobarauna
  44. 44. guru/code$ gem list rake (0.8.7, 0.8.5) thor (0.13.6) # Gemfile gem "rake" Hugo Baraúna blog.plataformatec.com @hugobarauna
  45. 45. guru/code$ gem list rake (0.8.7, 0.8.5) thor (0.13.6) # Gemfile gem "rake" # test_load_path_lock.rb require "rubygems" require "bundler" Bundler.setup require "rake" require "thor" Hugo Baraúna blog.plataformatec.com @hugobarauna
  46. 46. guru/code$ gem list rake (0.8.7, 0.8.5) thor (0.13.6) # Gemfile gem "rake" # test_load_path_lock.rb require "rubygems" require "bundler" Bundler.setup Lock no $LOAD_PATH require "rake" require "thor" Hugo Baraúna blog.plataformatec.com @hugobarauna
  47. 47. guru/code$ gem list rake (0.8.7, 0.8.5) thor (0.13.6) # Gemfile gem "rake" # test_load_path_lock.rb require "rubygems" require "bundler" Bundler.setup Lock no $LOAD_PATH require "rake" require "thor" guru/code$ ruby test_load_path_lock.rb test_load_path_lock.rb:6:in `require': no such file to load -- thor (LoadError) from test_load_path_lock.rb:6 Hugo Baraúna blog.plataformatec.com @hugobarauna
  48. 48. guru/code$ gem list rake (0.8.7, 0.8.5) thor (0.13.6) # Gemfile gem "rake" # test_load_path_lock.rb require "rubygems" require "bundler" Bundler.setup Lock no $LOAD_PATH require "rake" require "thor" guru/code$ ruby test_load_path_lock.rb test_load_path_lock.rb:6:in `require': no such file to load -- thor (LoadError) from test_load_path_lock.rb:6 Hugo Baraúna blog.plataformatec.com @hugobarauna
  49. 49. Hugo Baraúna blog.plataformatec.com @hugobarauna
  50. 50. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  51. 51. Router Hugo Baraúna blog.plataformatec.com @hugobarauna
  52. 52. Nova API Hugo Baraúna blog.plataformatec.com @hugobarauna
  53. 53. Rotas root Rails 2.3 map.root :controller => "welcome" Rails 3 root :to => "welcome#index" Hugo Baraúna blog.plataformatec.com @hugobarauna
  54. 54. Rotas comum Rails 2.3 map.connect "products/:id", controller=> "catalog", :action => "view" Rails 3 match 'products/:id' => 'catalog#view' Hugo Baraúna blog.plataformatec.com @hugobarauna
  55. 55. Named routes Rails 2.3 map.purchase "products/:id/purchase", :controller => "catalog", :action => "purchase" Rails 3 match "products/:id/purchase" => 'catalog#purchase', :as => :purchase Hugo Baraúna blog.plataformatec.com @hugobarauna
  56. 56. Resources com member e collection Rails 2.3 map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get } resources :products do Rails 3 member do get :short post :toggle end collection do get :sold end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  57. 57. Router and Rack FTW! Hugo Baraúna blog.plataformatec.com @hugobarauna
  58. 58. Rack FTW! Hugo Baraúna blog.plataformatec.com @hugobarauna
  59. 59. Rack FTW! match "posts/:echo" => "posts#show" Hugo Baraúna blog.plataformatec.com @hugobarauna
  60. 60. Rack FTW! match "posts/:echo" => "posts#show" uma Rack App! match "posts/:echo" => PostsController.action(:show) Hugo Baraúna blog.plataformatec.com @hugobarauna
  61. 61. Rack FTW! match "posts/:echo" => "posts#show" match "posts/:echo" => PostsController.action(:show) uma Rack App! match "posts/:echo" => lambda { |env| [ 200, {“Content-Type” => “plain/text”}, ["Echo!"] ] } Hugo Baraúna blog.plataformatec.com @hugobarauna
  62. 62. Rack FTW! match "posts/:echo" => "posts#show" match "posts/:echo" => PostsController.action(:show) match "posts/:echo" => lambda { |env| [ 200, {“Content-Type” => “plain/text”}, ["Echo!"] ] } uma Rack App! match "posts/:echo" => MySinatraBlog Hugo Baraúna blog.plataformatec.com @hugobarauna
  63. 63. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  64. 64. ActionMailer new API Hugo Baraúna blog.plataformatec.com @hugobarauna
  65. 65. ActionMailer new API guru/code$ rails g mailer Notifier signup_notification create app/mailers/notifier.rb invoke erb create app/views/notifier create app/views/notifier/signup_notification.text.erb invoke test_unit create test/functional/notifier_test.rb guru/code$ ls -lp app/ controllers/ helpers/ mailers/ models/ views/ Hugo Baraúna blog.plataformatec.com @hugobarauna
  66. 66. ActionMailer new API guru/code$ rails g mailer Notifier signup_notification create app/mailers/notifier.rb invoke erb create app/views/notifier create app/views/notifier/signup_notification.text.erb invoke test_unit create test/functional/notifier_test.rb guru/code$ ls -lp app/ controllers/ helpers/ mailers com diretório próprio mailers/ models/ views/ Hugo Baraúna blog.plataformatec.com @hugobarauna
  67. 67. ActionMailer new API class Notifier < ActionMailer::Base default :from => "system@example.com" def signup_notification(recipient) @account = recipient attachments['image.jpg'] = File.read ("image.jpg") mail(:to => recipient.email) do |format| format.html format.text end end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  68. 68. ActionMailer new API class Notifier < ActionMailer::Base Variáveis default :from => "system@example.com" de instância def signup_notification(recipient) @account = recipient attachments['image.jpg'] = File.read ("image.jpg") mail(:to => recipient.email) do |format| format.html format.text end end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  69. 69. ActionMailer new API class Notifier < ActionMailer::Base Variáveis default :from => "system@example.com" de instância def signup_notification(recipient) @account = recipient Attachments tipo attachments['image.jpg'] = File.read cookies ("image.jpg") mail(:to => recipient.email) do |format| format.html format.text end end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  70. 70. ActionMailer new API class Notifier < ActionMailer::Base Variáveis default :from => "system@example.com" de instância def signup_notification(recipient) @account = recipient Attachments tipo attachments['image.jpg'] = File.read cookies ("image.jpg") mail(:to => recipient.email) do |format| format.html format.text end end mail tipo respond_to do |format| end Hugo Baraúna blog.plataformatec.com @hugobarauna
  71. 71. AbstractController::Base ActionController::Metal ActionMailer::Base ActionController::Base Hugo Baraúna blog.plataformatec.com @hugobarauna
  72. 72. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  73. 73. ActiveModel Hugo Baraúna blog.plataformatec.com @hugobarauna
  74. 74. ActiveModel Hugo Baraúna blog.plataformatec.com @hugobarauna
  75. 75. ActiveModel • Google Summer of Code 2009: Hugo Baraúna blog.plataformatec.com @hugobarauna
  76. 76. ActiveModel • Google Summer of Code 2009: • Extraira lógica comum entre ActiveRecord e ActiveResource Hugo Baraúna blog.plataformatec.com @hugobarauna
  77. 77. ActiveModel • Google Summer of Code 2009: • Extraira lógica comum entre ActiveRecord e ActiveResource • Hoje Hugo Baraúna blog.plataformatec.com @hugobarauna
  78. 78. ActiveModel • Google Summer of Code 2009: • Extraira lógica comum entre ActiveRecord e ActiveResource • Hoje • Desempenha papel no agnosticismo de ORM Hugo Baraúna blog.plataformatec.com @hugobarauna
  79. 79. ActiveModel • Google Summer of Code 2009: • Extraira lógica comum entre ActiveRecord e ActiveResource • Hoje • Desempenha papel no agnosticismo de ORM • Permite a criação de models à la ActiveRecord Hugo Baraúna blog.plataformatec.com @hugobarauna
  80. 80. ActiveResource::Base + ActiveModel module ActiveResource ... class Base extend ActiveModel::Naming include CustomMethods, Observing, Validations include ActiveModel::Conversion include ActiveModel::Serializers::JSON include ActiveModel::Serializers::Xml end end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  81. 81. ActiveRecord::Base + ActiveModel Base.class_eval do ... extend ActiveModel::Naming ... include ActiveModel::Conversion include Validations ... include Callbacks, ActiveModel::Observing, Timestamp end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  82. 82. Agnosticismo de ORM Hugo Baraúna blog.plataformatec.com @hugobarauna
  83. 83. Agnosticismo de ORM Agnosticismo de ORM ActiveModel Rails::Railtie Hugo Baraúna blog.plataformatec.com @hugobarauna
  84. 84. Agnosticismo de ORM Agnosticismo de ORM ActiveModel Rails::Railtie Provê uma API para que o ActionPack possa conversar com o ORM Hugo Baraúna blog.plataformatec.com @hugobarauna
  85. 85. Agnosticismo de ORM Agnosticismo de ORM ActiveModel Rails::Railtie Provê uma API para que o Integração do ORM com o Rails ActionPack possa conversar com o ORM Hugo Baraúna blog.plataformatec.com @hugobarauna
  86. 86. ActiveModel::Lint::Tests Hugo Baraúna blog.plataformatec.com @hugobarauna
  87. 87. module ActiveModel module Lint module Tests def test_to_key assert model.respond_to?(:to_key), "The model should respond to to_key" def model.persisted?() false end assert model.to_key.nil? end def test_to_param assert model.respond_to?(:to_param), "The model should respond to to_param" def model.persisted?() false end assert model.to_param.nil? end def test_valid? assert model.respond_to?(:valid?), "The model should respond to valid?" assert_boolean model.valid?, "valid?" end ... def test_persisted? assert model.respond_to?(:persisted?), "The model should respond to persisted?" assert_boolean model.persisted?, "persisted?" end def test_errors_aref assert model.respond_to?(:errors), "The model should respond to errors" assert model.errors[:hello].is_a?(Array), "errors#[] should return an Array" end def test_errors_full_messages assert model.respond_to?(:errors), "The model should respond to errors" assert model.errors.full_messages.is_a?(Array), "errors#full_messages should return an Array" end end end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  88. 88. def test_to_param assert model.respond_to?(:to_param), "The model should respond to to_param" def model.persisted?() false end assert model.to_param.nil? end def test_valid? assert model.respond_to?(:valid?), "The model should respond to valid?" assert_boolean model.valid?, "valid?" end ... def test_errors_aref assert model.respond_to?(:errors), "The model should respond to errors" assert model.errors[:hello].is_a?(Array), "errors#[] should return an Array" end Hugo Baraúna blog.plataformatec.com @hugobarauna
  89. 89. ActiveRecord-like Ótimo exemplo de uso do ActiveModel http://github.com/plataformatec/mail_form Hugo Baraúna blog.plataformatec.com @hugobarauna
  90. 90. ActiveModel Hugo Baraúna blog.plataformatec.com @hugobarauna
  91. 91. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  92. 92. Responders Hugo Baraúna blog.plataformatec.com @hugobarauna
  93. 93. RAILS 2.3 def index @users = User.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @users } end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  94. 94. RAILS 2.3 def index @users = User.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @users } end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  95. 95. RAILS 3.0 respond_to :html, :xml def index @users = User.all respond_with(@users) end Hugo Baraúna blog.plataformatec.com @hugobarauna
  96. 96. RAILS 3.0 respond_to :html, :xml def index @users = User.all respond_with(@users) end Hugo Baraúna blog.plataformatec.com @hugobarauna
  97. 97. Navigational API GET POST PUT DELETE Hugo Baraúna blog.plataformatec.com @hugobarauna
  98. 98. Navigational API GET POST PUT DELETE Hugo Baraúna blog.plataformatec.com @hugobarauna
  99. 99. Navigational API GET POST PUT DELETE Hugo Baraúna blog.plataformatec.com @hugobarauna
  100. 100. respond_to :html, :xml def index @users = User.all respond_with(@users) end Hugo Baraúna blog.plataformatec.com @hugobarauna
  101. 101. Navigational API render GET render template collection.to_format POST PUT DELETE Hugo Baraúna blog.plataformatec.com @hugobarauna
  102. 102. RAILS 2.3 def create @user = User.new(params[:user]) respond_to do |format| if @user.save format.html { redirect_to @user, :notice => 'User was successfully created' } 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 Hugo Baraúna blog.plataformatec.com @hugobarauna
  103. 103. RAILS 3.0 def create @user = User.new(params[:user]) flash[:notice] = 'User was successfully created' if @user.save respond_with(@user) end Hugo Baraúna blog.plataformatec.com @hugobarauna
  104. 104. Navigational API render GET render template collection.to_format render Success redirect_to resource resource.to_format POST Failure render :new render resource.errors PUT DELETE Hugo Baraúna blog.plataformatec.com @hugobarauna
  105. 105. Navigational API render GET render template collection.to_format render Success redirect_to resource resource.to_format POST Failure render :new render resource.errors Success redirect_to resource head :ok PUT Failure render :edit render resource.errors DELETE redirect_to collection head :ok Hugo Baraúna blog.plataformatec.com @hugobarauna
  106. 106. respond_with(@users) ActionController::Responder Hugo Baraúna blog.plataformatec.com @hugobarauna
  107. 107. respond_with(@users) ActionController::Responder table.to_code Navigational API GET render template render collection.to_format Success redirect_to resource render resource.to_format POST Failure render :new render resource.errors Success redirect_to resource head :ok PUT Failure render :edit render resource.errors DELETE redirect_to collection head :ok Hugo Baraúna blog.plataformatec.com @hugobarauna
  108. 108. Responders Customizados Hugo Baraúna blog.plataformatec.com @hugobarauna
  109. 109. github.com/plataformatec/responders Hugo Baraúna blog.plataformatec.com @hugobarauna
  110. 110. github.com/plataformatec/responders Hugo Baraúna blog.plataformatec.com @hugobarauna
  111. 111. github.com/plataformatec/responders FlashResponder: seta o flash baseado na action do controller e no status do recurso Hugo Baraúna blog.plataformatec.com @hugobarauna
  112. 112. github.com/plataformatec/responders FlashResponder: seta o flash baseado na action do controller e no status do recurso HttpCacheResponder: automaticamente adiciona o cabeçalho HTTP Last-Modified para requests de API format Hugo Baraúna blog.plataformatec.com @hugobarauna
  113. 113. CONFIGURANDO O RESPONDERS # lib/application_responder.rb class ApplicationResponder < ActionController::Responder include Responders::FlashResponder include Responders::HttpCacheResponder end Hugo Baraúna blog.plataformatec.com @hugobarauna
  114. 114. CONFIGURANDO O RESPONDERS # lib/application_responder.rb class ApplicationResponder < ActionController::Responder include Responders::FlashResponder include Responders::HttpCacheResponder end # app/controllers/application_controller.rb class ApplicationController < ActionController::Base self.responder = ApplicationResponder respond_to :html protect_from_forgery layout 'application' end Hugo Baraúna blog.plataformatec.com @hugobarauna
  115. 115. SEM O RESPONDERS # app/controllers/users_controller.rb def create @user = User.new(params[:user]) flash[:notice] = 'User was successfully created' if @user.save respond_with(@user) end Hugo Baraúna blog.plataformatec.com @hugobarauna
  116. 116. SEM O RESPONDERS # app/controllers/users_controller.rb def create @user = User.new(params[:user]) flash[:notice] = 'User was successfully created' if @user.save respond_with(@user) end O FlashResponder vai fazer isso por mim Hugo Baraúna blog.plataformatec.com @hugobarauna
  117. 117. COM O RESPONDERS # app/controllers/users_controller.rb def create @user = User.new(params[:user]) @user.save respond_with(@user) end # config/locales/en.yml en: flash: users: create: success: “User was successfully created” Hugo Baraúna blog.plataformatec.com @hugobarauna
  118. 118. Responders Hugo Baraúna blog.plataformatec.com @hugobarauna
  119. 119. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  120. 120. ARel Hugo Baraúna blog.plataformatec.com @hugobarauna
  121. 121. Lazy loading # Rails 2.3 Job.find(:all, :conditions => {:published => true}) Faz um query no DB imediatamente e retorna um array de Jobs # Rails 3 Job.where(:published => true) Não faz query no DB, retorna um ActiveRecord::Relation Hugo Baraúna blog.plataformatec.com @hugobarauna
  122. 122. Onde a query roda? # app/controllers/jobs_controller.rb class JobsController < ApplicationController def index @jobs = Jobs.where(:published => true).order("created_at DESC") end end # app/views/jobs/index.html.erb <% cache do %> <% @jobs.each do |job| %> ... <% end %> <% end %> Hugo Baraúna blog.plataformatec.com @hugobarauna
  123. 123. Onde a query roda? # app/controllers/jobs_controller.rb class JobsController < ApplicationController def index @jobs = Jobs.where(:published => true).order("created_at DESC") end end Não realiza query no DB # app/views/jobs/index.html.erb <% cache do %> <% @jobs.each do |job| %> ... <% end %> <% end %> Hugo Baraúna blog.plataformatec.com @hugobarauna
  124. 124. Onde a query roda? # app/controllers/jobs_controller.rb class JobsController < ApplicationController def index @jobs = Jobs.where(:published => true).order("created_at DESC") end end Não realiza query no DB # app/views/jobs/index.html.erb <% cache do %> <% @jobs.each do |job| %> ... <% end %> <% end %> Só aqui que será feito a query no DB Hugo Baraúna blog.plataformatec.com @hugobarauna
  125. 125. Onde a query roda? # app/controllers/jobs_controller.rb class JobsController < ApplicationController def index @jobs = Jobs.where(:published => true).order("created_at DESC") end end Não realiza query no DB # app/views/jobs/index.html.erb Se estiver cacheado, não faz <% cache do %> a query no controller a toa <% @jobs.each do |job| %> ... <% end %> <% end %> Só aqui que será feito a query no DB Hugo Baraúna blog.plataformatec.com @hugobarauna
  126. 126. Chainability: it “quacks” like named_scope Job.where(:title => 'Rails Developer') Job.order('created_at DESC').limit(20).includes(:company) cars = Car.where(:colour => 'black') black_fancy_cars = cars.order('cars.price DESC').limit(10) black_cheap_cart = cars.order('cars.price ASC').limit(10) Hugo Baraúna blog.plataformatec.com @hugobarauna
  127. 127. Chainability: it “quacks” like named_scope Job.where(:title => 'Rails Developer') Job.order('created_at DESC').limit(20).includes(:company) ActiveRecord::Relation cars = Car.where(:colour => 'black') black_fancy_cars = cars.order('cars.price DESC').limit(10) black_cheap_cart = cars.order('cars.price ASC').limit(10) Hugo Baraúna blog.plataformatec.com @hugobarauna
  128. 128. Chainability: it “quacks” like named_scope Job.where(:title => 'Rails Developer') Job.order('created_at DESC').limit(20).includes(:company) ActiveRecord::Relation cars = Car.where(:colour => 'black') black_fancy_cars = cars.order('cars.price DESC').limit(10) black_cheap_cart = cars.order('cars.price ASC').limit(10) Reaproveitar uma Relation e encadear mais finders Hugo Baraúna blog.plataformatec.com @hugobarauna
  129. 129. ARel Hugo Baraúna blog.plataformatec.com @hugobarauna
  130. 130. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  131. 131. Unobtrusive Javascript Hugo Baraúna blog.plataformatec.com @hugobarauna
  132. 132. Unobtrusive Javascript: Rails 2.3 remote_form_for(@post) link_to 'Destroy', post, :confirm => 'Are you sure?',:method => :delete Hugo Baraúna blog.plataformatec.com @hugobarauna
  133. 133. Unobtrusive Javascript: Rails 2.3 remote_form_for(@post) <form action="/posts" class="new_post" id="new_post" method="post" onsubmit="new Ajax.Request('/posts', {asynchronous:true, evalScripts:true, parameters:Form.serialize (this)}); return false;"> link_to 'Destroy', post, :confirm => 'Are you sure?',:method => :delete Hugo Baraúna blog.plataformatec.com @hugobarauna
  134. 134. Unobtrusive Javascript: Rails 2.3 remote_form_for(@post) <form action="/posts" class="new_post" id="new_post" method="post" onsubmit="new Ajax.Request('/posts', {asynchronous:true, evalScripts:true, parameters:Form.serialize (this)}); return false;"> link_to 'Destroy', post, :confirm => 'Are you sure?',:method => :delete <a href="/posts/1" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute ('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'LM2fEF6HuRWdYUZdEumWlemhI6iDPH97pqWhO4jEpiU='); f.appendChild(s);f.submit(); };return false;">Destroy</a> Hugo Baraúna blog.plataformatec.com @hugobarauna
  135. 135. Unobtrusive Javascript: Rails 3 # Rails 2.3 remote_form_for(@post) <form action="/posts" class="new_post" id="new_post" method="post" onsubmit="new Ajax.Request('/posts', {asynchronous:true, evalScripts:true, parameters:Form.serialize (this)}); return false;"> Hugo Baraúna blog.plataformatec.com @hugobarauna
  136. 136. Unobtrusive Javascript: Rails 3 # Rails 2.3 remote_form_for(@post) <form action="/posts" class="new_post" id="new_post" method="post" onsubmit="new Ajax.Request('/posts', {asynchronous:true, evalScripts:true, parameters:Form.serialize (this)}); return false;"> # Rails 3 form_for(@posts, :remote => true) <form action="/posts" class="new_post" data-remote="true" id="new_post" method="post"> Hugo Baraúna blog.plataformatec.com @hugobarauna
  137. 137. Unobtrusive Javascript: Rails 3 # Rails 2.3 remote_form_for(@post) <form action="/posts" class="new_post" id="new_post" method="post" onsubmit="new Ajax.Request('/posts', {asynchronous:true, evalScripts:true, parameters:Form.serialize (this)}); return false;"> # Rails 3 form_for(@posts, :remote => true) <form action="/posts" class="new_post" data-remote="true" id="new_post" method="post"> Hugo Baraúna blog.plataformatec.com @hugobarauna
  138. 138. Unobtrusive Javascript: Rails 3 # Rails 2.3 link_to 'Destroy', post, :confirm => 'Are you sure?',:method => :delete <a href="/posts/1" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute ('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'LM2fEF6HuRWdYUZdEumWlemhI6iDPH97pqWhO4jEpiU='); f.appendChild(s);f.submit(); };return false;">Destroy</a> Hugo Baraúna blog.plataformatec.com @hugobarauna
  139. 139. Unobtrusive Javascript: Rails 3 # Rails 2.3 link_to 'Destroy', post, :confirm => 'Are you sure?',:method => :delete <a href="/posts/1" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute ('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'LM2fEF6HuRWdYUZdEumWlemhI6iDPH97pqWhO4jEpiU='); f.appendChild(s);f.submit(); };return false;">Destroy</a> # Rails 3 link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete <a href="/posts/1" data-confirm="Are you sure?" data-method="delete" rel="nofollow">Destroy</a> Hugo Baraúna blog.plataformatec.com @hugobarauna
  140. 140. Unobtrusive Javascript: Rails 3 # Rails 2.3 link_to 'Destroy', post, :confirm => 'Are you sure?',:method => :delete <a href="/posts/1" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute ('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'LM2fEF6HuRWdYUZdEumWlemhI6iDPH97pqWhO4jEpiU='); f.appendChild(s);f.submit(); };return false;">Destroy</a> # Rails 3 link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete <a href="/posts/1" data-confirm="Are you sure?" data-method="delete" rel="nofollow">Destroy</a> Hugo Baraúna blog.plataformatec.com @hugobarauna
  141. 141. JS Driver Markup com HTML 5 custom data attributes JS Driver JS Framework Hugo Baraúna blog.plataformatec.com @hugobarauna
  142. 142. JS Driver // public/javascripts/rails.js document.observe("dom:loaded", function() { function handleRemote(element) { var method, url, params; if (element.tagName.toLowerCase() === 'form') { Apenas 119 linhas! method = element.readAttribute('method') || 'post'; url = element.readAttribute('action'); params = element.serialize(true); } else { method = element.readAttribute('data-method') || 'get'; url = element.readAttribute('href'); params = {}; } var event = element.fire("ajax:before"); if (event.stopped) return false; new Ajax.Request(url, { method: method, parameters: params, asynchronous: true, evalScripts: true, onLoading: function(request) { element.fire("ajax:loading", {request: request}); }, onLoaded: function(request) { element.fire("ajax:loaded", {request: request}); }, onInteractive: function(request) { element.fire("ajax:interactive", {request: request}); }, onComplete: function(request) { element.fire("ajax:complete", {request: request}); }, onSuccess: function(request) { element.fire("ajax:success", {request: request}); }, onFailure: function(request) { element.fire("ajax:failure", {request: request}); } }); element.fire("ajax:after"); } ... Hugo Baraúna blog.plataformatec.com @hugobarauna
  143. 143. JS para todos os gostos • Prototype: default • jQuery: http://github.com/rails/jquery-ujs • MooTools: http://mootools.net/forge/p/rails_3_driver • Você pode fazer o seu! Hugo Baraúna blog.plataformatec.com @hugobarauna
  144. 144. Javascript no Rails 3 Hugo Baraúna blog.plataformatec.com @hugobarauna
  145. 145. Javascript no Rails 3 Agnosticismo de Javascript HTML 5 custom data attributes JS driver para cada framework Hugo Baraúna blog.plataformatec.com @hugobarauna
  146. 146. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  147. 147. XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  148. 148. XSS protection Rails 2.3: unsafe por default <%= @job.title %> <%= h @job.title %> unsafe safe Rails 3: safe por default <%= @job.title %> <%= raw @job.title %> safe unsafe Hugo Baraúna blog.plataformatec.com @hugobarauna
  149. 149. XSS protection Rails 2.3: unsafe por default <%= @job.title %> <%= h @job.title %> unsafe safe Rails 3: safe por default <%= @job.title %> <%= raw @job.title %> safe unsafe Hugo Baraúna blog.plataformatec.com @hugobarauna
  150. 150. XSS protection Rails 2.3: unsafe por default <%= @job.title %> <%= h @job.title %> unsafe safe Rails 3: safe por default <%= @job.title %> <%= raw @job.title %> safe unsafe Hugo Baraúna blog.plataformatec.com @hugobarauna
  151. 151. ActiveSupport::SafeBuffer guru/code$ rails console > a ="maybe dangerous" => "maybe dangerous" > a.html_safe? => false > b = a.html_safe => "maybe dangerous" > b.html_safe? => true > b.class => ActiveSupport::SafeBuffer Hugo Baraúna blog.plataformatec.com @hugobarauna
  152. 152. Helpers que retornam HTML module ApplicationHelper def strong(content) "<strong>#{h content}</string>".html_safe end end Hugo Baraúna blog.plataformatec.com @hugobarauna
  153. 153. Helpers que retornam HTML module ApplicationHelper def strong(content) "<strong>#{h content}</string>".html_safe end end Dicas: 1. Certificar-se de que todo input está sendo escapado Hugo Baraúna blog.plataformatec.com @hugobarauna
  154. 154. Helpers que retornam HTML module ApplicationHelper def strong(content) "<strong>#{h content}</string>".html_safe end end Dicas: 1. Certificar-se de que todo input está sendo escapado 2. Chamar html_safe no output Hugo Baraúna blog.plataformatec.com @hugobarauna
  155. 155. Tem muito mais aqui! http://github.com/plataformatec Hugo Baraúna blog.plataformatec.com @hugobarauna
  156. 156. Tem muito mais aqui! http://github.com/plataformatec ID blog twitter Hugo Baraúna blog.plataformatec.com @hugobarauna

×