What is the difference between Ruby 1.8 and Ruby 1.9
Sam Ruby has a cool slideshow that outline the differences.
In the interest of bringing this information inline for easier reference, and in case the link goes dead in the abstract future, here's an overview of Sam's slides. The slideshow is less overwhelming to review, but having it all laid out in a list like this is also helpful.
Ruby 1.9 - Major Features
- Performance
- Threads/Fibers
- Encoding/Unicode
- gems is (mostly) built-in now
- if statements do not introduce scope in Ruby.
What's changed?
Single character strings.
Ruby 1.9
irb(main):001:0> ?c
=> "c"
Ruby 1.8.6
irb(main):001:0> ?c
=> 99
String index.
Ruby 1.9
irb(main):001:0> "cat"[1]
=> "a"
Ruby 1.8.6
irb(main):001:0> "cat"[1]
=> 97
{"a","b"} No Longer Supported
Ruby 1.9
irb(main):002:0> {1,2}
SyntaxError: (irb):2: syntax error, unexpected ',', expecting tASSOC
Ruby 1.8.6
irb(main):001:0> {1,2}
=> {1=>2}
Action: Convert to {1 => 2}
Array.to_s
Now Contains Punctuation
Ruby 1.9
irb(main):001:0> [1,2,3].to_s
=> "[1, 2, 3]"
Ruby 1.8.6
irb(main):001:0> [1,2,3].to_s
=> "123"
Action: Use .join instead
Colon No Longer Valid In When Statements
Ruby 1.9
irb(main):001:0> case 'a'; when /\w/: puts 'word'; end
SyntaxError: (irb):1: syntax error, unexpected ':',
expecting keyword_then or ',' or ';' or '\n'
Ruby 1.8.6
irb(main):001:0> case 'a'; when /\w/: puts 'word'; end
word
Action: Use semicolon, then, or newline
Block Variables Now Shadow Local Variables
Ruby 1.9
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
Ruby 1.8.6
irb(main):001:0> i=0; [1,2,3].each {|i|}; i
=> 3
Hash.index
Deprecated
Ruby 1.9
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
Ruby 1.8.6
irb(main):001:0> {1=>2}.index(2)
=> 1
Action: Use Hash.key
Fixnum.to_sym
Now Gone
Ruby 1.9
irb(main):001:0> 5.to_sym
NoMethodError: undefined method 'to_sym' for 5:Fixnum
Ruby 1.8.6
irb(main):001:0> 5.to_sym
=> nil
(Cont'd) Ruby 1.9
# Find an argument value by name or index.
def [](index)
lookup(index.to_sym)
end
svn.ruby-lang.org/repos/ruby/trunk/lib/rake.rb
Hash Keys Now Unordered
Ruby 1.9
irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"}
=> {:a=>"a", :c=>"c", :b=>"b"}
Ruby 1.8.6
irb(main):001:0> {:a=>"a", :c=>"c", :b=>"b"}
=> {:a=>"a", :b=>"b", :c=>"c"}
Order is insertion order
Stricter Unicode Regular Expressions
Ruby 1.9
irb(main):001:0> /\x80/u
SyntaxError: (irb):2: invalid multibyte escape: /\x80/
Ruby 1.8.6
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
Ruby 1.8.6
def xchr(escape=true)
n = XChar::CP1252[self] || self
case n when *XChar::VALID
XChar::PREDEFINED[n] or
(n>128 ? n.chr : (escape ? "#{n};" : [n].pack('U*')))
else
Builder::XChar::REPLACEMENT_CHAR
end
end
unpack('U*').map {|n| n.xchr(escape)}.join
BasicObject
More Brutal Than BlankSlate
Ruby 1.9
irb(main):001:0> class C < BasicObject; def f; Math::PI; end; end; C.new.f
NameError: uninitialized constant C::Math
Ruby 1.8.6
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
Delegation Changes
Ruby 1.9
irb(main):002:0> class C < SimpleDelegator; end
=> nil
irb(main):003:0> C.new('').class
=> String
Ruby 1.8.6
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
Ruby 1.9
irb(main):004:1> $KCODE = 'UTF8'
(irb):4: warning: variable $KCODE is no longer effective; ignored
=> "UTF8"
Ruby 1.8.6
irb(main):001:0> $KCODE = 'UTF8'
=> "UTF8"
instance_methods
Now an Array of Symbols
Ruby 1.9
irb(main):001:0> {}.methods.sort.last
=> :zip
Ruby 1.8.6
irb(main):001:0> {}.methods.sort.last
=> "zip"
Action: Replace instance_methods.include? with method_defined?
Source File Encoding
Basic
# coding: utf-8
Emacs
# -*- encoding: utf-8 -*-
Shebang
#!/usr/local/rubybook/bin/ruby
# encoding: utf-8
Real Threading
- Race Conditions
- Implicit Ordering Assumptions
- Test Code
What's New?
Alternate Syntax for Symbol as Hash Keys
Ruby 1.9
{a: b}
redirect_to action: show
Ruby 1.8.6
{:a => b}
redirect_to :action => show
Block Local Variables
Ruby 1.9
[1,2].each {|value; t| t=value*value}
Inject Methods
Ruby 1.9
[1,2].inject(:+)
Ruby 1.8.6
[1,2].inject {|a,b| a+b}
to_enum
Ruby 1.9
short_enum = [1, 2, 3].to_enum
long_enum = ('a'..'z').to_enum
loop do
puts "#{short_enum.next} #{long_enum.next}"
end
No block? Enum!
Ruby 1.9
e = [1,2,3].each
Lambda Shorthand
Ruby 1.9
p = -> a,b,c {a+b+c}
puts p.(1,2,3)
puts p[1,2,3]
Ruby 1.8.6
p = lambda {|a,b,c| a+b+c}
puts p.call(1,2,3)
Complex Numbers
Ruby 1.9
Complex(3,4) == 3 + 4.im
Decimal Is Still Not The Default
Ruby 1.9
irb(main):001:0> 1.2-1.1
=> 0.0999999999999999
Regex “Properties”
Ruby 1.9
/\p{Space}/
Ruby 1.8.6
/[:space:]/
Splat in Middle
Ruby 1.9
def foo(first, *middle, last)
(->a, *b, c {p a-c}).(*5.downto(1))
Fibers
Ruby 1.9
f = Fiber.new do
a,b = 0,1
Fiber.yield a
Fiber.yield b
loop do
a,b = b,a+b
Fiber.yield b
end
end
10.times {puts f.resume}
Break Values
Ruby 1.9
match =
while line = gets
next if line =~ /^#/
break line if line.find('ruby')
end
“Nested” Methods
Ruby 1.9
def toggle
def toggle
"subsequent times"
end
"first time"
end
HTH!
String#[] Differences between Ruby 1.8.7 and 1.9.3
To get the old behavior, use String#getbyte
, as in:
"\200\001\002\004\b\020".getbyte(0)
String length difference between ruby 1.8 and 1.9
This is a Unicode issue. The string you are using contains characters outside the ASCII range, and the UTF-8 encoding that is frequently used encodes those as 2 (or more) bytes.
Ruby 1.8 did not handle Unicode properly, and length
simply gives the number of bytes in the string, which results in fun stuff like:
"ą".length
=> 2
Ruby 1.9 has better Unicode handling. This includes length
returning the actual number of characters in the string, as long as Ruby knows the encoding:
"ä".length
=> 1
One possible workaround in Ruby 1.8 is using regular expressions, which can be made Unicode aware:
"ą".scan(/./mu).size
=> 1
Ruby 1.8.7 versus Ruby 1.9+ performance
These could help you
http://nerds.airbnb.com/upgrading-from-ree-187-to-ruby-193
http://blog.pothoven.net/2012/10/ruby-187-vs-193-performance.html
http://pulse.sportngin.com/news_article/show/156863?referrer_id=543230
note that ruby 2 has even better performance
What is the difference between ruby 1.8.7 and 1.9.3 that causes session_store syntax errors in Rails?
The line that does not work in 1.8 is
Xxx::Application.config.session_store :cookie_store, key: '_xxx_session'
It uses new hash notation. To make it working for 1.8 change it to
Xxx::Application.config.session_store :cookie_store, :key => '_xxx_session'
Difference in `Array#to_s` in Ruby 1.8 and Ruby 1.9
Here's what is actually in Ruby source code:
1.8.7:
rb_ary_to_s(ary)
VALUE ary;
{
if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
return rb_ary_join(ary, rb_output_fs);
}
In other words, in 1.8.7, to_s
calls join
.
1.9.3:
rb_ary_inspect(VALUE ary)
{
if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
return rb_exec_recursive(inspect_ary, ary, 0);
}
VALUE
rb_ary_to_s(VALUE ary)
{
return rb_ary_inspect(ary);
}
In other words, in 1.9.3, to_s
delegates to inspect
.
Note: in future, if you're wondering about a difference you're observing between two versions, you can try taking a look at source code. Easy to pull down from here: https://github.com/ruby/ruby
Not everything is going to be easy to find in there of course, but if you search around for a bit you can often find good leads. In this case, array.c
has what you're looking for.
Then you can switch back and forth between versions by issuing git checkout ruby_1_8_7
and git checkout ruby_1_9_3
.
Differences in date string parsing between Ruby 1.9.3 and Ruby 1.8.7
Would it be an option for you to use Time.strptime("01/28/2012", "%m/%d/%Y")
in place of Time.parse
? That way you have better control over how Ruby is going to parse the date.
If not there are gems: (e.g. ruby-american_date) to make the Ruby 1.9 Time.parse behave like Ruby 1.8.7, but only use it if it's absolutely necessary.
1.9.3-p0 :002 > Time.parse '01/28/2012'
ArgumentError: argument out of range
1.9.3-p0 :003 > require 'american_date'
1.9.3-p0 :004 > Time.parse '01/28/2012'
=> 2012-01-28 00:00:00 +0000
Why does this code work in ruby 1.8 and not ruby 1.9?
It's to avoid ambiguity. Consider the following:
def foo(a, b = 1) # foo takes an optional second argument
end
[foo 1, 2]
This could be interpreted as [(foo 1), 2]
or as [(foo 1, 2)]
.
There are two references in the Calling Methods docs (although not directly related to the array literal):
Note that the parenthesis are optional ... Except when there is difference between using and omitting parentheses
In many cases parenthesis are not necessary when sending a message ... However, parenthesis are necessary to avoid ambiguity.
Different behavior of methods.include? between ruby 1.8.7 and ruby 1.9 & 2
By checking the difference between ruby 1.8 and 1.9 (and later), I found the reason is:
'instance_methods' has been changed from array of strings to array of symbols
A proper way of checking 'whether the method is defined' is:
x.respond_to?(:hello) # or string, both work
Related Topics
Rails 3: Alias_Method_Chain Still Used
How to Get the Match Data For All Occurrences of a Ruby Regular Expression in a String
Understanding the "||" or Operator in If Conditionals in Ruby
Ruby 2.4 and Rails 4 Stack Level Too Deep (Systemstackerror)
When Is 'Eval' in Ruby Justified
What Are the Brackets [5.1] After Activerecord Migration and How Does It Work
Adding a Directory to $Load_Path (Ruby)
How to Run a Rake Task from Capistrano
Understanding Ruby'S Load Paths
Aws S3: the Bucket You Are Attempting to Access Must Be Addressed Using the Specified Endpoint
How to Uninstall Ruby on Ubuntu