https://docs.ruby-lang.org/en/trunk/NEWS.html を元に Ruby 2.5 の変更内容を調べてみました。
長くなったので3つにわけてます。
個人的には coverage の分岐カバレッジ取得に SimpleCov とかが対応してくれるのを期待してます。
- bigdecimal
- coverage
- drb
- erb
- ipaddr
- irb
- logger
- mathn
- matrix
- net/http
- openssl
- pathname
- psych
- Psych.load_documents, detect_implicit, add_ruby_type, add_private_type, read_type_class, object_maker, tagurize, to_yaml_propaties, psych_yaml_as, yaml_initialize, yaml_as 廃止
- Psych.load, Psych.load_file, Psych.parse の fallback 引数が :fallback キーワード引数に変更
- Psych.load, Psych.safe_load に :symbolize_names キーワード引数追加
- Psych::Handler#event_location 追加
- rbconfig
- ripper
- rubygems
- securerandom
- set
- stringio
- strscan
- socket
- uri
- webrick
- zlib
bigdecimal
BigDecimal::VERSION 追加
BigDecimal.new, .ver が deprecated
% ruby -w -rbigdecimal -e BigDecimal.ver -e:1: warning: BigDecimal.ver is deprecated; use BigDecimal::VERSION instead.
BigDecimal#clone, #dup が同じオブジェクトを返す
数値オブジェクトだから Integer 等と同じく Immutable ってことだと思います。
require 'bigdecimal' # Ruby 2.4 b = BigDecimal(1) b.object_id == b.dup.object_id #=> false # Ruby 2.5 b = BigDecimal(1) b.object_id == b.dup.object_id #=> true
coverage
Coverage が分岐カバレッジ、メソッドカバレッジをサポート
低レベルAPIなのでアプリ等が対応するのを待ちたいところ。
drb
DRb の ACL::ACLEntry.new が IPAddr::InvalidPrefixError を無視しない
2.4 ではエラーになりませんでした。
require 'drb/acl' ACL::ACLEntry.new("192.168.0.0/255.255.0.1") #=> invalid mask 255.255.0.1 (IPAddr::InvalidPrefixError)
erb
ERB#result_with_hash 追加
コンテキストの変数じゃなくて、ハッシュで値を渡すこともできるようになりました。
require "erb" name = "tmtms" ERB.new("Hello <%=name%>").result #=> "Hello tmtms"
require "erb" ERB.new("Hello <%=name%>").result_with_hash(name: "tmtms")
ERB: trim 指定時 CR LF を trim
LF単独だと削除されましたが、CR LFは削除されなかったのが削除されるようになりました。
# Ruby 2.4 require 'erb' ERB.new("<%=123%>\r\n", nil, 1).result #=> "123\r\n" # Ruby 2.5 require 'erb' ERB.new("<%=123%>\r\n", nil, 1).result #=> "123"
bin/erb: デフォルトのエンコーディングが ASCII-8BIT から UTF-8 になった
# Ruby 2.4 % erb <(echo '<%="a".encoding%>') ASCII-8BIT # Ruby 2.5 % erb <(echo '<%="a".encoding%>') UTF-8
ipaddr
IPAddr#prefix, #loopback?, #private?, #link_local? 追加
require 'ipaddr' IPAddr.new("192.168.1.2/255.255.0.0").prefix #=> 16 IPAddr.new("127.0.0.1").loopback? #=> true IPAddr.new("10.1.2.3").private? #=> true IPAddr.new("169.254.0.0/16").link_local? #=> true
IPAddr.new が不正なアドレスマスクで例外を発生
Ruby 2.4 ではエラーになりませんでした。
require 'ipaddr' IPAddr.new("192.168.0.0/255.255.0.1") #=> invalid mask 255.255.0.1 (IPAddr::InvalidPrefixError)
IPAddr#ipv4_compat, ipv4_compat? が deprecated
RFC4291 で IPv4-Compatible IPv6 address が deprecated になったためのようです。
% ruby -w -ripaddr -e 'p IPAddr.new("::127.0.0.1").ipv4_compat?' -e:1: warning: IPAddr#ipv4_compat? is obsolete true
irb
irb コマンドでなくても binding.irb が有効
a = 123 binding.irb b = 456
みたいなスクリプトを書いて irb コマンドで実行すると binding.irb
の行で止まって対話的に調査できました。
% irb hoge.rb hoge.rb(main):001:0> a = 123 => 123 hoge.rb(main):002:0> binding.irb irb(main):001:0>
ruby で実行した場合はエラーになってました。
% ruby hoge.rb hoge.rb:2:in `<main>': undefined method `irb' for #<Binding:0x005626a1596280> (NoMethodError)
これがエラーにならずに irb で止まるようになりました。
% ruby hoge.rb From: hoge.rb @ line 2 : 1: a = 123 => 2: binding.irb 3: b = 456 irb(main):001:0>
logger
Logger.new の引数に String を渡した場合はファイル名としてだけ扱う
Logger.new("| command")
とした場合に command が実行されていましたが、文字列は単なるファイル名として扱うようになりました。
mathn
mathn 削除
もうあまり使われてないからのようです。RubyGems にはあるので使いたい場合は gem install すれば使うことができます。
matrix
Matrix.combine, Matrix#combine 追加
複数の Matrix オブジェクトの演算をブロックを用いて行えます。
require 'matrix' a = Matrix[ [1, 2], [3, 4] ] b = Matrix[ [5, 6], [7, 8] ] a + b #=> Matrix[[1, 2], [3, 4]] a.combine(b){|x, y| x + y } #=> Matrix[[1, 2], [3, 4]] Matrix.combine(a, b){|x, y| x + y } #=> Matrix[[1, 2], [3, 4]]
Matrix#hadamard_product, #entrywise_product 追加
行列演算には詳しくないのでわかりません。
net/http
Net::HTTP ステータス追加
'102' => Net::HTTPProcessing, '208' => Net::HTTPAlreadyReported, '421' => Net::HTTPMisdirectedRequest, '451' => Net::HTTPUnavailableForLegalReasons, '506' => Net::HTTPVariantAlsoNegotiates, '508' => Net::HTTPLoopDetected, '510' => Net::HTTPNotExtended,
Net::HTTP::STATUS_CODES 追加
require 'net/http/status' Net::HTTP::STATUS_CODES #=> {100=>"Continue", 101=>"Switching Protocols", # 102=>"Processing", 200=>"OK", 201=>"Created", # 202=>"Accepted", 203=>"Non-Authoritative Information", # 204=>"No Content", 205=>"Reset Content", 206=>"Partial Content", # ...}
Net::HTTP.new に no_proxy 引数追加
no_proxy = "example.com,example.net:8080" HTTP.new(address, port, proxy_addr, proxy_port, proxy_user, proxy_pass, no_proxy)
Net::HTTP: http_proxy環境変数を使用
HTTPプロキシ情報としてhttp_proxy環境変数が使われるようになりました。
環境変数を使用したくない場合は Net::HTTP.new
の第3引数に明示的に nil を指定する必要があります。
Net::HTTP: http_proxy環境変数の認証情報を使用
http://user:password@proxy:port/
ただし Linux, FreeBSD, Darwin に限られます。 他のOSでは、ps コマンド等で他のユーザーに環境変数の値が参照される可能性があるためのようです。
openssl
OpenSSL ライブラリのバージョンが 2.0 から 2.1 に
詳しくは https://github.com/ruby/ruby/blob/v2_5_0/ext/openssl/History.md
pathname
Pathname#glob 追加
require 'pathname' Pathname.new("/etc").glob("p*d") #=> [#<Pathname:/etc/pam.d>, #<Pathname:/etc/passwd>, #<Pathname:/etc/profile.d>]
psych
Psych.load_documents, detect_implicit, add_ruby_type, add_private_type, read_type_class, object_maker, tagurize, to_yaml_propaties, psych_yaml_as, yaml_initialize, yaml_as 廃止
Ruby 2.4 で既に deprecated だったメソッドが削除されました。
Psych.load, Psych.load_file, Psych.parse の fallback 引数が :fallback キーワード引数に変更
もともと非公開引数だったようなので既存コードに対する影響はないと思います。
Psych.load, Psych.safe_load に :symbolize_names キーワード引数追加
true を指定すると返されるHashのキーがシンボルになります。
require 'psych' Psych.load("abc: 123") #=> {"abc"=>123} Psych.load("abc: 123", symbolize_names: true)' #=> {:abc=>123}
Psych::Handler#event_location 追加
rbconfig
RbConfig::SIZEOF, RbConfig::LIMITS 追加
require "rbconfig/sizeof" RbConfig::SIZEOF #=> {"int"=>4, "short"=>2, "long"=>8, "long long"=>8, # "__int128"=>16, "off_t"=>8, "void*"=>8, "float"=>4, # "double"=>8, "time_t"=>8, "clock_t"=>8, "size_t"=>8, # ... RbConfig::LIMITS #=> {"FIXNUM_MAX"=>4611686018427387903, # "FIXNUM_MIN"=>-4611686018427387904, "CHAR_MAX"=>127, # "CHAR_MIN"=>-128, "SCHAR_MAX"=>127, "SCHAR_MIN"=>-128, # "UCHAR_MAX"=>255, "WCHAR_MAX"=>2147483647, # ...
ripper
Ripper#state, Ripper::EXPR_BEG 追加
Ripperは詳しくないのでわかりません。
rubygems
バージョン 2.7.3
Ruby 2.4.0 では Rubygems 2.6.8, Ruby 2.4.1 では Rubygems 2.6.11, Ruby 2.4.2 では Rubygems 2.6.13 でした。 各バージョンの変更内容は http://blog.rubygems.org/
ubygems 削除
ruby はコマンドラインオプション -r
でライブラリを読み込めるんですが、r で始まる名前のライブラリの場合は先頭の r を省いた名前のライブラリを用意することで、オプションの -r
と合わせて自然に読めるようになります。
ubygems は rubygems の別名で、-rubygems
コマンドラインオプションで使用できるようにするためのものですが、rubygems は require しなくても標準で使用されるためもう不要なのでした。
securerandom
SecureRandom.alphanumeric 追加
ランダムな英数字文字列を生成します。
require 'securerandom' SecureRandom.alphanumeric #=> "9S64YBvQnqOyauQV" SecureRandom.alphanumeric(5)' #=> "K0J8N"
set
Set#to_s 追加
require 'set' s = Set.new([1, 2, 3]) # Ruby 2.4 s.to_s #=> "#<Set:0x00560b825243b8>" # Ruby 2.5 s.to_s #=> "#<Set: {1, 2, 3}>"
Set#=== 追加
今までは未定義だったので Object#===
が動いていたのですが、Set#include?
と同じ動きになりました。
require 'set' s = Set.new([1, 2, 3]) # Ruby 2.4 s === 2 #=> false s === s #=> true # Ruby 2.5 s === 2 #=> true s === s #=> false
もしかしたら互換的な問題おきるかもしれないですね。
stringio
StringIO#write が複数文字列を受けつける
API としては IO#write
の変更と同じです。
strscan
StringScanner#size, #captures, #values_at 追加
最後に適合したサブグループに関するメソッド
require 'strscan' ss = StringScanner.new(Time.now.to_s) ss.scan(/(?<date>\d+-\d+-\d+) (?<time>\d+:\d+:\d+)/) ss.size #=> 3 サブグループだけでなく適合した部分全体も含む ss.captures #=> ["2017-12-29", "20:47:03"] ss.values_at(1, 2) #=> ["2017-12-29", "20:47:03"] ss.values_at(:date, :time) #=> ["2017-12-29", "20:47:03"]
socket
BasicSocket#read_nonblock, #write_nonblock が O_NONBLOCK をセットしない
require 'io/nonblock' s = TCPSocket.new("127.0.0.1", 80) s.nonblock? #=> false s.read_nonblock(10) # Ruby 2.4 s.nonblock? #=> true # Ruby 2.5 s.nonblock? #=> false
Socket::Ifaddr#vhid 追加
vhid が何なのかわからなかったです。BSDで使われてる何か?
uri
URI.open 追加
Kernel.open
のエイリアスとして追加されました。Kerlen.open
は将来廃止される予定のようです。
URI中の連続した「/
」の扱い
pathの連続した「/
」は今まではひとつになっていましたが連続したまま残るようになりました。
https://url.spec.whatwg.org/ では、pathは0文字要素も含むことができるとなっているためのようです。
# Ruby 2.4 URI.parse("http://example.com/hoge//fuga/")+"x" #=> #<URI::HTTP http://example.com/hoge/fuga/x> # Ruby 2.5 URI.parse("http://example.com/hoge//fuga/")+"x" #=> #<URI::HTTP http://example.com/hoge//fuga/x>
webrick
WEBrick: Server Name Indication (SNI) サポート
名前ベースのバーチャルホストでHTTPS対応できる仕組みのようです。詳しくないのでよくわかってません。
WEBrick::HTTPResponse#body= に Proc を指定可
require 'webrick' server = WEBrick::HTTPServer.new Port: 8080 server.mount_proc '/' do |req, res| res.content_length = 8 res.body = proc{ |socket| socket.write "hogehoge" } end server.start
Proc に限らず call メソッドを持っているオブジェクトなら何でも指定できそうな感じです。
zlib
Zlib::GzipWriter#write が複数文字列を受けつける
API としては IO#write
の変更と同じです。