Microsoft's Internet Explorer browser has no built-in vector graphics machinery required for "loss-free" gradient background themes.

Please upgrade to a better browser such as Firefox, Opera, Safari or others with built-in vector graphics machinery and much more. (Learn more or post questions or comments at the Slide Show (S9) project site. Thanks!)

Migrating to Ruby 1.9

Bruce Williams @ Scotland on Rails, Edinburgh, April 2008

Adapted S6/S91 Version from Original Slide Deck


1 (Source)

Slide Show Keyboard Controls (Help)

Action Key
Go to next slide Space Bar, Right Arrow, Down Arrow, Page Down
Go to previous slide Left Arrow, Up Arrow, Page Up
Toggle between slideshow and outline view (Ø) T
Show/hide slide controls (Ø « ») C, Move mouse to bottom right corner

About Bruce Williams

Perpetrator of much random Ruby hackery, language tourist

Rubyist since 2001 (Full-time since 2005)

Open source developer, contributer, technical editor, designer

Occasionally blogs at codefluency.com

Ruby 1.8 / Ruby 1.9

1.8

1.9

Installing Ruby 1.9

Ruby’s Releases – From Toybox to Toolshed

Born in Japan (1995) → Beyond Japan (2001) → .. on Rails (2004) → Expansion (2008)

(development 1.5)
1.6.0 ’00
1.6.1 ’01
1.6.2 ’01
1.6.3 ’01
1.6.4 ’02
1.6.5 ’02
1.6.7 ’02
1.6.8 ’03 (development 1.7 ongoing)
1.8.0 ’04
1.8.1 ’04
1.8.2 ’05
1.8.3 ’05
1.8.4 ’06
1.8.5 ’06
1.8.6 ’07 (development 1.9 ongoing)

Standard Library

Parser/Syntax Changes

New Hash Literal

{a: "foo"}
# => {:a=>"foo"}

{a: "bar", :b => "baz"}
# => {:a=>"bar", :b=>"baz"}

New Proc Literal, Invocation

multiply_by_2 = ->(x) { x * 2 }
# => #<Proc:0x3c5a50>

multiply_by_2.(4)
# => 8

Parser/Syntax Changes Continued

Splat arguments before

names = %w(joe john bill)
[*names, 'jack']
# => ["joe", "john", "bill", "jack"]

Method Parameter ordering

def say(language=:english, text)
  puts Translator[language].translate(text)
end
say "hello"
# hello
say :spanish, "hello"
# hola

Migrating Risk Factors

Tests are Good

I was surprised at how much work my 11th hour integration of the FasterCSV code was. It was a pure Ruby library that really didn’t do a lot of fancy tricks, but I had to track down about 20 little issues to get it running under Ruby 1.9. Thank goodness it had terrific test coverage to lead me to the problem areas.

— James Edward Gray II (December 2007)

Follow-up Posting: Getting Code Ready for Ruby 1.9

Block Local Variables – Arguments Are Always Local

item = 1
2.upto(4) do |item|
  p item
end

Outputs In 1.8

# 2
# 3
# 4
item
# => 4

Outputs In 1.9

# 2
# 3
# 4
item
# => 1

Shadowing Variables – You’ll Get a Warning

i = 1
lambda { |i| p i }.call(3)

Outputs In 1.8

# 3
i
# => 3

Outputs In 1.9

# 3
i
# => 1

warning line 2: shadowing outer local variable – i

Shadowing Variables – Locals, But Warned

No Local, Reassigns

d = 2
-> { d = 1 }.()
d
# => 1

Local, shadowed

d = 2
->(;d) { d = 1 }.()
d
# => 2

warning line 2: shadowing outer local variable – d

Hash#select – Changes to Yielded Arguments

Ruby 1.8

conferences.select do |data|
  p data
end
# [:euruko, "Prague"]
# [:scotland_on_rails, "Edinburgh"]
# [:railsconf_europe, "Berlin"]

warning: multiple values for a block parameter (2 for 1)

Ruby 1.9

conferences.select do |data|
  p data
end
# :euruko
# :scotland_on_rails
# :railsconf_europe
conferences.select do |name, city|
  p [name, city]
end
# [:euruko, "Prague"]
# [:scotland_on_rails, "Edinburgh"]
# [:railsconf_europe, "Berlin"]

Hash#select – Returns a Hash

conferences.select do |name, _|
  name == :scotland_on_rails
end

Ruby 1.8

# => [[:scotland_on_rails, "Edinburgh"]]

Ruby 1.9

# => {:scotland_on_rails=>"Edinburgh"}

Multilingualization (m17n)

Multilingualization (m17n) Continued

Encodings

:ASCII_8BIT, :Big5, :BIG5, :CP949, :EUC_JP, :EUC_KR, :EUC_TW, :GB18030, :GBK, :ISO_8859_1, :ISO_8859_2, :ISO_8859_3, :ISO_8859_4, :ISO_8859_5, :ISO_8859_6, :ISO_8859_7, :ISO_8859_8, :ISO_8859_9, :ISO_8859_10, :ISO_8859_11, :ISO_8859_13, :ISO_8859_14, :ISO_8859_15, :ISO_8859_16, :KOI8_R, :KOI8_U, :Shift_JIS, :SHIFT_JIS, :US_ASCII, :UTF_8, :UTF_16BE, :UTF_16LE, :UTF_32BE, :UTF_32LE, :Windows_1251, :WINDOWS_1251, :BINARY, :IBM437, :CP437, :IBM737, :CP737, :IBM775, :CP775, :CP850, :IBM850, :IBM852, :CP852, :IBM855, :CP855, :IBM857, :CP857, :IBM860, :CP860, :IBM861, :CP861, :IBM862, :CP862, :IBM863, :CP863, :IBM864, :CP864, :IBM865, :CP865, :IBM866, :CP866, :IBM869, :CP869, :Windows_1258, :WINDOWS_1258, :CP1258, :GB1988, :MacCentEuro, :MACCENTEURO, :MacCroatian, :MACCROATIAN, :MacCyrillic, :MACCYRILLIC, :MacGreek, :MACGREEK, :MacIceland, :MACICELAND, :MacRoman, :MACROMAN, :MacRomania, :MACROMANIA, :MacThai, :MACTHAI, :MacTurkish, :MACTURKISH, :MacUkraine, :MACUKRAINE, :CP950, :EucJP, :EUCJP, :EucJP_ms, :EUCJP_MS, :EUC_JP_MS, :CP51932, :EucKR, :EUCKR, :EucTW, :EUCTW, :EUC_CN, :EucCN, :EUCCN, :GB12345, :CP936, :ISO_2022_JP, :ISO2022_JP, :ISO_2022_JP_2, :ISO2022_JP2, :ISO8859_1, :Windows_1252, :WINDOWS_1252, :CP1252, :ISO8859_2, :Windows_1250, :WINDOWS_1250, :CP1250, :ISO8859_3, :ISO8859_4, :ISO8859_5, :ISO8859_6, :Windows_1256, :WINDOWS_1256, :CP1256, :ISO8859_7, :Windows_1253, :WINDOWS_1253, :CP1253, :ISO8859_8, :Windows_1255, :WINDOWS_1255, :CP1255, :ISO8859_9, :Windows_1254, :WINDOWS_1254, :CP1254, :ISO8859_10, :ISO8859_11, :TIS_620, :Windows_874, :WINDOWS_874, :CP874, :ISO8859_13, :Windows_1257, :WINDOWS_1257, :CP1257, :ISO8859_14, :ISO8859_15, :ISO8859_16, :CP878, :SJIS, :Windows_31J, :WINDOWS_31J, :CP932, :CsWindows31J, :CSWINDOWS31J, :MacJapanese, :MACJAPANESE, :MacJapan, :MACJAPAN, :ASCII, :ANSI_X3_4_1968, :UTF_7, :CP65000, :CP65001, :UCS_2BE, :UCS_4BE, :UCS_4LE, :CP1251

Multilingualization (m17n) Continued

Read a file with File.read

File.read("input.txt").encoding
# => #<Encoding:UTF-8>

File.read("input.txt", encoding: 'ascii-8bit').encoding
# => #<Encoding:ASCII-8BIT>

Read a file with File.open

result = File.open("input.txt", "r:euc-jp") do |f|
  f.read
end
result.encoding
# => #<Encoding:EUC-JP>
result.valid_encoding?
# => true

Regular Expressions – Oniguruma Engine

Named Groups

"His name is Joe".match(/name is (?<name>\S+)/)[:name]
# => "Joe"

Enumerable

Enumerator built-in, returned from Enumerable methods (and those in Array, Dir, Hash, IO, Range, String or Struct that serve the same purposes). Added Enumerator#with_index

Map with Index

%w(Joe John Jack).map.with_index do |name, offset|
  "#{name} is #{offset + 1}"
end
# => ["Joe is #1", "John is #2", "Jack is #3"]

Enumerable – Reduce (inject)

[1,2,3,4].reduce(:+)
# => 10

Enumerable Continued

New Enumerable methods take, group_by, drop, min_by, max_by, count, and others. Enumerable#inject/reduce can take a single argument.

take

array = [1, 2, 3, 4, 5]
array.take(3)
# => [1, 2, 3]
array
# => [1, 2, 3, 4, 5]

drop

array = [1, 2, 3, 4, 5]
array.drop(3)
# => [4, 5]
array
# => [1, 2, 3, 4, 5]

Hash Changes – Insertion Order Preserved

conferences = {
  euruko: 'Prague',
  scotland_on_rails: 'Edinburgh'
}
conferences[:railsconf_europe] = 'Berlin'
conferences.each do |name, city|
  p "#{name} is in #{city}"
end

# "euruko is in Prague"
# "scotland_on_rails is in Edinburgh"
# "railsconf_europe is in Berlin"

conferences.delete(:scotland_on_rails)
conferences[:scotland_on_rails] = 'Edinburgh'
conferences.each do |name, city|
  p "#{name} is in #{city}"
end

# "euruko is in Prague"
# "railsconf_europe is in Berlin"
# "scotland_on_rails is in Edinburgh"

Object – Added tap

thing = Thing.new.tap do |thing|
  thing.something = 1
  thing.something_else = 2
end

Lambda Changes – Obfuscation, Ahoy!

Passing Blocks

m = ->(x, &b) { b.(x * 2) if b }
m.(3) do |result|
  puts result
end
# Output
# 6

Default Arguments

->(a, b=2) { a * b }.(3)
# => 6

Symbol Changes – Less Sibling Rivalry

Indexing into a Symbol

:foo[1]
# => "o"

Comparing with a String

:this === "this"
# => true

Fibers – “Semi-Coroutines”

For some examples, see:

Thanks!

This was really just an introduction.

Bruce Williams // bruce AT codefluency.com // twitter: wbruce