# Welcome
if
statements do not introduce scope in Ruby.
# Replace methods
{{{ Bilingual Ruby
class Employee
if String.method_defined?(:encode)
def name
...
end
else
def name
...
end
end
end
}}}
# Replace implementation
{{{ Bilingual Ruby
if String.method_defined?(:encode)
module Builder
...
end
else
class String
...
end
end
}}}
# CI Efforts
* Ruby
* Bacon
* Builder
* HTML5lib
* Libxml2
* OpenID
* REXML
* Rake (contrib)
* XMPP4R
# Part 1
{1 => 2}
# Array.to_s now contains punctuation
irb(main):001:0> [1,2,3].to_s
=> "[1, 2, 3]"
# Array.to_s now contains punctuation
irb(main):001:0> [1,2,3].to_s
=> "[1, 2, 3]"
irb(main):001:0> [1,2,3].to_s
=> "123"
# Array.to_s now contains punctuation
irb(main):001:0> [1,2,3].to_s
=> "[1, 2, 3]"
irb(main):001:0> [1,2,3].to_s
=> "123"
*Action*: use .join
instead
# Colon no longer valid in when statements
irb(main):001:0> case 'a'; when /\w/: puts 'word'; end
SyntaxError: (irb):1: syntax error, unexpected ':',
expecting keyword_then or ',' or ';' or '\n'
# Colon no longer valid in when statements
irb(main):001:0> case 'a'; when /\w/: puts 'word'; end
SyntaxError: (irb):1: syntax error, unexpected ':',
expecting keyword_then or ',' or ';' or '\n'
irb(main):001:0> case 'a'; when /\w/: puts 'word'; end
word
# Colon no longer valid in when statements
irb(main):001:0> case 'a'; when /\w/: puts 'word'; end
SyntaxError: (irb):1: syntax error, unexpected ':',
expecting keyword_then or ',' or ';' or '\n'
irb(main):001:0> case 'a'; when /\w/: puts 'word'; end
word
*Action*: use semicolon, then
, or newline
# block variables now shadow local variables
irb(main):001:0> i=0; [1,2,3].each {|i|}; i
=> 0
# block variables now shadow local variables
irb(main):001:0> i=0; [1,2,3].each {|i|}; i
=> 0
irb(main):002:0> i=0; for i in [1,2,3]; end; i
=> 3
# block variables now shadow local variables
irb(main):001:0> i=0; [1,2,3].each {|i|}; i
=> 0
irb(main):002:0> i=0; for i in [1,2,3]; end; i
=> 3
irb(main):001:0> i=0; [1,2,3].each {|i|}; i
=> 3
# Hash.index deprecated
irb(main):001:0> {1=>2}.index(2)
(irb):18: warning: Hash#index is deprecated; use Hash#key
=> 1
# Hash.index deprecated
irb(main):001:0> {1=>2}.index(2)
(irb):18: warning: Hash#index is deprecated; use Hash#key
=> 1
irb(main):002:0> {1=>2}.key(2)
=> 1
# Hash.index deprecated
irb(main):001:0> {1=>2}.index(2)
(irb):18: warning: Hash#index is deprecated; use Hash#key
=> 1
irb(main):002:0> {1=>2}.key(2)
=> 1
irb(main):001:0> {1=>2}.index(2)
=> 1
# Hash.index deprecated
irb(main):001:0> {1=>2}.index(2)
(irb):18: warning: Hash#index is deprecated; use Hash#key
=> 1
irb(main):002:0> {1=>2}.key(2)
=> 1
irb(main):001:0> {1=>2}.index(2)
=> 1
*Action*: use Hash.key
# Fixnum.to_sym now gone
irb(main):001:0> 5.to_sym
NoMethodError: undefined method `to_sym' for 5:Fixnum
# Fixnum.to_sym now gone
irb(main):001:0> 5.to_sym
NoMethodError: undefined method `to_sym' for 5:Fixnum
irb(main):001:0> 5.to_sym
=> nil
# Fixnum.to_sym now gone (cont'd)
{{{ Ruby 1.9
# Find an argument value by name or index.
def [](index)
lookup(index.to_sym)
end
}}}
# Fixnum.to_sym now gone (cont'd)
{{{ Ruby 1.9
# Find an argument value by name or index.
def [](index)
lookup(index.to_sym)
end
}}}
http://svn.ruby-lang.org/repos/ruby/trunk/lib/rake.rb
# hash keys now unordered
irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"}
=> {:a=>"a", :c=>"c", :b=>"b"}
# hash keys now unordered
irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"}
=> {:a=>"a", :c=>"c", :b=>"b"}
irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"}
=> {:a=>"a", :b=>"b", :c=>"c"}
# hash keys now unordered
irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"}
=> {:a=>"a", :c=>"c", :b=>"b"}
irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"}
=> {:a=>"a", :b=>"b", :c=>"c"}
Order is insertion order
# stricter unicode regular expressions
irb(main):001:0> /\x80/u
SyntaxError: (irb):2: invalid multibyte escape: /\x80/
# stricter unicode regular expressions
irb(main):001:0> /\x80/u
SyntaxError: (irb):2: invalid multibyte escape: /\x80/
irb(main):001:0> /\x80/u
=> /\x80/u
# tr and Regexp now understand Unicode
{{{ Ruby 1.9
unicode(string).tr(CP1252_DIFFERENCES, UNICODE_EQUIVALENT).
gsub(INVALID_XML_CHAR, REPLACEMENT_CHAR).
gsub(XML_PREDEFINED) {|c| PREDEFINED[c.ord]}
}}}
# pack and unpack
# BasicObject more brutal than BlankSlate
irb(main):001:0> class C < BasicObject; def f; Math::PI; end; end; C.new.f
NameError: uninitialized constant C::Math
# BasicObject more brutal than BlankSlate
irb(main):001:0> class C < BasicObject; def f; Math::PI; end; end; C.new.f
NameError: uninitialized constant C::Math
irb(main):001:0> require 'blankslate'
=> true
irb(main):002:0> class C < BlankSlate; def f; Math::PI; end; end; C.new.f
=> 3.14159265358979
# BasicObject more brutal than BlankSlate
irb(main):001:0> class C < BasicObject; def f; Math::PI; end; end; C.new.f
NameError: uninitialized constant C::Math
irb(main):001:0> require 'blankslate'
=> true
irb(main):002:0> class C < BlankSlate; def f; Math::PI; end; end; C.new.f
=> 3.14159265358979
*Action*: use ::Math::PI
# degation changes
irb(main):002:0> class C < SimpleDelegator; end
=> nil
irb(main):003:0> C.new('').class
=> String
# degation changes
irb(main):002:0> class C < SimpleDelegator; end
=> nil
irb(main):003:0> C.new('').class
=> String
irb(main):002:0> class C < SimpleDelegator; end
=> nil
irb(main):003:0> C.new('').class
=> C
irb(main):004:0>
# degation changes
irb(main):002:0> class C < SimpleDelegator; end
=> nil
irb(main):003:0> C.new('').class
=> String
irb(main):002:0> class C < SimpleDelegator; end
=> nil
irb(main):003:0> C.new('').class
=> C
irb(main):004:0>
Defect 17700
# Use of $KCODE produces warnings
irb(main):004:1> $KCODE = 'UTF8'
(irb):4: warning: variable $KCODE is no longer effective; ignored
=> "UTF8"
# Use of $KCODE produces warnings
irb(main):004:1> $KCODE = 'UTF8'
(irb):4: warning: variable $KCODE is no longer effective; ignored
=> "UTF8"
irb(main):001:0> $KCODE = 'UTF8'
=> "UTF8"
# instance_methods now an array of symbols
irb(main):001:0> {}.methods.sort.last
=> :zip
# instance_methods now an array of symbols
irb(main):001:0> {}.methods.sort.last
=> :zip
irb(main):001:0> {}.methods.sort.last
=> "zip"
# instance_methods now an array of symbols
irb(main):001:0> {}.methods.sort.last
=> :zip
irb(main):001:0> {}.methods.sort.last
=> "zip"
*Action*: Replace instance_methods.include?
with method_defined?
# Source file encoding
# Real threading
* Race conditions
* Implicit Ordering Assumptions
* Test code
# Implications
# Implications
* Changes are straightforward
# Implications
* Changes are straightforward
* Cumulative effect is massive
# Implications
* Changes are straightforward
* Cumulative effect is massive
* The biggest obstacle to Ruby 1.9's adoption is the sheer number of mostly working but essentially unmaintained gems that virtually everybody in the Ruby community depends on
# Implications
* Changes are straightforward
* Cumulative effect is massive
* The biggest obstacle to Ruby 1.9's adoption is the sheer number of mostly working but essentially unmaintained gems that virtually everybody in the Ruby community depends on
* Emergence of alternate implementations also a source for inertia
# Recommendations
# Recommendations
Encourage Maintainers of gems to:
* Produce versions of gems that work with 1.8.x and 1.9
# Recommendations
Encourage Maintainers of gems to:
* Produce versions of gems that work with 1.8.x and 1.9
* For long term, move to DVCS like git
# Rails dependencies
*(compact) actionmailer-2.1.0
* actionpack-2.1.0
* activerecord-2.1.0
* activeresource-2.1.0
* activesupport-2.1.0
* builder-2.1.2
* memcache-client-1.5.0
* rails-2.1.0
* rake-0.8.1
* sources-0.0.1
* text-format-0.6.3
* tmail-1.2.3
* tzinfo-0.3.8
* xml-simple-1.0.11
* html-scanner
* db2.rb
* mysql.rb
# Part 2