結論
**「合格教本の内容を8割理解して問題を解けるようにする」**です。
私自身としてはひたすら問題を解いて暗記で乗り切るのではなく、2ヶ月で8割以上理解しながら問題を回答するスタイルをおすすめします。
理由
・ 理解してることでコーディングやクラス設計能力の向上
・ 本番の引っ掛け問題に対応できる
概要
私が合格した学習した方法と試験直前メモをまとめています。
私自身はただ資格を取るのではなくコーディング、クラス設計、Railsのソースコードの読解能力を上げたかったので工夫して学習しました。
ただ資格を取るのではなく、RubyGoldの勉強でRuby力の底上げしたい方におすすめです。
学習手順
- Rexを解きつつ、理解していない単語や処理をググる
- メタプログラミングRubyを5章まで6割理解で読む
- 教本の練習問題と模試を解いた後、RubyGoldの範囲を流し読み
- 理解しつつ、ひたすら問題を解く
勉強方法
①Rex
目安期間:2週間
RexのRubyGoldの問題を最低10周しましょう。
理解重視でだいたい80点は取れるようにすると良いです。(80点だと合格は難しいです。)
※わからない部分の処理等を調べる時間を取ることが重要です。
通勤時間等の隙間時間でやるのがおすすめです。
②メタプログラミングRubyを5章まで読む
目安期間:1週間
6割理解で5章まで読みましょう。
期間に余裕がある方は最後まで読んでも良いと思います。
※最後のRailsの話のところを読むかはお好みで良いと思います。
5章まででだいたいの試験範囲に必要な箇所のRubyの原理、仕組み、動作の全体図がわかります。
おそらく多言語の経験がある方は割とスムーズに読めると思いますが、Ruby特有部分が満載なので多少時間がかかります。
他の言語の経験が浅い方は意味不明状態になる箇所があると思いますが、概要を6割程度理解して読むことが重要です。
(100%理解は時間の浪費です。理解が深まった段階で再度読むのが効率的です。)
1週間で読みきらないと思い出しのコストが高いので、5章まで読みきった方が良いです。
③教本の練習問題と模試を解いた後、RubyGoldの範囲を流し読み
目安期間:2週間
表題の通りで問題を解いた後に、RubyGoldの範囲を流し読みしてください。
※わからない箇所を把握してから全体を読むと時間を節約できます。
現時点では模試で60点くらい取れるのが理想ですが、なかなか難しいと思います。
④理解しつつ、ひたすら問題を解く
目安期間:3週間
Rexや教本の問題をひたすら解きましょう。
解いて、調べて、解いてをゲームの素材集めのようにひたすら繰り返します。
ここで理解力を底上げすると本番に強くなります。
本番は問題のバリエーションが豊富なので、応用して対応しなければならないためです。
試験直前メモ
私が間違えた箇所と試験に出やす箇所をまとめました。
試験直前や試験前で使って貰えばと思います。
ファイル系
・requireとload
概要 | require | load |
---|---|---|
ファイル読み込み | 1度 | 何度も |
拡張子 | 省略可 | 省略不可 |
バイナリエクステンション | ロード可 | ロード可 |
・特殊な変数
変数 | 内容 |
---|---|
$0 | 実行ファイル名 |
$0 == name
みたいな条件式が処理の途中にあって、回答するみたいな問題が出てました。
組み込み定数
NULL
という組み込み定数はない。
使える定数はどれみたいな問題でした。
Rdoc
概要 | 詳細 |
---|---|
見出し |
= h1 == h2 .. |
ボールド | *word* |
イタリック | _word_ |
番号なしリスト | * |
多重代入
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
スーパークラスの同名メソッドの未定義になる
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 で与えられること
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以降も実行される |
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
ブロックについて
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クラスのオブジェクト
ミックスインの継承について
# ・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の継承ツリーは更新されません。
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されたモジュール内は上位スコープの定数を読み込みに行かない
レキシカルに決まるため
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
定数探索
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 #例外発生しない
・定数探索
定数のスコープについては継承関係と違う
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がないため例外が発生します。
モジュールは継承ではないため例外が発生。
module M
CONST = "Hello, world"
end
class M::C
def hello_method
CONST
end
end
p M::C.new.hello_method #=> 例外
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’
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”
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"
メソッド継承
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'
エイリアス
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可
array = [1].freeze
array += [2,3]
p array #=> [1,2,3]
※配列ではmap!等の破壊的メソッドは実行不可だが、参照先の変更であれば可
※文字列で+=はエラー、文字列は<<なら可
JSON
---
# JSON配列
["1", "2", "3"]
---
# JSONハッシュ
{"city": "tokyo", "town": "nihonbashi"}
・load
、parse
メソッド
文字列のJSONをハッシュに変換
json = {"city": "tokyo", "town": "nihonbashi"}
JSON.load(json)
JSON.parse(json)
・dump
メソッド
ハッシュをJSONに変換
hash = {"city" => "tokyo", "town" => "nihonbashi"}
JSON.dump(hash)
・to_json
メソッド
ハッシュをJSONに変換
require 'json'
hash = {"city" => "tokyo", "town" => "nihonbashi"}
hash.to_json
require 'json'を実行するとto_jsonメソッドがObjectクラスに定義される
YAML
一応概要は知っていたほうが良いですが、コードベースの問題は本番で出ませんでした。
選択肢から間違っている問題を選ぶ際に、選択肢のひとつとして出題してました。
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