- formal argument cannot be an instance variable:
In ruby1.8 it’s possible to use an instance variable as a block argument:class Foo attr_accessor :bar def test [1,2,3].each {|@bar| } # @bar will be 3 here end end
This no longer works in ruby1.9, you as it always creates a new local variable block argument. The equivalent in ruby1.9:
class Foo attr_accessor :bar def test [1,2,3].each {|bar| @bar=bar } # @bar will be 3 here end end
- warning: shadowing outer local variable:
In ruby1.9 the block arguments are always local to block, in ruby1.8 if there’s an existing variable with the same name, the block parameter will use that one:i = 0 [1,2,3].each {|i| } puts i
This will print
0
in ruby1.9, as the variables namedi
inside/outside the block are different, and3
in ruby1.8, as here the block reuses the outside variablei
.As with most warning, this warning doesn’t means that your code is incorrect, only that it might be incorrect.
For example the code bellow works the same in ruby1.9 and 1.8:options = options.inject({}) do |options,pair| options[pair.first.to_sym] = pair.last.to_sym; options end
It still makes sense to rewrite the above code just to supress warnings.
Note: You should set
RUBYOPT
to-w
, or start your program withruby -w
, for this warning to show up - syntax error, unexpected ‘,’, expecting tASSOC
ruby1.8 supports,
in hash definition, in 1.9 you have to use=>
.So the following valid ruby1.8:
{"a","b"}
has to be rewritten in ruby1.9:
{"a" => "b"}
- invalid multibyte char:
the default encoding in ruby 1.9 for files isUS-ASCII
, if you have a non ASCII character in your text file you have to specify the encoding of the source code. You can do it by adding the following line to your ruby file:# coding:utf-8
- NoMethodError: undefined method `to_a’ for “…”:String:
In Ruby1.8 the String class has ato_a
method, so in ruby1.8 you can write:lines = string.to_a
The equivalent in ruby1.9 is:
lines = string.lines.to_a # chars = string.chars.to_a # to get array of chars # bytes = string.bytes.to_a # to get array of bytes
The issue with this solution, is that the ruby1.9 solution is not compatible with ruby1.8.
Some ideas for a ruby1.9 and ruby1.8 compatible solution:
The first one is to add a
lines
method to theString
, so you can use the ruby1.9 syntax:unless String.method_defined?(:lines) then class String def lines to_a end end endif
The downside is that this
lines
method is not 100% compatible with ruby1.9 String#lines – for example string.lines(“\n\r”) won’t work.The second one is to check at each call whether it has the
lines
method:if str.respond_to?(:lines) then lines = string.lines.to_a else lines = string.to_a end
- unexpected ‘:’, expecting keyword_then or ‘,’ or ‘;’ or ‘\n’:
case
orif
with:
instead ofthen
Ruby1.8 allows the use of : shortcut instead of then in
if
andcase
expressions. In Ruby1.9 this is no more allowed.case 'test' when 'test': print 'OK' end
In ruby1.9 you’ll get a syntax error, so you have to replace the ‘:’ with ‘then’
case 'test' when 'test' then print 'OK' end
- no such file to load — base64:
require "base64"
: ruby 1.9 ships without base64. You should use Array#pack, unpackrequire 'base64' enc = Base64.encode64('Send reinforcements') plain = Base64.decode64(enc)
In ruby1.9 you can write:
enc = ['Send reinforcements'].pack( 'm' ) plain = enc.unpack( 'm' )[0]
- ‘struct RString’ has no member named ‘ptr’
‘struct RString’ has no member named ‘len’:
In ruby1.9 for the RString in C extensions was changed because of optimization, you should use theRSTRING_LEN
,RSTRING_PTR
macros instead of directly accessing thelen
,ptr
members.len = RSTRING(foo)->len ptr = RSTRING(foo)->ptr
Should be changed to
len = RSTRING_LEN(foo); ptr = RSTRING_PTR(foo);
- .methods changed from Strings to Symbols
The contents of the methods array was changed from String to Symbol, so if you were doing something like this in ruby1.8:Object.methods.include?("to_s")
The ruby1.9 version is:
Object.methods.include?(:to_s)
And the following works in ruby1.8 and 1.9:
object.respond_to?(:some_method)
-
TypeError: cannot assign nil; use Hash#delete instead
In ruby1.8 you can remove an environment variable by setting it tonil
.
In ruby1.9 use thedelete
method instead:ENV.delete('MY_ENV_VARIABLE')
Related link:
- Porting REXML to ruby 1.9
- Mongrel on ruby1.9
- Matz on ruby1.9 – RubyConf 2007
- Matz on ruby1.9 – EURUKO2008
- Matz on ruby1.9 Google tech talks
- Migrating to ruby 1.9 by Bruce Williams
- Getting Code Ready for Ruby 1.9
- Installing ruby 1.9 on MacOSX
- Purpose of Ruby 1.9? – what is/isn’t 1.9.0, 1.9.1, and 2.0.x
- Ruby 1.9 – Right for you?
Migrating to Ruby 1.9 (YARV): Posts you have to re…
So, you are reading everywhere that Ruby 1.9 is faster than 1.8 (even I say so! 😀 ) and you want to give it a try or even port your existing code to it. Where should you start from?…
[…] Заметили костыль в виде # coding:utf-8? Он и будет заниматься тем, что все символы будут корректно обрабатываться. Немножко не так просто, как хотелось бы, но уже что-то 🙂 Выполнение ruby18 test-unicode.rb выдаст нам следующую лабуду: 67 131 [“320”, “240”, “321”, “203”, “320”, “261”, “320”, “270”, ” “, “-“, ” “, “320”, “276”, “321”, “202”, “320”, “273”, “320”, “270”, “321”, “207”, “320”, “275”, “321”, “213”, “320”, “271”, ” “, “321”, “217”, “320”, “267”, “321”, “213”, “320”, “272”, ” “, “320”, “262”, “321”, “213”, “321”, “201”, “320”, “276”, “320”, “272”, “320”, “276”, “320”, “263”, “320”, “276”, ” “, “321”, “203”, “321”, “200”, “320”, “276”, “320”, “262”, “320”, “275”, “321”, “217”, “!”] Запуск же свежесобранного ruby19 test-unicode.rb покажет следующее: 37 и [“Р”, “у”, “б”, “и”, ” “, “-“, ” “, “о”, “т”, “л”, “и”, “ч”, “н”, “ы”, “й”, ” “, “я”, “з”, “ы”, “к”, ” “, “в”, “ы”, “с”, “о”, “к”, “о”, “г”, “о”, ” “, “у”, “р”, “о”, “в”, “н”, “я”, “!”] Что ж, куда лучше, не правда ли? 🙂 Очень советую тем, кто ищет что изучить, попробовать ruby, будете приятно удивлены элегантностью и гибкостью 😉 p.s.: заметки по портированию с 1.8 на 1.9 (англ.) […]
[…] YAY! 1.9 porting notes:https://boga.wordpress.com/2008/04/15/ruby-19-porting-notes/ […]
The multibyte char comment line should read:
# encoding:utf-8
not
# coding:utf-8