新米パパの育児留学

新米パパの育児留学

未経験からエンジニアへの転職体験談など "リアル" な情報を発信

【30代未経験もok】IT/WEBエンジニアにおすすめの転職エージェント/スクール比較(侍の炎上を見て)
全くの未経験からIT/Webエンジニアに転職した私(30代)のロードマップ
30代未経験からIT / Webエンジニアへのリアルな転職体験談4 ”2度目の転職活動から入社へ”
本当に使えるものだけ!出産準備品・ベビー用品で実際に買ってよかったおすすめ10選
クロスバイク  LIG(リグ) MOVE 700Cの組み立て手順まとめ
Ruby初心者におすすめの学習方法「プロを目指す人のためのRuby入門」
Ruby on Rails チュートリアル 完全攻略 概要と演習解答総まとめ

Ruby2.3の主な変更点まとめ

先日Rails5.0(Ruby2.3,Ruby2.4)の新機能勉強会を開催したのでその際の資料をアップします。

本記事は、Ruby2.3 の主な新機能についてです。

GEEKLYのIT・WEB・ソーシャルゲーム業界への転職支援サービス

発表スライド

Ruby 2.3の主な新機能

1. 【重要!】nil でもメソッド呼び出しがエラーにならない safe navigation operator(ぼっちオペレーター)

  • Railsの Object#try! のように、オブジェクトが nil でもエラーを恐れずメソッドが呼び出せる
  • obj&.fooのように書き、objnil であれば、foo の戻り値が nil になる
  • try! と同様にメソッドが実装されていないとエラーが起きる
  • &. は rubyのオペレータなので、メソッドコールである try! よりも速い
  • ぼっちオペレーターが主流
> nil.try(:book)
#=> nil

> nil.try!(:book)
#=> nil

> nil&.book
#=> nil

> "foo".try(:book)
#=> nil

> "foo".try!(:book)
NoMethodError: undefined method 'book' for "foo":String

> "foo"&.book
NoMethodError: undefined method 'book' for "foo":String

2. 合致しない要素を返す Enumerable#grep_v

  • grepコマンドの-vオプションと同等の役割
> list = %w(foo bar baz)
#=> ["foo", "bar", "baz"]

> list.grep_v(/ba/)
#=> ["foo"]

> list.grep(/ba/)
#=> ["bar", "baz"]

3. 複数の値をまとめてfetchする Hash#fetch_values

  • 該当のキーが検出された場合のみ、キーに対する値の配列を返す
  • 値が無かった場合、#values_atnilを返すのに対して、 #fetch_valuesは例外KeyErrorを返す。
> h = { foo: 1, bar: 2, baz: 3}
#=> {:foo=>1, :bar=>2, :baz=>3}

> h.fetch_values(:foo, :bar)
#=> [1, 2]

> h.values_at(:foo, :none)
#=> [1, nil]

> h.fetch_values(:foo, :none)
KeyError: key not found: :none

4. 数値の正負を判別する Numeric#positive?, negative?

  • positive?: 数値が正の値の場合 true、それ以外なら false
  • negative?: 数値が負の値の場合 true、それ以外なら false
> 1.positive?
#=> true
> -1.positive?
#=> false
> 1.negative?
#=> false
> -1.negative?
#=> true

5. 非推奨となった定数を参照時に警告を出す Module#deprecate_constant

  • deprecate_constantとして非推奨となった定数を指定すると、当該定数を参照時に警告を出力
require 'timeout'
TimeoutError # warning: constant ::TimeoutError is deprecated

FOO = 1
class Object
  deprecate_constant :FOO
end

FOO # warning: constant ::FOO is deprecated

6. エラー発生時に呼び出されたオブジェクトを取得する NameError#receiver

  • NameError や NoMethodError 発生時に、呼び出されたオブジェクト(レシーバ)を取得する
begin
  "foo".to_ss
rescue => e
  puts e.receiver
end
#=>foo

7. ヒアドキュメント内のインデントを取り除いてくれる <<~ (squiggly heredoc)

  • Rubyのヒアドキュメント<<-を使うと、ヒアドキュメント内のインデントはそのままスペースやタブとして残っていた
  • <<~を使うとstrip_heredoc と同様に、ヒアドキュメント内のインデントを取り除いてくれる

[railsでの実装:strip_heredocメソッドとしてあった]

# <<- を使うと、ヒアドキュメント内のインデントがそのままスペースとして残ってしまう
text_with_legacy_heredoc = <<-TEXT
  This would contain specially formatted text.
  That might span many lines
TEXT
#=> "  This would contain specially formatted text.\n  That might span many lines\n"

# Railsのstrip_heredocを使うと、インデントのスペースを取り除くことができる
text_with_strip_heredoc = <<-TEXT.strip_heredoc
  This would contain specially formatted text.
  That might span many lines
TEXT
#=> "This would contain specially formatted text.\nThat might span many lines\n"

# <<~ を使うとstrip_heredocと同じようにインデントのスペースを取り除いてくれる
text_with_squiggly_heredoc = <<~TEXT
  This would contain specially formatted text.
  That might span many lines
TEXT
#=> "This would contain specially formatted text.\nThat might span many lines\n"

勉強会では紹介しなかった新機能

8. ハッシュをProc化できる Hash#to_proc

  • ハッシュをProc化することで引数にハッシュを渡したりすることができる
str_ids = Bookmark.where(cond_a).order(hoge_cond).limit(n).pluck(:store_id)  # 1. あるソートで str_id の配列を取る
strs_by_id = Store.where(cond_b).index_by(&:id)  # 2. ある条件で id を key にした str オブジェクトをたくさんもってくる

str_ids.map(&strs_by_id)  # 2. で作ったハッシュから 1. で指定したソート順でオブジェクトの配列を取得

9. did_you_mean gemの標準添付

  • NameError や NoMethodError が発生した際に正しい名前の候補を表示してデバッグしやすくする

[railsでの実装:なし]

> "foo".uppcase
NoMethodError: undefined method 'uppcase' for "foo":String
Did you mean?  upcase
               upcase!

10. バイナリサーチを使って配列のindexを検索する Array#bsearch_index

  • バイナリサーチ(二分探索)のアルゴリズムを使って、オブジェクトを検索するメソッド bsearchが以前からあった
  • bsearch_indexは見つかった要素そのものではなく、その要素のindexを返す
  • bsearch_indexは大きな配列であれば index よりも速く検索できる場合がある

  • バイナリサーチ(bsearch_index) = O(log2 n)

  • 線形探索(index) = O(n)

[railsでの実装:なし]

> [ "a", "b", "c", "d", "e" ].bsearch { |x| x > "a" }
#=> "b"

> [ "a", "b", "c", "d", "e" ].bsearch_index { |x| x > "a" }
#=> 1

> [ "a", "b", "c", "d", "e" ].index { |x| x > "a" }
#=> 1

11. 隣り合う要素が条件を満たせば同じグループとする Enumerable#chunk_while

  • 隣り合う要素が条件を満たせば同じグループとする
  • slice_when でも同じことが実現できますが、「隣り合う要素が条件を満たさなくなったら新しいグループに切り替える」という chunk_while とは逆の条件

[railsでの実装:なし]

> data = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
#=> [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]

> data.chunk_while { |i, j| i.even? == j.even? }.to_a
#=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]

> data.slice_when { |i, j| i.even? != j.even? }.to_a
#=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]

> data.slice_when { |i, j| i.even? == j.even? }.to_a
#=> [[7], [5], [9, 2], [0, 7], [9, 4], [2], [0]]

参考情報

公式情報

参考ブログ

所感

safe navigation operator(ぼっちオペレーター)は便利だし使う場面多そう。"did_you_mean gemの標準添付"は初心者がタイポでハマるのを助けてくれるから嬉しい。

GEEKLYのIT・WEB・ソーシャルゲーム業界への転職支援サービス

あわせて読みたい記事

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com