Ruby 2.0 Rundown
@benjaminoakes
Ruby 2.0 was released on its birthday, Feb 24th
From a developer's perspective:
Things I like:
__dir__%i / %I
to_hNot ready for prodution use, yet.
Object are now privateThese problems will shake out over time.
Some breakage is to be expected.
Many thanks to Mat Sadler for his writeup.
=> __dir__
%i / %I
to_h__dir__If you've ever hated writing File.dirname(__FILE__) over and over, you'll love this
p __dir__
# => "/vagrant"
            __dir__=> %i / %I
to_h%iLike %w(), but for symbols.
p %i(panda bamboo)
# => [:panda, :bamboo]
Seems roughly the same as:
p %w(panda bamboo).map { |s| s.intern }
# => [:panda, :bamboo]
Like normal, be careful when making symbols from user input.
__dir__%i / %I
=> to_h
to_hHash representation of an object.to_s, to_a, and to_sym for the other core types, why not to_h?serializable_hash in Rails.to_h (cont'd)Searching ruby-doc.org core gave:
ENV.to_hHash#to_hNilClass#to_hStruct#to_h...and a handful of aliases called to_hash (from 1.9)
to_h (cont'd)p ENV.to_h # => {"TERM"=>"xterm", "SHELL"=>"/bin/bash", ...}
p {}.to_h # => {}
p nil.to_h # => {}
s = Struct.new(:panda, :bamboo).new
p s.to_h # => {:panda=>nil, :bamboo=>nil}
            to_h (cont'd)Searching ruby-doc.org std-lib gave:
OpenStruct#to_hJSON::Ext::Generator::StateXMLRPC::FaultExceptionOpenSSL::X509::Extensionto_h (cont'd)require 'ostruct'
os = OpenStruct.new(panda: 'bamboo')
p os # => #<OpenStruct panda="bamboo">
p os.to_h # => {:panda=>"bamboo"}
            to_h (cont'd)to_h (cont'd)This doesn't work:
%w(panda bamboo).to_h
# => NoMethodError: undefined method `to_h'
I might have expected behavior like this:
p Hash['panda', 'bamboo']
# => {"panda"=>"bamboo"}
            to_h (cont'd)I screwed that up the first time (nested array Hash[['panda', 'bamboo']]), and got a bunch of new warnings:
# (irb):5: warning: wrong element type String
#     at 0 (expected array)
# (irb):5: warning: ignoring wrong elements is
#     deprecated, remove them explicitly
# (irb):5: warning: this causes ArgumentError
#     in the next release
# [...]
In Ruby 1.9.3, it would print no warnings and return {}.
to_h (cont'd)I also was hoping JSON would take advantage (More info)
require 'json'
p JSON.generate(ENV)
# => /usr/local/lib/ruby/2.0.0/json/common.rb:
#       223:in `generate': only generation of
#       JSON objects or arrays allowed
#       (JSON::GeneratorError)
#   from /usr/local/lib/ruby/2.0.0/json/common.rb:223:
#       in `generate'
#   from tmp/talk_code.rb:3:in `<main>'
            to_h (cont'd)Can do:
require 'json'
p ENV.to_h.to_json
# => "{\"TERM\":\"xterm\",\"SHELL\": ...
            to_h (cont'd)Hash[] too, if you've ever done that.to_h (cont'd)Duck typing example:
def eat(diet)
  diet.to_h[:eats]
end
panda_diet = { eats: 'bamboo' }
p eat(panda_diet)
# => "bamboo"
            to_h (cont'd)Duck typing example:
def eat(diet)
  diet.to_h[:eats]
end
panda_diet = Struct.new(:eats).new('bamboo')
p eat(panda_diet)
# => "bamboo"
            to_h (cont'd)Duck typing with "coercion" example:
def eat(diet)
  # New in 2.0: `Hash(obj)`
  #
  # Like `Array(obj)` or `String(obj)`
  #
  # Similar in 1.9: `Hash[diet]`
  Hash(diet)[:eats]
end
panda_diet = { eats: 'bamboo' }
p eat(panda_diet)
# => "bamboo"
            __dir__%i / %I
to_h=> Keyword argumentsFinally, a built in way to handle what we already do all the time:
some_method(positional_arg, panda: 'bamboo')
            # Ruby < 2.0 idiom
def some_method(positional_arg, opts)
  panda = opts[:panda] || 'bamboo'
  # ...
end
# Ruby 2.0
def some_method(positional_arg, panda: 'bamboo')
  # ...
end
            2 ways of defining
# As keywords
def keywords(positional, panda: 'bamboo', place: 'Earth')
  p positional
  p panda
  p place
end
keywords('foo', panda: 'kung fu')
# =>
# "foo"
# "kung fu"
# "Earth"
            # As keywords
def keywords(positional, panda: 'bamboo', place: 'Earth')
  p positional
  p panda
  p place
end
# 1.8 style hashes accepted
keywords('eats', :panda => 'shoots and leaves')
# =>
# "eats"
# "shoots and leaves"
# "Earth"
            # As keywords
def keywords(positional, panda: 'bamboo', place: 'Earth')
  p positional
  p panda
  p place
end
# Position doesn't matter
keywords('greeting', place: 'China', panda: 'nom nom nom')
# =>
# "greeting"
# "nom nom nom"
# "China"
            # As a capture ("double splat")
#
# Kind of like Python, but better.
#
# Because it's Ruby.
def capture(**kwargs)
  p kwargs
end
capture(anything: 'that', I: 'want')
# =>
# {:anything=>"that", :I=>"want"}
            __dir__%i / %I
to_h=> Lazy evaluationEnumerator (Enumerator::Lazy)Panda.where(...) doesn't retreive a result until needed)From the docs:
# See Kernel#to_enum for the definition of repeat
require_relative './repeat'
r = 1..Float::INFINITY
r.repeat(2).first(5) # => [1, 1, 2, 2, 3]
r.repeat(2).class # => Enumerator
# r.repeat(2).map { |n| n ** 2 }.first(5) # => endless loop!
# works naturally on lazy enumerator:
r.lazy.repeat(2).class # => Enumerator::Lazy
r.lazy.repeat(2).map { |n| n ** 2 }.first(5) # => [1, 1, 4, 4, 9]
            There's a lot of changes, but those are some that I like.
Kernel#require performance improvementsFloat operation performance improvementsModule#prepend./configure && make && sudo make install)rvm or rbenv
rvm pkg install openssl firstThese were very useful when preparing this.
Module#prependReplacement for alias_method_chain hackery.
Module#include examplemodule Diet
  def eats; 'bamboo'; end
end
class Panda
  include Diet
  def eats; 'shoots and leaves'; end
end
p Panda.new.eats # => 'shoots and leaves'
            Module#prepend examplemodule Diet
  def eats; 'bamboo'; end
end
class Panda
  prepend Diet # <-------
  def eats; 'shoots and leaves'; end
end
p Panda.new.eats # => 'bamboo'