SlideShare une entreprise Scribd logo
1  sur  156
Télécharger pour lire hors ligne
Rails 3


Hugo Baraúna    blog.plataformatec.com   @hugobarauna
Rails 3

   ID                   blog                 twitter

Hugo Baraúna    blog.plataformatec.com   @hugobarauna
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
Hugo Baraúna   blog.plataformatec.com   @hugobarauna
Desevolvemos
aplicações em Rails




 Coaching em                              Consultoria
 Rails e Agile

Hugo Baraúna     blog.plataformatec.com           @hugobarauna
Arquitetura
               Rails 3

                       Rails

                ActionDispatch

                 ActiveSupport




Hugo Baraúna    blog.plataformatec.com   @hugobarauna
Arquitetura
                                    Todo o resto são
               Rails 3                  Railties!

                       Rails

                ActionDispatch

                 ActiveSupport




Hugo Baraúna    blog.plataformatec.com        @hugobarauna
Arquitetura
                                              Todo o resto são
                        Rails 3                   Railties!
     ActiveRecord

                                  Rails
                                                    ActionView
                          ActionDispatch
       outros...
                           ActiveSupport
                                                   ActionController

                   ActionMailer

Hugo Baraúna              blog.plataformatec.com           @hugobarauna
Vantagens do Rails 3




Hugo Baraúna         blog.plataformatec.com   @hugobarauna
Vantagens do Rails 3




                    Performance



Hugo Baraúna         blog.plataformatec.com   @hugobarauna
Vantagens do Rails 3



                      Agnóstico


                    Performance



Hugo Baraúna         blog.plataformatec.com   @hugobarauna
Vantagens do Rails 3

                    Modularidade


                      Agnóstico


                    Performance



Hugo Baraúna         blog.plataformatec.com   @hugobarauna
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
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
blog/config.ru


               require ::File.expand_path('../config/environment',   __FILE__)
               run Blog::Application




Hugo Baraúna                   blog.plataformatec.com           @hugobarauna
blog/config.ru


               require ::File.expand_path('../config/environment',   __FILE__)
               run Blog::Application




Hugo Baraúna                   blog.plataformatec.com           @hugobarauna
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
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
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
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
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
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
Bundler
               Router
               ActionMailer
               ActiveModel
               Responders
               ARel
               Unobtrusive Javascript
               XSS Protection



Hugo Baraúna       blog.plataformatec.com   @hugobarauna
Hugo Baraúna   blog.plataformatec.com   @hugobarauna
Biblioteca para gerenciamento de
           dependências



Hugo Baraúna   blog.plataformatec.com   @hugobarauna
# 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
# 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
# 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
Resolução de dependências




Hugo Baraúna    blog.plataformatec.com   @hugobarauna
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
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
Resolução de dependências
               require "rubygems"
               require "thin"
               gem "actionpack", "2.3.5"




Hugo Baraúna       blog.plataformatec.com   @hugobarauna
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
Gemfile
               # Gemfile
               gem "thin"
               gem "actionpack", "2.3.5"




Hugo Baraúna       blog.plataformatec.com   @hugobarauna
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
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
Lock no $LOAD_PATH




Hugo Baraúna         blog.plataformatec.com   @hugobarauna
Esqueci de colocar no config.gem!




Hugo Baraúna   blog.plataformatec.com   @hugobarauna
Esqueci de colocar no config.gem!




Hugo Baraúna   blog.plataformatec.com   @hugobarauna
}
         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
}
         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
}
         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
guru/code$ gem list
               rake (0.8.7, 0.8.5)
               thor (0.13.6)




Hugo Baraúna                   blog.plataformatec.com   @hugobarauna
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
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
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
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
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
Hugo Baraúna   blog.plataformatec.com   @hugobarauna
Bundler
               Router
               ActionMailer
               ActiveModel
               Responders
               ARel
               Unobtrusive Javascript
               XSS Protection



Hugo Baraúna       blog.plataformatec.com   @hugobarauna
Router




Hugo Baraúna   blog.plataformatec.com   @hugobarauna
Nova API




Hugo Baraúna   blog.plataformatec.com   @hugobarauna
Rotas root
  Rails 2.3

               map.root :controller => "welcome"




  Rails 3
                  root :to => "welcome#index"




Hugo Baraúna           blog.plataformatec.com      @hugobarauna
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
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
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
Router and Rack FTW!




Hugo Baraúna         blog.plataformatec.com   @hugobarauna
Rack FTW!




Hugo Baraúna    blog.plataformatec.com   @hugobarauna
Rack FTW!
               match "posts/:echo" => "posts#show"




Hugo Baraúna             blog.plataformatec.com      @hugobarauna
Rack FTW!
                   match "posts/:echo" => "posts#show"
                                                      uma Rack App!
           match "posts/:echo" => PostsController.action(:show)




Hugo Baraúna                 blog.plataformatec.com           @hugobarauna
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
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
Bundler
               Router
               ActionMailer
               ActiveModel
               Responders
               ARel
               Unobtrusive Javascript
               XSS Protection



Hugo Baraúna       blog.plataformatec.com   @hugobarauna
ActionMailer new API




Hugo Baraúna         blog.plataformatec.com   @hugobarauna
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
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
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
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
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
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
AbstractController::Base




                                               ActionController::Metal




       ActionMailer::Base                       ActionController::Base




Hugo Baraúna                blog.plataformatec.com              @hugobarauna
Bundler
               Router
               ActionMailer
               ActiveModel
               Responders
               ARel
               Unobtrusive Javascript
               XSS Protection



Hugo Baraúna       blog.plataformatec.com   @hugobarauna
ActiveModel




Hugo Baraúna     blog.plataformatec.com   @hugobarauna
ActiveModel




Hugo Baraúna     blog.plataformatec.com   @hugobarauna
ActiveModel
• Google       Summer of Code 2009:




Hugo Baraúna               blog.plataformatec.com   @hugobarauna
ActiveModel
• Google       Summer of Code 2009:

  • Extraira lógica comum entre ActiveRecord e
    ActiveResource




Hugo Baraúna               blog.plataformatec.com   @hugobarauna
ActiveModel
• Google       Summer of Code 2009:

  • Extraira lógica comum entre ActiveRecord e
    ActiveResource

• Hoje




Hugo Baraúna               blog.plataformatec.com   @hugobarauna
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
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
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
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
Agnosticismo de ORM




Hugo Baraúna         blog.plataformatec.com   @hugobarauna
Agnosticismo de ORM

                      Agnosticismo de ORM


                 ActiveModel               Rails::Railtie




Hugo Baraúna             blog.plataformatec.com             @hugobarauna
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
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
ActiveModel::Lint::Tests




Hugo Baraúna          blog.plataformatec.com   @hugobarauna
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
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
ActiveRecord-like
                        Ótimo exemplo de uso do ActiveModel




    http://github.com/plataformatec/mail_form




Hugo Baraúna       blog.plataformatec.com        @hugobarauna
ActiveModel




Hugo Baraúna     blog.plataformatec.com   @hugobarauna
Bundler
               Router
               ActionMailer
               ActiveModel
               Responders
               ARel
               Unobtrusive Javascript
               XSS Protection



Hugo Baraúna       blog.plataformatec.com   @hugobarauna
Responders




Hugo Baraúna    blog.plataformatec.com   @hugobarauna
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
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
RAILS 3.0

               respond_to :html, :xml

               def index
                 @users = User.all
                 respond_with(@users)
               end




Hugo Baraúna         blog.plataformatec.com   @hugobarauna
RAILS 3.0

               respond_to :html, :xml

               def index
                 @users = User.all
                 respond_with(@users)
               end




Hugo Baraúna         blog.plataformatec.com   @hugobarauna
Navigational             API

        GET


        POST



        PUT


      DELETE

Hugo Baraúna   blog.plataformatec.com     @hugobarauna
Navigational               API

        GET


        POST



        PUT


      DELETE

Hugo Baraúna     blog.plataformatec.com     @hugobarauna
Navigational             API

        GET


       POST



        PUT


     DELETE

Hugo Baraúna   blog.plataformatec.com     @hugobarauna
respond_to :html, :xml

               def index
                 @users = User.all
                 respond_with(@users)
               end




Hugo Baraúna         blog.plataformatec.com   @hugobarauna
Navigational                      API
                                                  render
        GET    render template
                                          collection.to_format


        POST



        PUT


      DELETE

Hugo Baraúna     blog.plataformatec.com              @hugobarauna
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
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
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
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
respond_with(@users)

               ActionController::Responder




Hugo Baraúna           blog.plataformatec.com   @hugobarauna
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
Responders Customizados




Hugo Baraúna    blog.plataformatec.com   @hugobarauna
github.com/plataformatec/responders




Hugo Baraúna    blog.plataformatec.com   @hugobarauna
github.com/plataformatec/responders




Hugo Baraúna    blog.plataformatec.com   @hugobarauna
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
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
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
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
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
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
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
Responders




Hugo Baraúna    blog.plataformatec.com   @hugobarauna
Bundler
               Router
               ActionMailer
               ActiveModel
               Responders
               ARel
               Unobtrusive Javascript
               XSS Protection



Hugo Baraúna       blog.plataformatec.com   @hugobarauna
ARel




Hugo Baraúna   blog.plataformatec.com   @hugobarauna
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
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
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
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
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
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
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
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
ARel




Hugo Baraúna   blog.plataformatec.com   @hugobarauna
Bundler
               Router
               ActionMailer
               ActiveModel
               Responders
               ARel
               Unobtrusive Javascript
               XSS Protection



Hugo Baraúna      blog.plataformatec.com   @hugobarauna
Unobtrusive Javascript




Hugo Baraúna          blog.plataformatec.com   @hugobarauna
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
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
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
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
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
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
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
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
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
JS Driver

               Markup com HTML 5 custom data attributes




                                JS Driver




                             JS Framework


Hugo Baraúna                blog.plataformatec.com        @hugobarauna
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
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
Javascript no Rails 3




Hugo Baraúna         blog.plataformatec.com   @hugobarauna
Javascript no Rails 3


                  Agnosticismo de Javascript


HTML 5 custom data attributes        JS driver para cada framework




Hugo Baraúna           blog.plataformatec.com            @hugobarauna
Bundler
               Router
               ActionMailer
               ActiveModel
               Responders
               ARel
               Unobtrusive Javascript
               XSS Protection



Hugo Baraúna       blog.plataformatec.com   @hugobarauna
XSS Protection




Hugo Baraúna      blog.plataformatec.com   @hugobarauna
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
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
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
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
Helpers que retornam HTML
               module ApplicationHelper
                 def strong(content)
                   "<strong>#{h content}</string>".html_safe
                 end
               end




Hugo Baraúna                 blog.plataformatec.com            @hugobarauna
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
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
Tem muito mais aqui!

               http://github.com/plataformatec




Hugo Baraúna           blog.plataformatec.com     @hugobarauna
Tem muito mais aqui!

               http://github.com/plataformatec




   ID                          blog                   twitter

Hugo Baraúna           blog.plataformatec.com     @hugobarauna

Contenu connexe

Tendances

Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
diego_k
 
Smolder @Silex
Smolder @SilexSmolder @Silex
Smolder @Silex
Jeen Lee
 

Tendances (20)

Datagrids with Symfony 2, Backbone and Backgrid
Datagrids with Symfony 2, Backbone and BackgridDatagrids with Symfony 2, Backbone and Backgrid
Datagrids with Symfony 2, Backbone and Backgrid
 
Hello World on Slim Framework 3.x
Hello World on Slim Framework 3.xHello World on Slim Framework 3.x
Hello World on Slim Framework 3.x
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
Morpheus configuration engine (slides from Saint Perl-2 conference)
Morpheus configuration engine (slides from Saint Perl-2 conference)Morpheus configuration engine (slides from Saint Perl-2 conference)
Morpheus configuration engine (slides from Saint Perl-2 conference)
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
JRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudJRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the Cloud
 
Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortega
 
The road to Ember.js 2.0
The road to Ember.js 2.0The road to Ember.js 2.0
The road to Ember.js 2.0
 
Perl Dancer, FPW 2010
Perl Dancer, FPW 2010Perl Dancer, FPW 2010
Perl Dancer, FPW 2010
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
The Enterprise Wor/d/thy/Press
The Enterprise Wor/d/thy/PressThe Enterprise Wor/d/thy/Press
The Enterprise Wor/d/thy/Press
 
Smolder @Silex
Smolder @SilexSmolder @Silex
Smolder @Silex
 
Javascript laravel's friend
Javascript laravel's friendJavascript laravel's friend
Javascript laravel's friend
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
 
Codeigniter4の比較と検証
Codeigniter4の比較と検証Codeigniter4の比較と検証
Codeigniter4の比較と検証
 
Writing webapps with Perl Dancer
Writing webapps with Perl DancerWriting webapps with Perl Dancer
Writing webapps with Perl Dancer
 
Laravel 5 In Depth
Laravel 5 In DepthLaravel 5 In Depth
Laravel 5 In Depth
 
Laravel5 Introduction and essentials
Laravel5 Introduction and essentialsLaravel5 Introduction and essentials
Laravel5 Introduction and essentials
 

En vedette (7)

Slides of old cumbernauld
Slides of old cumbernauldSlides of old cumbernauld
Slides of old cumbernauld
 
Joy to the World Remix
Joy to the World RemixJoy to the World Remix
Joy to the World Remix
 
Rails 2.3, 3.0 and 3.1 - RubyConfBR - 26oct2010
Rails 2.3, 3.0 and 3.1 - RubyConfBR - 26oct2010Rails 2.3, 3.0 and 3.1 - RubyConfBR - 26oct2010
Rails 2.3, 3.0 and 3.1 - RubyConfBR - 26oct2010
 
Presentation1
Presentation1Presentation1
Presentation1
 
As reais razões do porque eu devo ser Ágil - Agile Tour São Paulo
As reais razões do porque eu devo ser Ágil - Agile Tour São PauloAs reais razões do porque eu devo ser Ágil - Agile Tour São Paulo
As reais razões do porque eu devo ser Ágil - Agile Tour São Paulo
 
Rails Contributors
Rails ContributorsRails Contributors
Rails Contributors
 
Do your own hacking evening - RubyConf UR
Do your own hacking evening - RubyConf URDo your own hacking evening - RubyConf UR
Do your own hacking evening - RubyConf UR
 

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

Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
Yehuda Katz
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
Guillaume Laforge
 

Similaire à O que há de novo no Rails 3 - Ruby on Rails no Mundo Real - 23may2010 (20)

Tdc 2013 - Ecossistema Ruby
Tdc 2013 - Ecossistema RubyTdc 2013 - Ecossistema Ruby
Tdc 2013 - Ecossistema Ruby
 
Crafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyCrafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in Ruby
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
Spring into rails
Spring into railsSpring into rails
Spring into rails
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
Generators
GeneratorsGenerators
Generators
 
Speedy TDD with Rails
Speedy TDD with RailsSpeedy TDD with Rails
Speedy TDD with Rails
 
Rails3 changesets
Rails3 changesetsRails3 changesets
Rails3 changesets
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Ruby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developerRuby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developer
 
Ecossistema Ruby - versão SCTI UNF 2013
Ecossistema Ruby - versão SCTI UNF 2013Ecossistema Ruby - versão SCTI UNF 2013
Ecossistema Ruby - versão SCTI UNF 2013
 
Rails 4.0
Rails 4.0Rails 4.0
Rails 4.0
 
Deploy Rails Application by Capistrano
Deploy Rails Application by CapistranoDeploy Rails Application by Capistrano
Deploy Rails Application by Capistrano
 
Fisl - Deployment
Fisl - DeploymentFisl - Deployment
Fisl - Deployment
 
Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!
 
Fisl 11 - Dicas de Desenvolvimento Web com Ruby
Fisl 11 - Dicas de Desenvolvimento Web com RubyFisl 11 - Dicas de Desenvolvimento Web com Ruby
Fisl 11 - Dicas de Desenvolvimento Web com Ruby
 
Introduction à Ruby
Introduction à RubyIntroduction à Ruby
Introduction à Ruby
 
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
JavaOne 2008 - TS-5793 - Groovy and Grails, changing the landscape of Java EE...
 
Rails-3-app-auto-generator-20100817
Rails-3-app-auto-generator-20100817Rails-3-app-auto-generator-20100817
Rails-3-app-auto-generator-20100817
 

Plus de Plataformatec

The Plafatorma Way - Oxente Rails - 05aug2010
The Plafatorma Way - Oxente Rails - 05aug2010The Plafatorma Way - Oxente Rails - 05aug2010
The Plafatorma Way - Oxente Rails - 05aug2010
Plataformatec
 

Plus de Plataformatec (11)

Product Owner - Simples como dizem? - Agile Tour 2011
Product Owner - Simples como dizem? - Agile Tour 2011Product Owner - Simples como dizem? - Agile Tour 2011
Product Owner - Simples como dizem? - Agile Tour 2011
 
Writing your own programming language to understand Ruby better - Euruko 2011
Writing your own programming language to understand Ruby better - Euruko 2011Writing your own programming language to understand Ruby better - Euruko 2011
Writing your own programming language to understand Ruby better - Euruko 2011
 
Railties - Ruby Masters Conf - 26Feb2011
Railties - Ruby Masters Conf - 26Feb2011Railties - Ruby Masters Conf - 26Feb2011
Railties - Ruby Masters Conf - 26Feb2011
 
Rails 3 - The Developers Conference - 21aug2010
Rails 3 - The Developers Conference - 21aug2010Rails 3 - The Developers Conference - 21aug2010
Rails 3 - The Developers Conference - 21aug2010
 
CRUDing Open Source - WhyDay - 19aug2010
CRUDing Open Source - WhyDay - 19aug2010CRUDing Open Source - WhyDay - 19aug2010
CRUDing Open Source - WhyDay - 19aug2010
 
Rails 3 - RS on Rails - 21aug2010
Rails 3 - RS on Rails - 21aug2010Rails 3 - RS on Rails - 21aug2010
Rails 3 - RS on Rails - 21aug2010
 
Project Rescue - Oxente Rails - 05aug2010
Project Rescue - Oxente Rails - 05aug2010Project Rescue - Oxente Rails - 05aug2010
Project Rescue - Oxente Rails - 05aug2010
 
The Plafatorma Way - Oxente Rails - 05aug2010
The Plafatorma Way - Oxente Rails - 05aug2010The Plafatorma Way - Oxente Rails - 05aug2010
The Plafatorma Way - Oxente Rails - 05aug2010
 
DSL or NoDSL - Euruko - 29may2010
DSL or NoDSL - Euruko - 29may2010DSL or NoDSL - Euruko - 29may2010
DSL or NoDSL - Euruko - 29may2010
 
Classificação de textos - Dev in Sampa - 28nov2009
Classificação de textos - Dev in Sampa - 28nov2009Classificação de textos - Dev in Sampa - 28nov2009
Classificação de textos - Dev in Sampa - 28nov2009
 
Devise - RSLA - 13oct2009
Devise - RSLA - 13oct2009Devise - RSLA - 13oct2009
Devise - RSLA - 13oct2009
 

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

  • 1. Rails 3 Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 2. Rails 3 ID blog twitter Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 5. Desevolvemos aplicações em Rails Coaching em Consultoria Rails e Agile Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 6. Arquitetura Rails 3 Rails ActionDispatch ActiveSupport Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 7. Arquitetura Todo o resto são Rails 3 Railties! Rails ActionDispatch ActiveSupport Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. Vantagens do Rails 3 Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 10. Vantagens do Rails 3 Performance Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 11. Vantagens do Rails 3 Agnóstico Performance Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 12. Vantagens do Rails 3 Modularidade Agnóstico Performance Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. blog/config.ru require ::File.expand_path('../config/environment', __FILE__) run Blog::Application Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 16. blog/config.ru require ::File.expand_path('../config/environment', __FILE__) run Blog::Application Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. 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. 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. 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. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 24. Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 25. Biblioteca para gerenciamento de dependências Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. # 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. # 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. Resolução de dependências Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. Resolução de dependências require "rubygems" require "thin" gem "actionpack", "2.3.5" Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. Gemfile # Gemfile gem "thin" gem "actionpack", "2.3.5" Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. Lock no $LOAD_PATH Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 38. Esqueci de colocar no config.gem! Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 39. Esqueci de colocar no config.gem! Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. } 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. } 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. guru/code$ gem list rake (0.8.7, 0.8.5) thor (0.13.6) Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. 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. 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. Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 50. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 51. Router Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 52. Nova API Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 53. Rotas root Rails 2.3 map.root :controller => "welcome" Rails 3 root :to => "welcome#index" Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. Router and Rack FTW! Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 58. Rack FTW! Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 59. Rack FTW! match "posts/:echo" => "posts#show" Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 64. ActionMailer new API Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. 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. 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. 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. AbstractController::Base ActionController::Metal ActionMailer::Base ActionController::Base Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 72. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 73. ActiveModel Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 74. ActiveModel Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 75. ActiveModel • Google Summer of Code 2009: Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 76. ActiveModel • Google Summer of Code 2009: • Extraira lógica comum entre ActiveRecord e ActiveResource Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 77. ActiveModel • Google Summer of Code 2009: • Extraira lógica comum entre ActiveRecord e ActiveResource • Hoje Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. 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. Agnosticismo de ORM Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 83. Agnosticismo de ORM Agnosticismo de ORM ActiveModel Rails::Railtie Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. ActiveModel::Lint::Tests Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. ActiveRecord-like Ótimo exemplo de uso do ActiveModel http://github.com/plataformatec/mail_form Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 90. ActiveModel Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 91. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 92. Responders Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. RAILS 3.0 respond_to :html, :xml def index @users = User.all respond_with(@users) end Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. Navigational API GET POST PUT DELETE Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 98. Navigational API GET POST PUT DELETE Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 99. Navigational API GET POST PUT DELETE Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 100. respond_to :html, :xml def index @users = User.all respond_with(@users) end Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 101. Navigational API render GET render template collection.to_format POST PUT DELETE Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. 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. respond_with(@users) ActionController::Responder Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. Responders Customizados Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 109. github.com/plataformatec/responders Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 110. github.com/plataformatec/responders Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. 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. 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. 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. 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. Responders Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 119. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 120. ARel Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. 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. 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. 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. 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. 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. ARel Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 130. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 131. Unobtrusive Javascript Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. JS Driver Markup com HTML 5 custom data attributes JS Driver JS Framework Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. Javascript no Rails 3 Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. Bundler Router ActionMailer ActiveModel Responders ARel Unobtrusive Javascript XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 147. XSS Protection Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 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. 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. 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. 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. 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. 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. 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. Tem muito mais aqui! http://github.com/plataformatec Hugo Baraúna blog.plataformatec.com @hugobarauna
  • 156. Tem muito mais aqui! http://github.com/plataformatec ID blog twitter Hugo Baraúna blog.plataformatec.com @hugobarauna