2021年版【 RubyGold 】Ruby Gold version 2.1に1発合格する方法のまとめ

####結論
**「合格教本の内容を8割理解して問題を解けるようにする」**です。

私自身としてはひたすら問題を解いて暗記で乗り切るのではなく、2ヶ月で8割以上理解しながら問題を回答するスタイルをおすすめします。

####理由
・ **理解してることでコーディングやクラス設計能力の向上**
・ **本番の引っ掛け問題に対応できる**

####概要
私が**合格した学習した方法**と**試験直前メモ**をまとめています。

私自身はただ資格を取るのではなくコーディング、クラス設計、Railsのソースコードの読解能力を上げたかったので工夫して学習しました。

**ただ資格を取るのではなく、RubyGoldの勉強でRuby力の底上げしたい方におすすめです。**

#学習手順
1. [Rex](https://rex.libertyfish.co.jp/)を解きつつ、理解していない単語や処理をググる
2. メタプログラミングRubyを5章まで6割理解で読む
3. 教本の練習問題と模試を解いた後、RubyGoldの範囲を流し読み
4. 理解しつつ、ひたすら問題を解く

#勉強方法
### ①Rex
**目安期間：2週間**

**[Rex](https://rex.libertyfish.co.jp/)のRubyGoldの問題を最低10周しましょう。**

理解重視でだいたい80点は取れるようにすると良いです。（80点だと合格は難しいです。）
※わからない部分の処理等を調べる時間を取ることが重要です。

通勤時間等の隙間時間でやるのがおすすめです。

###②メタプログラミングRubyを5章まで読む

**目安期間：1週間**

**6割理解で5章まで読みましょう。**

期間に余裕がある方は最後まで読んでも良いと思います。
※最後のRailsの話のところを読むかはお好みで良いと思います。

5章まででだいたいの試験範囲に必要な箇所のRubyの原理、仕組み、動作の全体図がわかります。

おそらく多言語の経験がある方は割とスムーズに読めると思いますが、Ruby特有部分が満載なので多少時間がかかります。

他の言語の経験が浅い方は意味不明状態になる箇所があると思いますが、概要を6割程度理解して読むことが重要です。
（100%理解は時間の浪費です。理解が深まった段階で再度読むのが効率的です。）

1週間で読みきらないと思い出しのコストが高いので、5章まで読みきった方が良いです。

###③教本の練習問題と模試を解いた後、RubyGoldの範囲を流し読み

**目安期間：2週間**

**表題の通りで問題を解いた後に、RubyGoldの範囲を流し読みしてください。**
※わからない箇所を把握してから全体を読むと時間を節約できます。

現時点では模試で60点くらい取れるのが理想ですが、なかなか難しいと思います。

###④理解しつつ、ひたすら問題を解く

**目安期間：3週間**

**[Rex](https://rex.libertyfish.co.jp/)や教本の問題をひたすら解きましょう。**

解いて、調べて、解いてをゲームの素材集めのようにひたすら繰り返します。

ここで理解力を底上げすると本番に強くなります。
本番は問題のバリエーションが豊富なので、応用して対応しなければならないためです。

#試験直前メモ

私が間違えた箇所と試験に出やす箇所をまとめました。
試験直前や試験前で使って貰えばと思います。

###ファイル系
・requireとload

| 概要 | require | load |
|:-----------:|:------------:|:------------:|
| ファイル読み込み | 1度 | 何度も |
| 拡張子 | 省略可 | 省略不可 |
| バイナリエクステンション | ロード可 | ロード可 |

・特殊な変数

| 変数 | 内容 |
|:-----------:|:------------:|
| $0 | 実行ファイル名 |


``$0 == name``みたいな条件式が処理の途中にあって、回答するみたいな問題が出てました。

###組み込み定数

``NULL``という組み込み定数はない。
使える定数はどれみたいな問題でした。

###Rdoc

| 概要 | 詳細 |
|:-----------:|:------------:|
| 見出し | ``= h1`` ``== h2`` .. |
| ボールド | ``*word*`` |
| イタリック | ``_word_`` |
| 番号なしリスト | * |

###多重代入

```ruby
a, b = [1, 2]
a=1
b=2

a, b = [1, 2,3]
a=1
b=2

a, *b = *[1, 2, 3]
a=1
b=[2,3]

a, b, c = [1, 2]
a=1
b=2
c=nil
```

###remove_methodとundef_methodの違い

・remove_mehtod
　　スーパークラスの同名メソッドは消えない
・undef_method
　　スーパークラスの同名メソッドの未定義になる

```ruby
class A
  def ok
    puts 'A'
  end
end
class B < A
  def ok
    puts 'B'
  end
end
B.new.ok   # => B

class B
  undef_method :ok
end
B.new.ok   # => NameError

class B
  remove_method :ok
end
B.new.ok   # => A
```

###undef 文と undef_method の違い

メソッド名を String または Symbol で与えられること

```ruby
module M1
  def foo; end
  def self.foo_delete
    undef foo
  end
end
M1.instance_methods false #=> ["foo"]
M1.foo_delete
M1.instance_methods false #=> []

module M2
  def foo; end
  def self.foo_delete
    undef_method :foo
  end
end
M2.instance_methods false #=> ["foo"]
M2.foo_delete
M2.instance_methods false #=> []
```

###ラムダとProcの違い

| 特徴 | Proc | lambda |
|:-----------:|:------------:|:------------:|
| 引数の数 | 曖昧 | 厳密 |
| return, brake, next | call以降が実行されない | call以降も実行される |

```ruby
def proc_return
  proc = Proc.new{ return "実行元のメソッドから脱出" }
  proc.call
  10 # 未実行
end

p proc_return # => "実行元のメソッドから脱出"

def lambda_proc_return
  lambda = -> { return "ブロックのスコープから脱出" }
  lambda.call
  10
end

p lambda_return # => 10
```

###ブロックについて

```ruby
bar do
  puts "hello, world"
end

def bar
  yield
end

def bar(&block)
  yield
end

def bar(&block)
  block.yield
end

def bar(&block)
  block.call
end

bar(5) {
  puts "hello, world"
}

def bar(n, &block)
  block.call
end

```

###Integerについて

|演算|戻り値クラス|
|:-----------:|:------------:|
|FixnumとRationalの演算|Rational|
|FloatとRationalの演算|Float|
|FixnumとComplexの演算|Complex|
|FloatとComplexの演算|Complex|
|Date同士の減算|Rational|
|Time同士の減算|Float|
|DateTime同士の減算|Rational|

※「+ -」等の演算子はFixnumクラスのオブジェクト

###ミックスインの継承について

```ruby
#・includeの継承

module M1; end
module M2; end

class C
  include M1, M2
end

p C.ancestors #=>[C, M1, M2, Object, Kernel, BasicObject]

class D
  include M1
  include M2
end

p D.ancestors #=>[C, M2, M1, Object, Kernel, BasicObject]

#・prependの継承

module M1
end
module M2
end
class C
  prepend M1, M2
end
p C.ancestors #=> [M1, M2, C, Object, Kernel, BasicObject]
```

サブモジュールをモジュールの継承ツリーに追加してもクラスCの継承ツリーは更新されません。

```ruby
module M1
  def method_1
    __method__
  end
end

class C
  include M1
end

p C.new.method_1

module M2
  def method_2
    __method__
  end
end

module M1
  include M2 # サブモジュールM2を追加しても、クラスCの継承ツリーは更新されない
end

p C.ancestors # [C, M1, Object, Kernel, BasicObject] と表示される
```

includeされたモジュール内は上位スコープの定数を読み込みに行かない
レキシカルに決まるため

```ruby
module M
  def const
    CONST
  end
end

module E
  CONST = '010'
end

class D
  CONST = "001"
end

class C < D
  include E
  include M
  CONST = '100'
end

p C.ancestors # => [C, M, E, D, Object, Kernel, BasicObject]
p C.new.const # => NameError
```

###定数探索

```ruby
module M
  CONST = "Hello, world"
end

class M::C
  def hello_method
    CONST
  end
end

p M::C.new.hello_method # 例外が発生する

module M
  CONST = "Hello, world"

  class C
    def hello_method
      CONST
    end
  end
end

p M::C.new.hello_method #例外発生しない
```

・定数探索
定数のスコープについては継承関係と違う

```ruby
  module M2
    CONST = "011"

    class Ca
      CONST = "100"
    end

    class Cb < Ca
      p CONST # => ‘011’
    end
  end
```

参考：特異クラスの継承関係
C特異クラス→C通常クラス→親クラス
``[#<Class:#<C:0x007fa4741607e0>>, C, Object, Kernel, BasicObject]``

定数の参照はレキシカルに行われます。 M::C#hello_methodのコンテキストにCONSTがないため例外が発生します。
モジュールは継承ではないため例外が発生。

```ruby
module M
  CONST = "Hello, world"
end

class M::C
  def hello_method
    CONST
  end
end

p M::C.new.hello_method #=> 例外
```

```ruby
module M1
  class C1
    CONST = "X01"
  end

  class C2 < C1
    CONST = "X10"

    module M2
      CONST = "X11"

      class Ca
        CONST = "X10"
      end

      class Cb < Ca
        p CONST
      end
    end
  end
end
#=> ‘X11’
```

```ruby
module M1
  class C1
    CONST = "X01"
  end

  class C2 < C1
    CONST = "X10"

    module M2
      CONST = "X11"

      class Ca
        CONST = "X10"
        class Cb < Ca
          p CONST
        end
      end
    end
  end
end

#=> “X10”
```

```ruby
Const = "top"

module M
  Const = "m"
end

class C1
  include M

  def c1
    ::Const
  end
end

class C2
  def c2
    M::Const
  end
end

class C3 < C1
end

p C1.new.c1 # => "top"
p C2.new.c2 # => "m"
p Const     # => "top"
p M::Const  # => "m"
p C1::Const # => "m"
p C3::Const # => "m"
```

###メソッド継承

```ruby
class Test1
  private
  def test
    'test'
  end

  def hoge
   'hoge'
  end
end

class Test2 < Test1
  public :test, :hoge
  def test
    super
    'test2'
  end
end

p Test2.new.test #=> 'test2'
p Test2.new.hoge #=> 'hoge'
```

###エイリアス

```ruby
alias new_method old_method
alias :new_method :old_method #（カンマない）
alias $new_global_val $old_global_val
alias_method "new_method", "old_method"
alias_method :new_method, :old_method
```

###・clone, dup, freezeメソッド

clone
freeze、特異メソッドなどの情報も含めてコピーする
参照先のオブジェクトはコピーされない

dup
freeze、特異メソッドなどの情報も含めてコピーしない

freeze
モジュールやクラスもfreeze可
モジュールをインクルードしたクラスはfreeze可

```ruby
array = [1].freeze
array += [2,3]
p array #=> [1,2,3]
```

※配列ではmap!等の破壊的メソッドは実行不可だが、参照先の変更であれば可
※文字列で+=はエラー、文字列は<<なら可

###JSON

```ruby
---

# JSON配列
["1", "2", "3"]

---

# JSONハッシュ
{"city": "tokyo", "town": "nihonbashi"}
```

・``load``、``parse``メソッド
文字列のJSONをハッシュに変換

```ruby
json = {"city": "tokyo", "town": "nihonbashi"}
JSON.load(json)
JSON.parse(json)
```

・``dump``メソッド
ハッシュをJSONに変換

```ruby
hash = {"city" => "tokyo", "town" => "nihonbashi"}
JSON.dump(hash)
```

・``to_json``メソッド
ハッシュをJSONに変換

```ruby
require 'json'
hash = {"city" => "tokyo", "town" => "nihonbashi"}
hash.to_json
```
require 'json'を実行するとto_jsonメソッドがObjectクラスに定義される

###YAML

一応概要は知っていたほうが良いですが、コードベースの問題は本番で出ませんでした。
選択肢から間違っている問題を選ぶ際に、選択肢のひとつとして出題してました。


```ruby
require 'yaml'

---

# yaml配列
- red
- green
- blue

---

# yamlのハッシュ
city: tokyo
town: nihonbashi
```

###Threadクラス
・スレッドを作成するメソッド
※runは生成しない

・Thread#new
・Thread#fork
・Thread#start

・例外について
スレッド実行中は例外が発生しても、メッセージ出力なしで停止状態になること
``-d``コマンドと実行するといずれかのスレッドで例外が発生した時点でメッセージを出力する

##終わりに
上記は個人的に重要な点をまとめましたが、教本の問題に関連する箇所の概要はすべてキャッチアップした方が良いと思います。

全体的に問題が応用されていて1問1問時間がかかります。
具体例だと「1問内でコードA,Bの合わせた結果」を求められるのでコードA,Bの解くので1問で2問解いている感触でした。
解くのに時間もかかりますし、1問内で出題範囲が広くなるので応用力が求められます。

下記の記事は古いですが復習にはおすすめです。
https://tamata78.hatenablog.com/entry/2015/11/03/101002