Upgrade to Pro — share decks privately, control downloads, hide ads and more …

O que mudou no Ruby 2.0

O que mudou no Ruby 2.0

Veja a palestra apresentada no 29º GURU-SP.

Cb5d9e9095cd41b636764a85e57ade4b?s=128

Nando Vieira

April 13, 2013
Tweet

Transcript

  1. O QUE MUDOU NO RUBY 2.0 NANDO VIEIRA

  2. http://nandovieira.com.br

  3. http://hellobits.com

  4. http://howtocode.com.br howto.

  5. http://codeplane.com.br

  6. @fnando nando@hellobits.com simplesideias.com.br

  7. RUBY 1.8 Se você ainda está usando Ruby 1.8, corra

    e atualize sua aplicação. Em junho esta versão deixará receber atualizações, inclusive de segurança.
  8. RUBY 1.9 O primeiro release estável saiu em dezembro de

    2009 e trouxe uma série de mudanças incompativeis com o Ruby 1.8.
  9. RUBY 2.0 Lançada em fevereiro de 2013, esta versão possui

    compatibilidade quase que total com o Ruby 1.9.
  10. Instalação http://apt.hellobits.com

  11. Instalação $ vagrant box add hellobits \ http://hellobits.com/vagrant/hellobits.box

  12. Instalação $ rvm install ruby-2.0.0

  13. Instalação $ rbenv install 2.0.0-p0

  14. Keyword Arguments Há sintaxe de hashes e argumentos nomeados foi

    proposta há quase 11 anos e, só agora, foi completamente implementada. http://fnando.me/d2
  15. def currency(number, options = {}) end

  16. precision = options.fetch(:precision, 3) unit = options.fetch(:unit, "$") format =

    options.fetch(:format, "%u%n")
  17. def currency(number, format: "%u%n", unit: "$", precision: 3) end

  18. Exceções A exceção ArgumentError é lançada se um argumento não

    esperado for passado.
  19. currency 1.234, separator: "," `<main>': unknown keyword: separator (ArgumentError)

  20. Splat Você pode agrupar argumentos não esperados com o splat.

  21. class Sample def method_missing(name, *args, &block) p args end end

    sample = Sample.new sample.say :what, :are, :you, :doing? #=> [:what, :are, :you, :doing?]
  22. Double Splat Você pode agrupar argumentos nomeados não esperados com

    o double splat.
  23. class Sample def method_missing(name, *args, **keys, &block) p keys end

    end sample = Sample.new sample.say what: "are", you: "doing?" #=> {:what=>"are", :you=>"doing?"}
  24. **keys Agrupa argumentos nomeados não esperados pelo método.

  25. def params(a, b = nil, *args, c: nil, **kwords, &block)

    end p method(:params).parameters
  26. def params(a, b = nil, *args, c: nil, **kwords, &block)

    end [ [:req, :a], [:rest, :args], [:key, :c], [:keyrest, :kwords], [:block, :block] ]
  27. Literais no Ruby O Ruby possui muitos literais para de

    nir strings e arrays. Agora também podemos de nir arrays de símbolos.
  28. platforms = [:mac, :linux, :windows] platforms = %i[ mac linux

    windows ]
  29. p %i[#{Time.now}] #=> [:"\#{Time.now}"] p %I[#{Time.now}] #=> [:"2013-04-13 02:05:58 -0300"]

  30. Encoding O encoding padrão do no Ruby 1.9 é US-ASCII.

    Para usar caracteres acentuados era preciso usar o magic comment.
  31. puts __ENCODING__ #=> US-ASCII text = "áéíóú" puts text #=>

    invalid multibyte char (US-ASCII)
  32. puts __ENCODING__ #=> UTF-8 text = "áéíóú" puts text #=>

    áéíóú
  33. Module#prepend Altera a hierarquia de classes e módulos, adicionando um

    módulo antes da própria classe.
  34. class MyClass def foo puts "foo" end end

  35. De nir um novo método, sobrescrevendo a implementação original.

  36. class MyClass foo_method = instance_method(:foo) define_method :foo do puts "before

    foo" result = foo_method.bind(self).call puts "after foo" result end end MyClass.new.foo #=> before foo #=> original #=> after foo
  37. De nir um alias para o método original e sobrescrever

    o método original com a nova implementação.
  38. class MyClass alias_method :foo_original, :foo def foo puts "before foo"

    result = foo_original puts "after foo" result end end MyClass.new.foo #=> before foo #=> original #=> after foo
  39. Usar o método Module#alias_method_chain , que segue a mesma ideia

    da implementação com alias.
  40. require "active_support/all" class MyClass def foo_with_puts puts "before foo" result

    = foo_without_puts puts "after foo" result end alias_method_chain :foo, :puts end MyClass.new.foo #=> before foo #=> original #=> after foo
  41. Usar o método Module#prepend para alterar a hierarquia de classes

    e módulos.
  42. module FooExtension def foo puts "before foo" super puts "after

    foo" end end class MyClass prepend FooExtension end MyClass.new.foo #=> before foo #=> original #=> after foo
  43. Hierarquia Como o módulo FooExtensions foi adicionado antes da própria

    classe MyClass, é possível chamar o super.
  44. MyClass.ancestors #=> [FooExtension, MyClass, Object, Kernel, BasicObject]

  45. Classes abertas Classes abertas e monkey patching sempre foi um

    motivo de preocupação dos iniciantes.
  46. Re nements O Re nements tenta amenizar esta situação permitindo

    fazer monkey patching de modo controlado.
  47. # file: time_extension.rb module TimeExtension refine Integer do def minutes

    self * 60 end end end
  48. # file: with_refinement.rb require_relative "time_extension" using TimeExtension puts 5.minutes #=>

    300
  49. # file: without_refinement.rb require_relative "time_extension" puts 5.minutes #=> undefined method

    `minutes' for 10:Fixnum (NoMethodError)
  50. Re nements Existem tantas incertezas em relação ao re nements

    e isso é reforçado através de um warning ao usar o método Module.re ne.
  51. warning: Refinements are experimental, and the behavior may change in

    future versions of Ruby!
  52. OpenStruct Estrutura de dados aberta com atributos que podem ser

    de nidos de forma arbitrária.
  53. require "ostruct" user = OpenStruct.new( name: "John Doe", email: "john@example.org"

    ) puts user.name #=> John Doe puts user.email #=> john@example.org
  54. puts user[:name] #=> John Doe puts user["name"] #=> John Doe

  55. user["name"] = "John D." puts user.name #=> John D.

  56. p user.to_h #=> {:name=>"John Doe", :email=>"john@example.org", :age=>42}

  57. Regexp O Ruby 2.0 mudou seu engine de expressão regular

    mais uma vez. O Oniguruma saiu para dar lugar ao Onigmo.
  58. text = "Line 1\r\nLine 2\vLine 3\nLine 4" lines = text.split(/\R/)

    p lines #=> ["Line 1", "Line 2", "Line 3", "Line 4"]
  59. (?(cond)if|else)

  60. regex = /^(\[a-z]{2})(\1)?(?(2)([a-z]+)|(\d+))$/ "aaaabbbbb".match(regex) #<MatchData "aaaabbbbb" 1:"aa" 2:"aa" 3:"bbbbb" 4:nil>

    "ababccccc".match(regex) #<MatchData "ababccccc" 1:"ab" 2:"ab" 3:"ccccc" 4:nil> "ab1111111".match(regex) #<MatchData "ab1111111" 1:"ab" 2:nil 3:nil 4:"1111111"> "abccccccc".match(regex) # nil "1212ccccc".match(regex) # nil
  61. LoadError Agora é possível saber qual arquivo não foi carregado

    sem ter que fazer parsing do backtrace.
  62. begin require "some/missing/file" rescue LoadError => error puts error.path end

  63. Constantes O método Object.const_get agora aceita um namespace completo, em

    vez de apenas um componente do namespace.
  64. module A module B module C end end end

  65. "A::B::C" .split("::") .reduce(Object) {|scope, name| scope.const_get(name) }

  66. Object.const_get("A::B::C")

  67. Kernel#__dir__ Agora é possível pegar uma referência do diretório atual

    de um script que está sendo executado.
  68. puts __FILE__ #=> ruby20_dir.rb puts __dir__ #=> /Projects/samples puts File.dirname(File.realpath(__FILE__))

    #=> /Projects/samples
  69. module Kernel alias_method :__DIR__, :__dir__ end puts __dir__ #=> /Projects/samples

    puts __DIR__ #=> /Projects/samples
  70. String enumerators Diversos métodos da classe String que antes retornavam

    enumerators agora retornam arrays.
  71. %[Line 1\nLine 2\nLine 3].lines #=> ["Line 1\n", "Line 2\n", "Line

    3"] %[abcdef].chars #=> ["a", "b", "c", "d", "e", "f"] %[abcdef].bytes #=> [97, 98, 99, 100, 101, 102] %[abcdef].codepoints #=> [97, 98, 99, 100, 101, 102]
  72. Enumerator#lazy O Ruby 2.0 introduziu um modo de criarmos enumerators

    que podem ser executados em conjuntos grandes ou mesmo in nitos.
  73. range = (1..Float::INFINITY)

  74. require "prime" range = (0..Float::INFINITY) primes = range.lazy .reject {|number|

    number < 50 } .select(&:prime?) .first(10) primes #=> [53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
  75. require "benchmark" require "prime" GC.disable range = (0..1000) cycles =

    1_000 def primes(range) range .reject {|number| number < 50 } .select(&:prime?) .first(10) end Benchmark.bmbm do |x| x.report("with lazy") do cycles.times { primes(range.lazy) } end x.report("without lazy") do cycles.times { primes(range) } end end
  76. Rehearsal ------------------------------------------------ with lazy 0.250000 0.020000 0.270000 ( 0.265709) without

    lazy 4.740000 0.390000 5.130000 ( 5.219114) --------------------------------------- total: 5.400000sec user system total real with lazy 0.260000 0.020000 0.280000 ( 0.280212) without lazy 5.090000 0.420000 5.510000 ( 5.576948)
  77. Muito mais! Backtrace otimizado, TracePoint, DTrace, __callee__, otimizações na VM

    (fork mais rápido), melhorias no Garbage Collector, Kernel#require mais rápido, Rubygems com suporte ao Gem le, e mais um monte de coisas!
  78. OBRIGADO!