サンプルコードでわかる！Ruby 2.3の主な新機能

# はじめに

Ruby 2.3が2015年12月25日にリリースされました。

そこでこの記事ではRuby 2.3の主な新機能を紹介していきます。

## 対象となるバージョン

以下のとおり、この記事では ruby 2.3.0 を使っています。

```bash
$ ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]
```

# 参考文献

今回紹介するサンプルコードは下記のサイトにあったコードをベースにしています。

[New features in ruby 2.3 - BlockScore Blog](https://blog.blockscore.com/new-features-in-ruby-2-3/)

ただし、実行結果を確認するために Minitest を使ったり、コードをいくつか変更したりしています。

# サンプルコードはGitHubにあります

この記事で使ったサンプルコードはGitHubに置いてあります。
興味のある方は手元で動かしてみてください。

[JunichiIto/ruby-2.3-sandbox](https://github.com/JunichiIto/ruby-2.3-sandbox)

それではここからRuby 2.3の新機能を紹介していきます。


# 深い階層にあるハッシュの値を一気に取得する Hash#dig

Ruby 2.3で追加された `Hash#dig` を使うと深い階層にあるハッシュの値を一気に取得できます。
また、Keyが見つからない場合はエラーにならず nil が返ります。

```ruby
def test_hash_dig
  user = {
      user: {
          address: {
              street1: '123 Main street'
          }
      }
  }

  # digを使って深い階層の値を一気に取得する
  assert_equal '123 Main street', user.dig(:user, :address, :street1)

  # Keyが存在する場合は以下のコードと同等
  assert_equal '123 Main street', user[:user][:address][:street1]

  # 存在しないKeyを指定するとnilが返ってくる（エラーは起きない）
  assert_nil user.dig(:user, :adddresss, :street1)

  # 普通に[]を使うとエラーになる
  assert_raises { user[:user][:adddresss][:street1] }
end
```

## 参考：Minitestのコードの読み方

「Minitestで書かれてもわからん！！」という方のために、テストコードの読み方を簡単に紹介しておきます。

```ruby
# aはbに等しい
assert_equal b, a

# aはnil
assert_nil a

# aは真（true、またはnilでもfalseでもない値）
assert a

# aは偽（nilまたはfalse）
refute a

# aとbは同じインスタンス
assert_same b, a

# a.foo() を実行するとエラーが発生する
assert_raises { a.foo() }

# a.foo() を実行するとFooErrorが発生する
assert_raises(FooError) { a.foo() }
```

# 深い階層にある配列の値を一気に取得する Array#dig

ハッシュだけでなく、配列にも `dig` が追加されています。
考え方はハッシュと同じです。

```ruby
def test_array_dig
  results = [[[1, 2, 3]]]
  
  # digを使って深い階層の値を一気に取得する
  assert_equal 1, results.dig(0, 0, 0)

  # Indexが存在する場合は以下のコードと同様
  assert_equal 1, results[0][0][0]

  # 存在しないIndexを指定するとnilが返ってくる（エラーは起きない）
  assert_nil results.dig(1, 1, 1)

  # 普通に[]を使うとエラーになる
  assert_raises { results[1][1][1] }
end
```

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

Enumerableモジュールには以前から各要素に対して「引数obj === 要素」を試し、その結果が真だった要素を集めて配列にして返す `grep` メソッドがありました。

[grep (Enumerable) - Rubyリファレンス](http://ref.xaio.jp/ruby/classes/enumerable/grep)

Ruby 2.3ではこの逆で「偽だった要素を配列にして返す」`grep_v` メソッドが追加されました。

```ruby
# 正規表現 + grep_v を使う場合
def test_grep_v_by_regex
  friends = %w[John Alain Jim Delmer]

  # Jで始まる文字列を探す
  j_friends = friends.grep(/^J/)
  assert_equal %w(John Jim), j_friends

  # Jで始まる文字列以外を探す
  others    = friends.grep_v(/^J/)
  assert_equal %w(Alain Delmer), others
end

# 型情報 + grep_v を使う場合
def test_grep_v_by_type
  items = [1, 1.0, '1', nil]

  # Numeric型のオブジェクトを探す
  nums   = items.grep(Numeric)
  assert_equal [1, 1.0], nums

  # Numeric型以外のオブジェクトを探す
  others = items.grep_v(Numeric)
  assert_equal ['1', nil], others
end
```

## 参考：grep_vの "v" って何？

おそらく invert（逆にする）の"v"だと思われます。

下記ページにて grep_v の実装が議論されています。
「grepコマンドの-vオプションみたいな機能がほしい」ということから、"grep_v"というメソッド名が提案され、そのまま採択されたようです。

> Shota Fukumori
>
> - sometime I want to do grep -v like operation
> - I'm not sure grep_v is the best name for this feature; feedback are welcomed. 
>
> Yukihiro Matsumoto
>
> - grep_v seems OK. Accepted. 
>
> [Feature #11049: Enumerable#grep_v (inversed grep) - Ruby trunk - Ruby Issue Tracking System](https://bugs.ruby-lang.org/issues/11049)

じゃあ、"grep -v" の "v" は何？ってなるんですが、これは "invert" の "v" っぽいです。

> -v, --invert-match
>
> - Invert the sense of matching, to select non-matching lines.
>
> [Linux and Unix grep command help and examples](http://www.computerhope.com/unix/ugrep.htm)

-i だと 大文字小文字を無視する "ignore case の -i" とかぶってしまうので、-v になったんでしょうね。

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

Hashクラスには以前から `fetch` メソッドがありました。
`fetch` メソッドは `[]` メソッドと機能は同じですが、キーが存在しないときの動作が異なります。

[fetch (Hash) - Rubyリファレンス](http://ref.xaio.jp/ruby/classes/hash/fetch)

Ruby2.3では複数のKeyを指定して fetch できる `fetch_values` が追加されました。

```ruby
def test_fetch_values
  values = {
      foo: 1,
      bar: 2,
      baz: 3,
      qux: 4
  }

  # Keyが存在する場合は values_at も fetch_values も同じ結果を返す
  assert_equal [1, 2], values.values_at(:foo, :bar)
  assert_equal [1, 2], values.fetch_values(:foo, :bar)

  # Keyが存在しない場合、 values_at は nil を返す
  assert_equal [1, 2, nil], values.values_at(:foo, :bar, :invalid)

  # Keyが存在しない場合、 fetch_values はエラーが発生する
  e = assert_raises(KeyError) { values.fetch_values(:foo, :bar, :invalid) }
  assert_equal 'key not found: :invalid', e.message

  # Hash#fetch と同様、fetch_values はブロックを使ってデフォルト値を返すことができる
  assert_equal [1, 2, :invalid], values.fetch_values(:foo, :bar, :invalid) {|k| k }
end
```

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

Ruby 2.3では数値が0より大きいか、0未満かを判断して true/false を返す `Numeric#positive?` と `Numeric#negative?` が追加されました。

```ruby
def test_positive_and_negative
  numbers = (-5..5)

  # positive? メソッドと negative? メソッドを使って、正または負の値を抜き出す
  assert_equal [1, 2, 3, 4, 5], numbers.select(&:positive?)
  assert_equal [-5, -4, -3, -2, -1], numbers.select(&:negative?)

  # negative? は0未満の場合 true を返す、なので負のゼロの場合は false を返す
  assert_equal -0.0.negative?, false
end
```

# ハッシュを比較して包含関係を判別する Hash#<=, <, >=, >

Ruby 2.3では、ふたつのハッシュを比較して包含関係を判別する演算子 `Hash#<=` `Hash#<` `Hash#>=` `Hash#>` が追加されました。

演算子 `>` / `>=` / `<` / `<=` はそれぞれ集合の関係を表す記号 ⊃ / ⊇ / ⊂ / ⊆ に対応しています。

```ruby
def test_hash_operators
  # A ⊃ B の関係である
  assert({ a: 1, b: 2 } > { a: 1 })

  # A ⊃ B の関係ではない（値が異なる）
  refute({ a: 1, b: 2 } > { a: 10 })

  # A ⊃ B の関係ではない（等しい関係である）
  refute({ a: 1 } > { a: 1 })

  # A ⊇ B の関係である
  assert({ a: 1 } >= { a: 1 })

  # A ⊃ B の関係ではない（Keyも値も別物）
  refute({ b: 1 } > { a: 1 })

  # A ⊂ B の関係ではない（Keyも値も別物）
  refute({ b: 1 } < { a: 1 })

  # A ⊂ B の関係である
  assert({ a: 1, b: 2 } < { a: 1, b: 2, c: 3 })
end
```

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

Ruby 2.3ではハッシュをProc化する `Hash#to_proc` が追加されました。
これにより、mapの引数にハッシュを渡したりすることができます。

```ruby
def test_hash_to_proc
  hash = { a: 1, b: 2, c: 3 }
  keys = %i[a c d]

  # ハッシュをProcに変換できるので、mapの引数に &hash を渡せる
  assert_equal [1, 3, nil], keys.map(&hash)

  # 次のようにProc化したハッシュを個別に呼び出すこともできる
  hash_proc = hash.to_proc
  assert_equal 1, hash_proc.call(:a)
  assert_equal 2, hash_proc.call(:b)
  assert_equal nil, hash_proc.call(:d)

  # つまり &hash は下のようなコードと同等
  assert_equal [1, 3, nil], keys.map { |k| hash_proc.call(k) }

  # ハッシュをProc化しない場合は次のようなコードになる
  assert_equal [1, 3, nil], keys.map { |k| hash[k] }
end
```

# nil でもメソッド呼び出しがエラーにならない safe navigation operator

Railsの `Object#try!` のように、オブジェクトが `nil` でもエラーを恐れずメソッドが呼び出せる safe navigation operator （正式な日本語訳は何？）が追加されました。

safe navigation operator は `obj&.foo` のように書きます。
`obj` が `nil` であれば、`foo` の戻り値が `nil` になります。

```ruby
require 'active_support/core_ext/object/try'

User = Struct.new(:address)
Address = Struct.new(:street)
Street = Struct.new(:first_lane)

def test_safe_navigation_operator
  street = Street.new('123')
  address = Address.new(street)
  user = User.new(address)
  # オブジェクトが存在する場合は普通にメソッドを呼び出せる
  assert_equal '123', user&.address&.street&.first_lane

  other = User.new
  # オブジェクトがnilでもNoMethodErrorが発生せずにnilが返る
  assert_nil other&.address&.street&.first_lane

  # nil でないオブジェクトに対して存在しないメソッドを呼ぶとエラーが起きる
  assert_raises(NoMethodError) { other&.adddress&.street&.first_lane }

  # Railsであれば try! を使ったコードと同等
  assert_equal '123', user.try!(:address).try!(:street).try!(:first_lane)
  assert_nil other.try!(:address).try!(:street).try!(:first_lane)
  assert_raises(NoMethodError) { other.try!(:adddress).try!(:street).try!(:first_lane) }
end
```

## 参考：Railsの try と try! の違い

`try` は呼びだしたオブジェクトにそのメソッドが実装されていなくても `nil` が返ります。
一方、`try!` はメソッドが実装されていないとエラーが起きます。
Ruby 2.3の safe navigation operator の挙動は `try!` と同等になります。

```rb 
assert_nil "hoge".try(:reverseee)
assert_raises(NoMethodError) { "hoge".try!(:reverseee) }
assert_raises(NoMethodError) { "hoge"&.reverseee }
```

参考文献： [Rails - try と try! の使い分け - Qiita](http://qiita.com/kuboon/items/8e4812bbb55c31c235bf)

P.S. 
@koic さん、編集リクエストありがとうございました！ 

# ヒアドキュメント内のインデントを取り除いてくれる <<~ （squiggly heredoc）

これまでRubyのヒアドキュメントを使うと、ヒアドキュメント内のインデントはそのままスペースやタブとして残っていました。
これだと不便なケースがよくあるため、Railsではこのインデントを取り除いてくれる [strip_heredoc](http://apidock.com/rails/String/strip_heredoc) というメソッドが用意されています。

Ruby 2.3では `<<~` というリテラル（squiggly heredoc）が導入されました。
これを使うと、`strip_heredoc` と同様に、ヒアドキュメント内のインデントを取り除いてくれます。

```rb 
require 'active_support/core_ext/string/strip'

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

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

  # <<~ を使うとstrip_heredocと同じようにインデントのスペースを取り除いてくれる（Ruby 2.3）
  text_with_squiggly_heredoc = <<~TEXT
    This would contain specially formatted text.
    That might span many lines
  TEXT
  assert_equal expected, text_with_squiggly_heredoc
end
```

# 文字列リテラルをデフォルトでfreezeさせるマジックコメント（Pragma）

Ruby 3.0では文字列リテラル（`"abc"`や`'xyz'`のようにダブルクオートやシングルクオートで囲った文字列）がデフォルトでfreeze（＝不変）になる予定です。
Ruby 2.3ではこれをファイル単位でシミュレーションするためのマジックコメント（Pragma）が導入されています。

**【2019.7.14追記】デフォルトで文字列リテラルがfreezeされる変更は見送られました**
Ruby 3.0で文字列リテラルがデフォルトでfreezeされる変更は結局見送られたようです。
詳しい内容は以下の記事をご覧ください。

> しかし、これに対してRuby3においても frozen string literals をデフォルトとすることはないという判断をしました。
>
> [Rubyではimmutable string literalといった非互換な機能の導入はどのようなプロセスを経て決定されますか？ \- Quora](https://jp.quora.com/Ruby%E3%81%A7%E3%81%AFimmutable-string-literal%E3%81%A8%E3%81%84%E3%81%A3%E3%81%9F%E9%9D%9E%E4%BA%92%E6%8F%9B%E3%81%AA%E6%A9%9F%E8%83%BD%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%AF%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86)

## マジックコメント無し => freezeしない

マジックコメントが付いていないファイルは、文字列リテラルはfreezeしません。

```ruby
require_relative '../test/test_helper'

class WithoutPragmaTest < Minitest::Test
  def test_frozen_string
    # マジックコメント（Pragma）がないのでStringは freeze していない
    assert_equal "dlrow olleH", "Hello world".reverse!
    refute "Hello world".frozen?
  end
end
```

## frozen_string_literal: true => freezeする

マジックコメントを付けることで、文字列リテラルがデフォルトでfreezeします。
ただし、文字列リテラルを使わずに文字列を生成した場合は freeze しない点に注意してください。

```rb
# frozen_string_literal: true
require_relative '../test/test_helper'

class PragmaEnabledTest < Minitest::Test
  def test_frozen_string
    # マジックコメント（Pragma）がtrueなのでStringは freeze している
    e = assert_raises(RuntimeError) { "Hello world".reverse! }
    assert_equal "can't modify frozen String", e.message
    assert "Hello world".frozen?

    # リテラルを使わずにStringを生成した場合は freeze しない
    s = true.to_s
    assert_equal 'eurt', s.reverse!
    refute s.frozen?
  end
end
```

## frozen_string_literal: false => freezeしない

マジックコメントには true/false を指定できます。
false にするとfreezeしません。

```ruby
# frozen_string_literal: false
require_relative '../test/test_helper'

class PragmaDisabledTest < Minitest::Test
  def test_frozen_string
    # マジックコメント（Pragma）がfalseなのでStringは freeze していない
    assert_equal "dlrow olleH", "Hello world".reverse!
    refute "Hello world".frozen?
  end
end
```

## 実行オプションで挙動を切り替える

ファイル内にマジックコメントがない場合、実行オプションを使って全体の挙動を切り替えることができます。

```test.rb
puts "Hello".reverse!
```

```bash
# 実行オプションを使わないとfreezeしない
$ ruby test.rb
olleH

# 実行オプションを付けてデフォルトでfreezeさせる
$ ruby --enable-frozen-string-literal test.rb          
test.rb:1:in `reverse!': can't modify frozen String (RuntimeError)
	from test.rb:1:in `<main>'

# freezeさせない実行オプションもある
$ ruby --disable-frozen-string-literal test.rb
olleH
```

実行オプションはそれぞれ `--enable=frozen-string-literal` `--disable=frozen-string-literal` のように書くこともできます。

# did_you_mean gemの標準添付
`NameError` や `NoMethodError` が発生した際に正しい名前の候補を表示してデバッグしやすくする [did_you_mean](https://github.com/yuki24/did_you_mean) gemがRuby 2.3から標準添付されます。

特に `require 'did_you_mean'` のようなコードを書かなくてもデフォルトで有効になっているようです。

```test.rb
# わざとメソッド名をtypoする
puts "Hello".revers!
```

```bash
# 実行すると正しいメソッド名の候補を表示してくれる
$  ruby test.rb
test.rb:2:in `<main>': undefined method `revers!' for "Hello":String (NoMethodError)
Did you mean?  reverse!
               reverse
```

**【2015.11.18 追記：まだあるRuby 2.3の新機能】**

@sue738 さんの[Ruby2.3.0-preview1 リリースノートメモ](http://qiita.com/sue738/items/5179464ec2e469455277)を読みながら、まだ紹介していない新機能があったことに気づきました。
というわけで、さらに追記します。

@sue738 さん、情報ありがとうございます！

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

以前から配列には `bsearch` というメソッドがありました。
これはバイナリサーチ（二分探索）のアルゴリズムを使って、オブジェクトを検索するメソッドです。

[instance method Array#bsearch (Ruby 2.2.0)](http://docs.ruby-lang.org/ja/2.2.0/method/Array/i/bsearch.html)

Ruby 2.3では見つかった要素そのものではなく、その要素のindexを返す `bsearch_index` が追加されました。

```rb
def test_bsearch_index
  # バイナリサーチ（二分探索）を使ってindexを探す
  assert_equal 0, [10, 11, 12].bsearch_index {|x| x < 12 }

  # 通常のindexを使っても結果は同じ
  assert_equal 0, [10, 11, 12].index {|x| x < 12 }

  # 配列が予めソートされていない場合、バイナリサーチは間違った結果を返す場合がある
  refute_equal 0, [10, 12, 11].bsearch_index {|x| x < 12 }

  # 通常のindexであればソートされていなくても問題ない
  assert_equal 0, [10, 12, 11].index {|x| x < 12 }
end
```

## 参考：パフォーマンスを比較する

上のコードで示したとおり、配列を予めソートしておく必要がありますが、大きな配列であれば `index` よりも速く検索できる場合があります。
`bsearch_index` と `index` の時間計算量をO記法で表すと次のようになります。

- バイナリサーチ(`bsearch_index`) = O(log2 n)
- 線形探索(`index`) = O(n)

以下はMinitestのベンチマーク機能を使って、`bsearch_index` と `index` のパフォーマンスを比較したコードです。

```rb 
require_relative '../test/test_helper'
require 'minitest/benchmark'

class Test < Minitest::Benchmark
  def self.bench_range
    # 10万、100万、1000万とテストの件数（配列の要素数）を増やす
    bench_exp 100_000, 10_000_000
  end

  def bench_bsearch_index
    results = []
    # bsearch_index と index の実行結果を保存する
    validation = ->(range, times) { results << times }

    # bsearch_indexを使って末尾の要素を探す
    assert_performance(validation) do |n|
      [*0..n].bsearch_index { |item| item == n }
    end

    # indexを使って末尾の要素を探す
    assert_performance(validation) do |n|
      [*0..n].index { |item| item == n }
    end

    # bsearch_index の方が index よりも毎回速いことを検証する
    assert results.transpose.all? { |binary, linear| binary < linear }
  end
end
```

```bash
# 実行結果（上が bsearch_index 下が index の実行時間）
bench_bsearch_index  0.004181  0.035023  0.361250
bench_bsearch_index  0.006879  0.073163  0.775984
```

ただし、配列が小さい場合や、検索したい要素が配列の先頭付近にある場合は `index` の方が速くなる場合もあります。
アルゴリズムの違いを十分理解した上で、適切なメソッドを使用してください。

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

Ruby 2.3では隣り合う要素が条件を満たせば同じグループとする `Enumerable#chunk_while` が追加されました。

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

```ruby
def test_chunk_while
  data = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
  # 隣り合う偶数同士、奇数同士の部分配列ごとに分ける
  results = data.chunk_while { |i, j| i.even? == j.even? }.to_a
  assert_equal [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]], results

  # slice_whenでも同じことができる。ただし条件が否定形になる
  results = data.slice_when { |i, j| i.even? != j.even? }.to_a
  assert_equal [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]], results
end
```

# 非推奨となった定数にマークを付ける Module#deprecate_constant

Ruby 2.3では非推奨となった定数にマークを付ける `Module#deprecate_constant` が追加されました。
マークを付けると、定数の参照時に警告が出力されます。

```ruby
class ::Foo
  BAR = 'Deprecated constant'
  # BARは deprecated （非推奨）な定数とする
  deprecate_constant :BAR
end

def test_deprecate_constant
  # Foo::BAR を参照すると警告が出力される
  assert_output(nil, /warning: constant Foo::BAR is deprecated/) { Foo::BAR }
end
```

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

Ruby 2.3では NameError や NoMethodError 発生時に、呼び出されたオブジェクト（レシーバ）を取得する `NameError#receiver` が追加されました。

```ruby
def test_name_error_receiver
  receiver = "receiver"
  e = receiver.to_ss rescue $!
  # エラーからレシーバを取得できる
  assert_same receiver, e.receiver
  assert_instance_of NoMethodError, e

  e = foo_bar.to_s rescue $!
  # NoMethodErrorの親クラスであるNameErrorでもレシーバを取得できる
  assert_same self, e.receiver
  assert_instance_of NameError, e
end
```
# freezeされていない/されている文字列を返す+と-

【2017.6.26 追記】 Ruby 2.3からStringクラスに単項演算子の`+`と`-`が追加されています。

簡単にいうと、`+`はfreezeされていない文字列を、`-`はfreezeされた文字列をそれぞれ返却します。

```ruby
x = +"foo"
x.frozen?    #=> false
(-x).frozen? #=> true

y = -"foo"
y.frozen?    #=> true
(+y).frozen? #=> false
```

厳密にいうと、次のような仕様になっています。

`String#+@`

- self が freeze されている文字列の場合、元の文字列の複製を返します。 freeze されていない場合は self を返します。

`String#-@`

- self が freeze されている文字列の場合、self を返します。 freeze されていない場合は元の文字列の freeze された複製を返します。

引用元：[Ruby 2.4.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Stringクラス](https://docs.ruby-lang.org/ja/latest/class/String.html)


# その他の新機能

これ以外にもRuby 2.3ではいろいろなメソッドや機能が追加されています。
が、使い方やサンプルコードの書き方がよくわからなかったので、今回は書きませんでした。（すいません）

もっと詳しく知りたい方は下記のファイルを参照してください。

[ruby/NEWS at v2_3_0_preview2 · ruby/ruby](https://github.com/ruby/ruby/blob/v2_3_0_preview2/NEWS)

# まとめ

というわけで、この記事ではRuby 2.3で導入される主な新機能を紹介してみました。
`dig` や safe navigation operator なんかは使用頻度が結構高そうです。
did_you_mean gemの標準添付もデバッグ効率を高めてくれそうでありがたいですね！

みなさんもどんどんRubyの新機能を活用していきましょう！

## あわせて読みたい

Ruby 2.4の新機能もまとめてみたので、気になる方は以下の記事をご覧ください。

[サンプルコードでわかる！Ruby 2\.4の新機能と変更点 \- Qiita](http://qiita.com/jnchito/items/9f9d45581816f121af07)

RSpec学習の定番本、「Everyday Rails - RSpecによるRailsテスト入門」には日本語版独自の特典として **「RSpecユーザのためのMinitestチュートリアル」** という追加コンテンツ（電子書籍）が付いています。

「RSpecならだいたいわかるけど、Minitestはあまりよくわからない」という方には特にオススメですので、まだ読んでいない方はぜひ読んでみてください！

[Everyday Rails - RSpecによるRailsテスト入門 + RSpecユーザのためのMinitestチュートリアル](https://leanpub.com/everydayrailsrspec-jp)