o que mudou
 no ruby 1.9
   nando vieira
minhas urls
• http://simplesideias.com.br
• http://howtocode.com.br
• http://spesa.com.br
• http://twitter.com/fnando
• http://github.com/fnando
ruby 1.9
• lançado em dezembro de 2008
• prévia estável da versão 2.0
• mais rápido
• menos memória
• muitas mudanças
YARV BasicObject
                 *splat
Oniguruma Fiber
        Rake      Threads
m17n  Date
              Blocks
 Lambda Array
                 String
          JSON
RubyGems Rdoc Object
 Hash
   Symbol   Enumerable
m17n
multilingualization


 • apenas um tipo de string
 • codificação é mutável
 • pode ser definida de várias maneiras
 • se estende por toda a linguagem
m17n
codificações disponíveis
ASCII-8BIT   IBM437          ISO-8859-10   macCroatian   UTF-32BE
Big5         IBM737          ISO-8859-11   macCyrillic   UTF-32LE
CP51932      IBM775          ISO-8859-13   macGreek      UTF-7
CP850        IBM852          ISO-8859-14   macIceland    UTF-8
CP852        IBM855          ISO-8859-15   MacJapanese   UTF8-MAC
CP855        IBM857          ISO-8859-16   macRoman      Windows-1250
CP949        IBM860          ISO-8859-2    macRomania    Windows-1251
Emacs-Mule   IBM861          ISO-8859-3    macThai       Windows-1252
EUC-JP       IBM862          ISO-8859-4    macTurkish    Windows-1253
EUC-KR       IBM863          ISO-8859-5    macUkraine    Windows-1254
EUC-TW       IBM864          ISO-8859-6    Shift_JIS     Windows-1255
eucJP-ms     IBM865          ISO-8859-7    stateless-    Windows-1256
GB12345      IBM866          ISO-8859-8    ISO-2022-JP   Windows-1257
GB18030      IBM869          ISO-8859-9    TIS-620       Windows-1258
GB1988       ISO-2022-JP     KOI8-R        US-ASCII      Windows-31J
GB2312       ISO-2022-JP-2   KOI8-U        UTF-16BE      Windows-874
GBK          ISO-8859-1      macCentEuro   UTF-16LE
$KCODE
(irb):1: warning: variable $KCODE
   is no longer effective; ignored
m17n
em todos os lugares

      Em strings
 text.encode("utf-8")

 text.force_encoding("iso-8859-1")




      Em arquivos
 # encoding: utf-8
 £ = 2.68
 maçã = "apple"
m17n
em arquivos
# coding: utf-8
# encoding: utf-8
# -*- coding: utf-8 -*-           Magic
# vim:fileencoding=utf-8         Comments
                                /coding[:=] ?/
# vim:set fileencoding=utf-8 :
m17n
em todos os lugares

      Em IO
 f = File.open("file.txt", "r:utf-8")
 f.external_encoding #=> utf-8

 f = File.open("file.txt", "w+:utf-8:iso-8859-1")
 f.external_encoding #=> utf-8
 f.internal_encoding #=> iso-8859-1


 f = File.open("img.png", "r:binary")
 f.encoding #=> ASCII-8BIT
strings
codificação
      "maçã".length
1.8   #=> 6

      "abcd"[0]
      #=> 97


      "maçã".length
1.9   #=> 4

      "abcd"[0]
      #=> a

      "abcd".codepoints.to_a[0]
                                  Retorna a representação
      #=> 97                      numérica dos caracteres
      "abcd"[0].ord
      #=> 97
strings
codificação
      "áéíóu"[0,1]
1.8   #=> 303

      "áéíóú".tr("áéíóú", "aeiou")
      #=> ueuouuuuuu


      "áéíóú"[0]
1.9   #=> á

      "áéíóú".tr("áéíóú", "aeiou")
      #=> aeiou
strings
enumerable
      String.ancestors
1.8   #=> [String, Enumerable, Comparable, Object, Kernel]

      text.each {|line| puts line }



      String.ancestors
1.9   #=> [String, Comparable, Object, Kernel, BasicObject]

      text.each_line {|line| puts line }
      text.each_char {|char| puts char }
      text.each_byte {|byte| puts byte }
      text.each_codepoint {|codepoint| puts codepoint }
símbolos
string-wannabe

 • pode ser comparado com regexes
 • pode ser acessado como strings
 • possui muitos métodos da classe String
 • :symbol.to_s é menos frequente
símbolos
string-wannabe
1.9   :cool[0]
      #=> "c"

      :cool =~ /cool/
      #=> 0

      :cool.upcase
      #=> COOL

      :"maçã".length
      #=> 4

      [:c, :b, :a].sort
      #=> [:a, :b, :c]
símbolos
blocos

 • to_proc agora é nativo
 • é muito rápido
  chars = %w(a b c d)
  1_000_000.times { chars.collect(&:upcase) }


            user     system       total        real
1.8    16.380000   3.700000   20.080000   20.333704

            user     system       total        real
1.9     5.300000   0.040000    5.340000    5.365868
símbolos
métodos & variáveis

1.8   Object.methods.grep(/variables/)
      #=> ["class_variables", "instance_variables"]

      object.instance_variables
      #=> ["@name", "@type"]



      Object.methods.grep(/variables/)
1.9   #=> [:class_variables, :instance_variables]

      object.instance_variables
      #=> [:name, :type]
regexp
nova engine


 • utiliza a biblioteca oniguruma
 • muito mais rápida
 • suporta diversas codificações
 • possui uma sintaxe estendida
regexp
sintaxe
 1.9 named groups
    date = "2009-09-01"
    regexp = /(?<ano>d{4})-(?<mes>d{2})-(?<dia>d{2})/
    date.gsub(regexp, 'k<dia>/k<mes>/k<ano>')
    #=> 01/09/2009
    matches = s.match(/(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/)
    matches[:year]


    look behind
    str = "rasa asa casa"
    str.gsub(/((?<=[rc])asa)/, '[1]')
    #=> r[asa] asa c[asa]

    str.gsub(/((?<![rc])asa)/, '[1]')
    #=> rasa [asa] casa
regexp
codificação
        text = "text: Γενηθήτω φῶς"
1.9     match = text.match(/(?<greek>b[p{Greek} ]+b)/)
        match[:greek]
        #=> Γενηθήτω φῶς



                                                       Documentação
http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt
                                                       Oficial
regexp
erro comum
       require "open-uri"
1.8    contents = open("http://google.com").read
       _, title = *contents.match(/<title>(.*?)</title>/sim)
       p title
       #=> "Google"


                     Encoding::CompatibilityError: incompatible encoding
      Ruby 1.9:      regexp match (Windows-31J regexp with ISO-8859-1 string)



      /<title>(.*?)</title>/sim            /<title>(.*?)</title>/im
hash
nova sintaxe
      dict = {
1.8     :mac => "Mac OS X",
        :win => "Windows Vista Tabajara Version"
      }

      redirect_to :action => "show"



      dict = {
1.9     mac: "Mac OS X",
        win: "Windows Vista Tabajara Version"
      }

      redirect_to action: "show"
:key => value
hash
ordem dos itens
      hash = {:c => 3, :b => 2, :a => 1}
1.8   #=> {:a=>1, :b=>2, :c=>3}

      hash.keys
      #=> [:a, :b, :c]




      hash = {:c => 3, :b => 2, :a => 1}
1.9   #=> {:c=>3, :b=>2, :a=>1}

      hash.keys
      #=> [:c, :b, :a]
hash
seleção
      hash.select {|key, value| key == :a }
1.8   #=> [[:a, 1]]

      hash.index(1)
      #=> :a               Deprecated

      hash.select {|key, value| key == :a }
1.9   #=> {:a => 1}

      hash.key(1)
      #=> :a               Novo método
date/time
mudanças
      Time.now.monday?          sunday?, monday?, tuesday?, wednesday?,
1.9   #=> true                  thursday?, friday?, saturday?




      Time.parse "10/13/2009"
1.8   #=> 2009-10-13
                                     mm/dd/aaaa
                                           vs
      Time.parse "13/10/2009"
1.9   #=> 2009-10-13
                                     dd/mm/aaaa
lambda
funções anônimas
       sum = lambda {|*args| args.reduce(:+) }
1.8    sum = lambda {|*args| args.inject(0) {|s,n| s += n; s } }



1.9    sum = -> *args { args.reduce(:+) }



sum.call(1,2,3)
#=> 6

sum[1,2,3]
#=> 6

sum.(1,2,3)       Ruby 1.9
#=> 6
basic object
começando do zero
BasicObject.superclass
#=> nil


Object.superclass
#=> BasicObject


BasicObject.instance_methods
#=> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]


class MyClass < BasicObject; end
object
#tap
       user = User.new.tap do |u|
1.9      u.name = "Nando Vieira"
         u.blog = "http://simplesideias.com.br"
       end
bloco
escopo de variáveis
      n = 0
1.8
      (1..10).each do |n|
      end

      #=> n = 10


      n = 0                 n = 1
1.9
      (1..10).each do |n|   lambda {|;n| n = 2 }.call
      end
                            #=> n = 1
      #=> n = 0
suporte
como lidar com ambas as versões

class Sample
  if String.method_defined?(:encode)
    def some_method
    end
  else
    def some_method
    end
  end
end
suporte
como lidar com ambas as versões


unless String.method_defined?(:encode)
  class String
    def encode(*options)
    end
  end
end
mais mudanças
operador *splat
      def group(a, b, *c)
1.8     [a, b, c]
      end

      group(1,2,3,4,5)
      #=> [1, 2, [3, 4, 5]]



      def group(a, *b, c)
1.9     [a, b, c]
      end

      group(1,2,3,4,5)
      #=> [1, [2, 3, 4], 5]
mais mudanças
valor padrão de argumentos
      def color(type, value)
1.8   end
                               Como fazer "type" ser "hex" por padrão?


      color(:rgb, [255, 255, 255])   a) Precisa mudar a ordem dos parâmetros
      color([255, 255, 255])         b) Sempre especificar os 2 parâmetros (?)



      def color(type=:hex, value)
1.9   end

      color(:rgb, [255, 255, 255])
      color("#fff")
mais mudanças
standard library + bundles

 • rubygems, rake, rdoc
 • fiber, enumerator, json (ext + pure), minitest,
   ripper, securerandom, probeprofiler

 • csv foi substituída por fastcsv
 • soap e wsdl foram removidas
mas e aí?
migrar ou não migrar para o Ruby 1.9?

 • todas as gems foram portadas
 • uma parte do sistema pode ser portada

         isitruby19.com
mas e aí?
migrar ou não migrar para o Ruby 1.9?




        testes
        pelo menos as partes críticas
one more thing


     apenas R$10
     http://howtocode.com.br
dúvidas?
obrigado
nando@simplesideias.com.br

O que mudou no Ruby 1.9

  • 1.
    o que mudou no ruby 1.9 nando vieira
  • 2.
    minhas urls • http://simplesideias.com.br •http://howtocode.com.br • http://spesa.com.br • http://twitter.com/fnando • http://github.com/fnando
  • 3.
    ruby 1.9 • lançadoem dezembro de 2008 • prévia estável da versão 2.0 • mais rápido • menos memória • muitas mudanças
  • 4.
    YARV BasicObject *splat Oniguruma Fiber Rake Threads m17n Date Blocks Lambda Array String JSON RubyGems Rdoc Object Hash Symbol Enumerable
  • 5.
    m17n multilingualization • apenasum tipo de string • codificação é mutável • pode ser definida de várias maneiras • se estende por toda a linguagem
  • 6.
    m17n codificações disponíveis ASCII-8BIT IBM437 ISO-8859-10 macCroatian UTF-32BE Big5 IBM737 ISO-8859-11 macCyrillic UTF-32LE CP51932 IBM775 ISO-8859-13 macGreek UTF-7 CP850 IBM852 ISO-8859-14 macIceland UTF-8 CP852 IBM855 ISO-8859-15 MacJapanese UTF8-MAC CP855 IBM857 ISO-8859-16 macRoman Windows-1250 CP949 IBM860 ISO-8859-2 macRomania Windows-1251 Emacs-Mule IBM861 ISO-8859-3 macThai Windows-1252 EUC-JP IBM862 ISO-8859-4 macTurkish Windows-1253 EUC-KR IBM863 ISO-8859-5 macUkraine Windows-1254 EUC-TW IBM864 ISO-8859-6 Shift_JIS Windows-1255 eucJP-ms IBM865 ISO-8859-7 stateless- Windows-1256 GB12345 IBM866 ISO-8859-8 ISO-2022-JP Windows-1257 GB18030 IBM869 ISO-8859-9 TIS-620 Windows-1258 GB1988 ISO-2022-JP KOI8-R US-ASCII Windows-31J GB2312 ISO-2022-JP-2 KOI8-U UTF-16BE Windows-874 GBK ISO-8859-1 macCentEuro UTF-16LE
  • 7.
    $KCODE (irb):1: warning: variable$KCODE is no longer effective; ignored
  • 8.
    m17n em todos oslugares Em strings text.encode("utf-8") text.force_encoding("iso-8859-1") Em arquivos # encoding: utf-8 £ = 2.68 maçã = "apple"
  • 9.
    m17n em arquivos # coding:utf-8 # encoding: utf-8 # -*- coding: utf-8 -*- Magic # vim:fileencoding=utf-8 Comments /coding[:=] ?/ # vim:set fileencoding=utf-8 :
  • 10.
    m17n em todos oslugares Em IO f = File.open("file.txt", "r:utf-8") f.external_encoding #=> utf-8 f = File.open("file.txt", "w+:utf-8:iso-8859-1") f.external_encoding #=> utf-8 f.internal_encoding #=> iso-8859-1 f = File.open("img.png", "r:binary") f.encoding #=> ASCII-8BIT
  • 11.
    strings codificação "maçã".length 1.8 #=> 6 "abcd"[0] #=> 97 "maçã".length 1.9 #=> 4 "abcd"[0] #=> a "abcd".codepoints.to_a[0] Retorna a representação #=> 97 numérica dos caracteres "abcd"[0].ord #=> 97
  • 12.
    strings codificação "áéíóu"[0,1] 1.8 #=> 303 "áéíóú".tr("áéíóú", "aeiou") #=> ueuouuuuuu "áéíóú"[0] 1.9 #=> á "áéíóú".tr("áéíóú", "aeiou") #=> aeiou
  • 13.
    strings enumerable String.ancestors 1.8 #=> [String, Enumerable, Comparable, Object, Kernel] text.each {|line| puts line } String.ancestors 1.9 #=> [String, Comparable, Object, Kernel, BasicObject] text.each_line {|line| puts line } text.each_char {|char| puts char } text.each_byte {|byte| puts byte } text.each_codepoint {|codepoint| puts codepoint }
  • 14.
    símbolos string-wannabe • podeser comparado com regexes • pode ser acessado como strings • possui muitos métodos da classe String • :symbol.to_s é menos frequente
  • 15.
    símbolos string-wannabe 1.9 :cool[0] #=> "c" :cool =~ /cool/ #=> 0 :cool.upcase #=> COOL :"maçã".length #=> 4 [:c, :b, :a].sort #=> [:a, :b, :c]
  • 16.
    símbolos blocos • to_procagora é nativo • é muito rápido chars = %w(a b c d) 1_000_000.times { chars.collect(&:upcase) } user system total real 1.8 16.380000 3.700000 20.080000 20.333704 user system total real 1.9 5.300000 0.040000 5.340000 5.365868
  • 17.
    símbolos métodos & variáveis 1.8 Object.methods.grep(/variables/) #=> ["class_variables", "instance_variables"] object.instance_variables #=> ["@name", "@type"] Object.methods.grep(/variables/) 1.9 #=> [:class_variables, :instance_variables] object.instance_variables #=> [:name, :type]
  • 18.
    regexp nova engine •utiliza a biblioteca oniguruma • muito mais rápida • suporta diversas codificações • possui uma sintaxe estendida
  • 19.
    regexp sintaxe 1.9 namedgroups date = "2009-09-01" regexp = /(?<ano>d{4})-(?<mes>d{2})-(?<dia>d{2})/ date.gsub(regexp, 'k<dia>/k<mes>/k<ano>') #=> 01/09/2009 matches = s.match(/(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/) matches[:year] look behind str = "rasa asa casa" str.gsub(/((?<=[rc])asa)/, '[1]') #=> r[asa] asa c[asa] str.gsub(/((?<![rc])asa)/, '[1]') #=> rasa [asa] casa
  • 20.
    regexp codificação text = "text: Γενηθήτω φῶς" 1.9 match = text.match(/(?<greek>b[p{Greek} ]+b)/) match[:greek] #=> Γενηθήτω φῶς Documentação http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt Oficial
  • 21.
    regexp erro comum require "open-uri" 1.8 contents = open("http://google.com").read _, title = *contents.match(/<title>(.*?)</title>/sim) p title #=> "Google" Encoding::CompatibilityError: incompatible encoding Ruby 1.9: regexp match (Windows-31J regexp with ISO-8859-1 string) /<title>(.*?)</title>/sim /<title>(.*?)</title>/im
  • 22.
    hash nova sintaxe dict = { 1.8 :mac => "Mac OS X", :win => "Windows Vista Tabajara Version" } redirect_to :action => "show" dict = { 1.9 mac: "Mac OS X", win: "Windows Vista Tabajara Version" } redirect_to action: "show"
  • 23.
  • 24.
    hash ordem dos itens hash = {:c => 3, :b => 2, :a => 1} 1.8 #=> {:a=>1, :b=>2, :c=>3} hash.keys #=> [:a, :b, :c] hash = {:c => 3, :b => 2, :a => 1} 1.9 #=> {:c=>3, :b=>2, :a=>1} hash.keys #=> [:c, :b, :a]
  • 25.
    hash seleção hash.select {|key, value| key == :a } 1.8 #=> [[:a, 1]] hash.index(1) #=> :a Deprecated hash.select {|key, value| key == :a } 1.9 #=> {:a => 1} hash.key(1) #=> :a Novo método
  • 26.
    date/time mudanças Time.now.monday? sunday?, monday?, tuesday?, wednesday?, 1.9 #=> true thursday?, friday?, saturday? Time.parse "10/13/2009" 1.8 #=> 2009-10-13 mm/dd/aaaa vs Time.parse "13/10/2009" 1.9 #=> 2009-10-13 dd/mm/aaaa
  • 27.
    lambda funções anônimas sum = lambda {|*args| args.reduce(:+) } 1.8 sum = lambda {|*args| args.inject(0) {|s,n| s += n; s } } 1.9 sum = -> *args { args.reduce(:+) } sum.call(1,2,3) #=> 6 sum[1,2,3] #=> 6 sum.(1,2,3) Ruby 1.9 #=> 6
  • 28.
    basic object começando dozero BasicObject.superclass #=> nil Object.superclass #=> BasicObject BasicObject.instance_methods #=> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__] class MyClass < BasicObject; end
  • 29.
    object #tap user = User.new.tap do |u| 1.9 u.name = "Nando Vieira" u.blog = "http://simplesideias.com.br" end
  • 30.
    bloco escopo de variáveis n = 0 1.8 (1..10).each do |n| end #=> n = 10 n = 0 n = 1 1.9 (1..10).each do |n| lambda {|;n| n = 2 }.call end #=> n = 1 #=> n = 0
  • 31.
    suporte como lidar comambas as versões class Sample if String.method_defined?(:encode) def some_method end else def some_method end end end
  • 32.
    suporte como lidar comambas as versões unless String.method_defined?(:encode) class String def encode(*options) end end end
  • 33.
    mais mudanças operador *splat def group(a, b, *c) 1.8 [a, b, c] end group(1,2,3,4,5) #=> [1, 2, [3, 4, 5]] def group(a, *b, c) 1.9 [a, b, c] end group(1,2,3,4,5) #=> [1, [2, 3, 4], 5]
  • 34.
    mais mudanças valor padrãode argumentos def color(type, value) 1.8 end Como fazer "type" ser "hex" por padrão? color(:rgb, [255, 255, 255]) a) Precisa mudar a ordem dos parâmetros color([255, 255, 255]) b) Sempre especificar os 2 parâmetros (?) def color(type=:hex, value) 1.9 end color(:rgb, [255, 255, 255]) color("#fff")
  • 35.
    mais mudanças standard library+ bundles • rubygems, rake, rdoc • fiber, enumerator, json (ext + pure), minitest, ripper, securerandom, probeprofiler • csv foi substituída por fastcsv • soap e wsdl foram removidas
  • 36.
    mas e aí? migrarou não migrar para o Ruby 1.9? • todas as gems foram portadas • uma parte do sistema pode ser portada isitruby19.com
  • 37.
    mas e aí? migrarou não migrar para o Ruby 1.9? testes pelo menos as partes críticas
  • 38.
    one more thing apenas R$10 http://howtocode.com.br
  • 39.
  • 40.