ruby資格試験ポイントまとめ

##Ruby Silver 試験ポイントまとめ(自分用)
自分用メモで汚いですが間違えやすいところをまとめてますぜひ

## 2020/9/14 合格した。94点
- 模擬と完全に同じ問題は5問ぐらいあったかな
- 模擬試験やっておけば、ほとんど初見の問題はない。ルビー開発を10年やっていても、試験対策しないと落ちると思う
- 試験会場は早めに着いても、受け付けはない。時間になると名前が呼ばれる、このタイミングで受け付け
- テストを終えると合否が画面に出でくる
- 模擬試験を繰り返せば受かりそう。教本は読まなくていけそう、模擬試験で難しい問題は出なかった。合格させたい試験に思われる。基本情報試験より楽だと思われる
- 試験費用が高すぎる。5000にしてくれ。ゴールドが10000なら分かる。
- 試験は３０分でおわた。３０分で16000だと思うとパチスロより吸い込まれる感がある
- 一度不合格になった人向けに、無料受験キャンペーンをやる時がある。
- 試験は終われば帰れる
- arrayの問題多かった
- 新宿の会場は混んでいた。
- ５０hぐらいかかった。
- arrayをただ後ろから並び変える方法、1の文字コードがわからなかった。raiseの後らrescueでexitした場合、ensureが動くのか？
- 12問間違えてもいい。３８問正解スルヒツヨウガアル
- Ruby 2.0以降では、デフォルトのスクリプトエンコーディングはUTF-8
- Hash#eachのブロックパラメータはArray。
- Hash#size はhashの要素の数を返す
- Enumerable#select	selfからブロックの条件に該当する要素を集めて返す。
- Enumerable#find	selfからブロックの条件に該当する最初の要素を返す。
- Array#delete	selfから引数の要素を削除。削除した要素を返す。破壊的メソッド。
- Obejct-numeric-integer-fixnum,bignum
- 
- split('d'),split(/;|:/)　区切って配列に入れる
- split 引数なしはスペースで区切る
- split("") 一文字ずつ区切る
- -split(",", 2) 2は区切る数　["1","2,3,4,5"]
- 例外処理について
    - Rescue 節で省略するとstandard error とそのサブクラスを拾う
    - Ensure節は必ず実行される
    - raiseメソッドは引数を指定していなければ、RuntimeError例外
 を発生
　- elseもある。rescueが実行されないときに実行。resucueの下に書く。

- extend
- オーバライド不可演算子
    - ..,&&

- 八進数表記
    - 0から始まるもの
    - Puts 090 などでエラー

- 演算子
    - 　A && B ...AがtrueだとＢがうごく
    - 　A && B ...AがfalseだとＢがうごカナイ
    - 　A || B ...AがfalseだとＢが動く
    - 　A || B ...AがtrueだとＢが動かない
    - 　A&BまたはA|B ... AがtrueデモfalseデモＢガ動く

- time
    - strftime("ここに入れる")
    - %Y YYYY
    - %m MM 月
    - %d dd
    - %H 
    - %M 分
    - %S 秒

- 演算子の優先順位は\*よりも\**が高い

- Ruby定数は大文字で始める
    - 変更可能だが警告が出る
    - <<　で追加するときは警告なし

- Ruby変数名
    - １文字目はアルファベット小文字か_で始める必要がある。
    - ２文字目以降はアルファベットもしくは数字を使用


- 可変長変数
    - *a などで宣言
    - 任意の数の引数が取れ、aに配列が格納される

- Initializeメソッドは何回でも読み出され書き直される
- Super の記述場所は任意の位置でおｋ。同名のメソッドをオーバライドしている場合はスーパーのほうが呼ばれる

- 外部モジュール読み込みについて
    - 数学PIなどをしようする場合Mathモジュールを読みこむ必要がある
    - 読み込み方法例
        - Include Math
        - Math::PI

- クラス拡張のメソッドより特異メソッドが優先して実行される

- .. , … 演算子について
    - a = [1,2,3,4]
    - a[0..3] => [1,2,3,4]
    - a[0..-1] => [1,2,3,4]
    - a[0,3] => [1,2,3]
- Timeオブジェクト、datetimeオブジェクト管理する日付時刻をフォーマットするにはsrtftime
- Timeオブジェクト同士の減算は秒になる
- File.join('/',"aaa","bbb") -> /aaa/bbb　　/は/で結合する意味ではない。
- File.join("aaa","bbb") -> aaa/bbb    通常はこっちかな
- find_all == select
- map == collect
- find == detect
- updade! == merge
- delete_if = reject!  ブロックが真になるあたいを取り除く
- %w(a b c) -> ["a","b","c"]
- "abcde".index("c") -> 2
- "abcdec".index("c",2) -> 2  (indexの位置から探す
- "abcdec".index("c",3) -> 5
- {"foo" => 1}
- {:foo -> 1}
- { foo : 1}
- hash[:foo,1]
- ポイントハ=はＮＧ，"foo":1モＮＧ、右は文字なら""必要
- 正規表現記号
    - *は直前の文字列の０回以上の繰り返しを表す
    - + は1回以上
    - iオプションで大文字と小文字の区別しない
    - . は任意の文字を表す
    - {m}は直前の正規表現のm回の繰り返しを意味
    - {m,} 直前最低ｍ回繰り返し
    - {m.n} 直前最低ｍ回繰り返し 最高ｎ回繰り返し
    - Mオプションで.が改行にもマッチする
    - \d+などの+は連続を表す
    - Matchは一度しか行わない
    - Scanは繰り返し行われる
    - \wは単語構成文字の省略記号

- 65を”A”にしたい時
    - 65.chr
    - 逆は”A”.ord
- for文、スコープは作られないので、内外の変数にアクセス可能
- each文、スコープが作られる。外からeach内部の変数にアクセスするとエラーになる。each内部から外の変数は見える
- 'abcdefg'['bc'] -> bc
- 'abcdefg'.slice('bc') -> bc
- 'abcdefg'['bd'] -> nil
- 'abcdefg'.slice!('bc') -> bc,  中身も変わる'adefg'
- 'abcdefg'[/bc/] -> bc
- 'abcdefg'.slice(/bc/) -> bc
- 'abcdefg'.slice!(/bc/) -> bc,  中身アも変わる'adefg'
- sub ... 非破壊、一つ置換  !がつけば破壊
- gsub ... 非破壊、全部置換　 !がつけば破壊
- a='aabbccddeeffgg',  
    - a.delete('be') -> 消した結果を返すaaccddffgg。 変数aは変わらない　非破壊
    - a.delete('a-f')  範囲指定可能
    - a.delete('a-c','c-g') 複数条件時は両方に共通な文字cが消える
- a='abcd'
    - a.replace('xyz') => xyz,a='xyz' になる
- 連結 + << concat *
- 大文字小文字変換、！がつけば破壊
    - downcase,upcase,swapcaseは反転
- chomp ... \r \r\n  \n を削除、非破壊
    - 複数ついてる場合は1種類消える
    - chopで消える場合は\も一緒に消える
    - str = "foobarbaz\r\n\r\n"
        - p str.chomp('').chop.chop.reverse
        - 空文字指定は全部の改行コード消える。“braboof”
    - "\r\n".chop -> kieru
    - "\r".chop -> kieeru
    - "\n".chop -> kieru 
    - "\n\n".cho- -> \n
- reverse,reverse!
- "abc\ndef\nghi".each{|c| puts c}
    - デフォルトで改行毎にブロックにわたる。、オプション変更可能
    - each_line,lineメソッドも同じ
- a=1,2,3 -> [1,2,3]
- array=[1,2,3]　参照、中身は変わらない
    - array[0..1] -> [1,2] 
    - array[1] -> 2
    - array.at(1) -> 2
    - array.valuea_at(1) ->　2
    - array.first -> 1
    - array.first(3) => [1,2,3] ３ツ
    - array.include?(3) -> true
    - array.index(2) -> 1, これは値を探して、場所を返す（string.index(?)は?文字を探してindexを返す）
- a=[1,2,3,4,5] 削除　中身が変わる
    - array.delete_at(2) -> 3,  a=[1,2,3,5]  添え字の値を削除、破壊（string.deleteは消した結果を返す、hi破壊メソッド）
    - array.detete_if{|n| n % 2 ==0} -> [1,3,5] ,a=[1,3,5]
        - reject!と同じ
    - array.delete(3)　-> 3 , a=[1,2,4,5] 値を削除
    - array.slice!(2,2) ->[3,4] ,a=[1,2,5]
    - array.shift(2) -> [1,2] , a=[3,4,5]
    - array.shift -> 1, a=[2,3,4,5]
    - popはシフトの逆
    - -でも削除可能　[1,2]-[1]=>[2]
    - []|[] 和集合
    - []&[] 重複
- 配列の繰り返し
    - each 各要素がブロックへ
    - each_index 配列のindexがブロックへ
- [1,2,3].join(",") -> "1,2,3"
- array=[1,2,3]
    - a[10]=10,トスルト　a[4-9]ハnilガハイル
- [].uniq -> 重複削除、非破壊、！がつけば破壊
- [].compact -> nil 削除、非破壊、！がつけば破壊
- [1,2,3,4,5].map{|n| n*2} -> [2,4,6,8,10]
- [1,2]*4 -> [1,2,1,2,1,2,1,2]
- ハッシュの作り方
    - {"foo" => 1}  値が文字列なら""を付ける.文字列キーにするにはこの方法しかな
    - {10 =>1}も可能、a[10]->1トナル
    - Hash["foo", 1] => {"foo" => 1}
    - {"foo" => 1,}  # {"foo"=>1}
    - {:foo => 1,} # {:foo=>1}
    - {foo: 1,} # {:foo=>1}
    - {10=> 1,} # {10=>1}
    - Hash["foo", 1,] # {"foo"=>1}
    - Hash[:foo, 1,] # {:foo=>1}
    - Hash[foo: 1,] # {:foo=>1}
    - Hash[10, 1,] # {10=>1}
        - 注意　=　はＮＧ，"foo":1もない
        - a["hoo"] -> 1
        - a[:foo] -> 1
- ハッシュメソッド
    - hash={"apple"=>"fruit","coffee"=>"drink"}
        - hash.keys -> ["apple", "coffee"] 配列で
        - hash.value -> ["fru","dri"] 
    - hash={1 => "a", 3=>"b"}
        - hash.value_at(1,3)   -> ["a","b"]  keyに対応する値を配列で返す
        - hash.fetech("1")-> a  
    - a={1 =>"a",2 =>"b",3 =>"c",4 =>"d"}
        - hash.select(|key,value| key % 2==0} -> [[2,b],[4,d]] 結果が真となる配列の組み合わせを返す
- ハッシュ変更
    - hash={"apple"=>"fruit","coffee"=>"drink"}
        - hash["apple"]="red" -> "red", hash={"apple"=>"red","coffee"=>"drink"}
        - hash["orange"]="orange" -> orange ,hash={"apple"=>"red","coffee"=>"drink","oragen"=>"orange"} 追加される
        - hash.delete("apple") -> "fruite" ,hash={"coffee"=>"drink"}
        - hash.reject{|key,value| value == "drink"} ->{"apple"=>"fruit"}, 真に値を取り除いて返す。hashは変わらない
        - hash.reject!{|key,value| value == "drink"} ->{"apple"=>"fruit"}, 真に値を取り除いて返す。hashは変わる。hash={"apple"=>"fruit"}, delete_ifと同じ機能
        - replaceは引数の中身に代わる。a=変わる
        - hash.merge は引数のハッシュとマージ、新規キーは追加、既存のキーはバリューを上書き、マージした結果を返す、非破壊
        - hash.merge! == updateは同じ機能。、マージした結果を返す、破壊メソッド
        - has_key?,inclued?,key?,member? ハッシュにkeyが存在すればtrueを返す
        - has_value?,value? ハッシュにvalueが存在すればtrueを返す
        - each,each_pair for文である。keyとvalueをブロックへ
        - each_key　keyを
        - each_value 　valueを
        - hash.sort keyで昇順ソート　配列で返す 

- File.delete('readme'
- FIle.rename('before','after')  afterになる
- IO.read('readme',5)  先頭から5バイト出力、未指定時はｆｉｌｅ全部読み込んで、変数にstringで全部入る
- IO.foreach('readme'7){ |line| puts line} 1行ずつ読み込む
- open('readme').readlines  ファイル全部読み込んで行ごとに配列へ
- io.gets 1行読み込み
- io.readline　1行読み込み
- IO出力ハwrite puts print 
- lineno => getsメソッドが呼び出された回数
- rewind , ファイルポインタが先頭へ、lineno=0
- pos=?  ファイルポインタ移動
- io.seek(10) = io.seek(10,IO::SEEK_SET) ポインタを先頭から10バイト移動
- io.seek(10,IO::SEEK_CUR) 現在位置から移動
- io.seek(10,IO::SEEK_END) ファイル末尾から移動
- Time.now,Time.new 現在時刻のtimeオブジェクトを返す
- [1,2,3,4,5].inject(0){|result,v| result + v ** 2} ->  ５５タシザンシタケッカ
- each_with_index{|item,i|   i=０カラ
- (1..10).each_cons(3) -> 
    - [1,2,3]
    - [2,3,4]
    - ...
    - [8,9,10]
- (1..10).each_slice(3) ->
    - [1,2,3]
    - [4,5,6]
    - ...
    - [10]
- [1,2,3,4,5].include?(3)-> true
- find == detect
    -  [1,2,3,4,5].find{|i| i % 2 == 0} -> 2 真ヲ1イッコ
-  [1,2,3,4,5].seletc{|i| i % 2 == 0} ->[2,4]
-  ["aaa","b","cc"].sort{|a,b| a.length <==> b.length} -> [ "b","cc","aaa"]
- ヒアドキュメント
    - <<-識別子' のように-' を付けて書くことで終端行をインデントすることは可能
    - 通常は空白を開けるとエラー

- Chompメソッドで\r\n　1つ消す
- chopメソッドで末尾の文字を消す
- IO#rewindはファイルポインターを先頭に移動する

- Splitメソッドは引数で特定の文字列を区切り文字として指定できる。また第二引数で生成される配列の個数を指定することができる。

- “0-5”は範囲指定になるが、”8-”では範囲指定にならず8と-を削除します

- eql は 文字列が同じ場合true
- equal は　オブジェクトが同じかどうかを見る

- inject はブロックに要素を割り当てる…|i,j|

- IO
    - IO#getsとIO#readlineはファイルオブジェクトから一行読み込んで、読み込みに成功した時にはその文字列を返す。
    - IO#getsとIO#readlineの違いはEOFに到達した時の振る舞いのみ。IO#getsはnil, IO#readlineはEOFErrorを返す 

```
foo = [1,2,3]
bar = foo
p foo === bar # => true　// equalと一緒なのかな？
```

```
Module Foo
  def foo			//インスタンスメソッドとして定義
    puts("foo")
  end
end

Class Bar
  extend Foo		//FooモジュールのインスタンスメソッドをBarクラスの特異メソッドとして定義
end

Bar.foo  #=> foo  という使い方ができる
```
- ::Fooのような::演算子から始まる定数は、トップレベルで定義されている定数

- slice!はスライス後を参照している

- ファイルの末尾(EOF)への反応の仕方
    - getsの場合、nilが帰る
    - Readlineの場合、EOFError例外が発生する

- File#mtimeメソッドは更新が保存されるがFile::Stat#mtimeメソッドは更新が保存されない
    - File::Statクラスはnewメソッドのみクラスメソッド

- ファイル名と拡張子が".“で区切られているファイル名から任意の拡張子を取り除く時に、第2引数として”.*"を指定してFile.basenameを呼び出します
- "%2d%s"の"%2d"は出力したい数値が2桁より少なければ、空白スペースを入れるようにする指定

```
(1..5).each_cons(3) {|arr| p arr }
# <実行結果>
# [1, 2, 3]
# [2, 3, 4]
# [3, 4, 5]

(1..10).each_slice(3) {|arr| p arr }
# <実行結果>
# [1, 2, 3]
# [4, 5, 6]
# [7, 8, 9]
# [10]
```
```
arr = [1,2].zip([3,4])
p arr
# <実行結果>
[[1, 3], [2, 4]]
```
```
a1 = [1,2,3]
a2 = [4,2,3]
p a1 - a2
# <実行結果>
[1]
```
```
p ({a: 100, b: 100}).invert

# <実行結果>
# {100 => :b}
```
```
1: s = ["one", "two", "three"]
2: s.shift
3: s.shift
4: s.unshift
5: s.push "four"
6: p s

# <実行結果>
# 1: ["one", "two", "three"]
# 2: ["two", "three"]
# 3: ["three"]
# 4: ["three"]
# 5: ["three", "four"]
```
```
p "Ruby on Rails".delete("Rails")
# <実行結果>
# "uby on "
```
```
a, b = 0    # a => 0, b => nil
c, a = 1    # c => 1, a => nil
a, d = 1, 2 # a => 1, d => 2
b, c = 3    # b => 3, c => nil
```

### selfがわからんからこれ覚える
```
class Blog
  def foo       # インスタンスメソッド
  end

  def self.foo  # クラスメソッド(このselfはクラス自身(Blog)を指す)
  end

  def bar           # インスタンスメソッド
    self.foo        # インスタンスメソッドのfooが呼ばれる(このselfはインスタンス自身(Blog.new)を指す)
    foo             # インスタンスメソッドのfooが呼ばれる
    self.class.foo  # クラスメソッドのfooが呼ばれる(このような記述でインスタンスメソッド内でもクラス自身を指すことができる)
  end

  def self.bar  # クラスメソッド(このselfはクラス自身を指す)
    self.foo    #クラスメソッドのfooが呼ばれる
    foo         #クラスメソッドのfooが呼ばれる
  end
end
```

self="My job is a sales"である

```
class String
  def change_job
    self.replace("I will become an engineer!")
  end
end

s = "My job is a sales"
s.change_job
p s
```

selfは４

```
class Interger
def aaaa
 return self
end
end

print 4.aaaa
```

一文字マッチするものがマッチ

```
a = ['3p', '913', 'Zx', 'ssr', 'M7', 'W']
a.grep(/[A-Z0-9]/)
["3p", "913", "Zx", "M7", "W"]
```

keyのソートsort1、非破壊

```
h = { "def" => 2, "ghi" => 1, "abc" => 3 }
p h.sort
[["abc", 3], ["def", 2], ["ghi", 1]]

h = { "def" => 2, "ghi" => 1, "abc" => 3 }
p h.sort.reverse
[["ghi", 1], ["def", 2], ["abc", 3]]
```

vauleのsort、非破壊

```
昇順
h = { "def" => 2, "ghi" => 1, "abc" => 3 }
p h.sort{ | a, b | a[1] <=> b[1] }
p h
[["ghi", 1], ["def", 2], ["abc", 3]]

降順
h = { "def" => 2, "ghi" => 1, "abc" => 3, "ddd" => 5 }
p h.sort{ | a, b | b[1] <=> a[1] }
[["ddd", 5], ["abc", 3], ["def", 2], ["ghi", 1]]

a,bに-がつくパターンもある意味が分からん
```

 include で読み込めるのは？インスタンスメソッド、インスタンス変数、定数の情報を定義しているクラスに追加します。

```
module Foo
  Bar = "bar"
end
 
class Baz
  include Foo
end
 
puts Baz::Bar  #=> bar　　// 定数だからなぜか定数はこれでいける。メソッドはnewシナイトダメ
```

extend で読み込めるのは？のインスタンスメソッドを特異メソッドとしてクラスに追加します。クラスメソッド扱い

```
module Foo
def foo
  puts("foo")
end
end
 
class Bar
  extend Foo
end
 
Bar.foo  #=> foo
```

```
a = "foo"
b = a
b.slice!(0, 1)  ->fが出る。!ナノデooになる
print(a, b) -> oooo
```

- マシンのポインタのサイズは31ビット幅とします。31ｂｉｔならbignumになる
- Fooクラスの定義の中でattr_accessorメソッドを呼び出すと、引数に指定された名前のインスタンス変数を作成し、そのインスタンス変数に対する書き込みと読み込みのアクセサメソッドをFooクラスに定義します
    - attr_accessor :foo ->インスタンス変数
    - とすれば
    - bar = Bar.new(“bar”)
    - puts(bar.foo)


Dunce\スペースは改行されない

```
File.open("hats.txt", "w") do |f|
  f.puts(%w[Bowler Deerstalker Dunce\ cap Fedora Fez])
end

hats.txt
Bowler
Deerstalker
Dunce\ cap
Fedora
Fez
```

File.statはopenしたときのスナップショット

```
file = File.open("hello.rb", "w")
stat = file.stat
mtime1 = stat.mtime　　//onaji
file.puts("new data")
file.flush
mtime2 = stat.mtime　// onaji
```

カレント、親
```
["tmp", "tmp/lang",  "tmp/lang/ruby", "tmp/lang/python"].each do |dir|
  Dir.mkdir(dir)
end
Dir.chdir("tmp/lang")
Dir.new(".").each do |entry| // . , .. , ruby, python の4ディレクトリ
  filename = File.join(entry, "rocking.rb")
  File.open(filename, "w")
end
Dir.rmdir("python")
```

- File.basename(filename, “.*”)  // ファイル名から拡張子をとる
- File.extname("child/kenji.rb")　// .rb
- 書き込み
    - puts 改行あり
    - print なし
    - write ナシ
  
```
File.open("fancy.txt", "w") do |f|
  f.write("R u b y\n")
  f.puts(["u","b","y"]) // 配列１ツズツ改行
end
puts File.read("fancy.txt")

R u b y
u
b
y

```

File.splitはディレクトリ部分とファイル部分に文字列オブジェクトの引数を分割し、両方から末尾のスラッシュを取り除きます。2つの部分は2つの要素を持つ1つの配列として返されます。問題のプログラムでは、配列の[“/home/john”, “bookmarks”]が返されます。
joinメソッドはFile.splitの返した値である配列で呼ばれています。つまりArray#joinが呼び出され、File.joinではありません。Array#joinは配列の要素に文字列を単純に連結するので、(d)が正解です。
```
p File.split("/home/john/bookmarks/").join
“/home/johnbookmarks”
```

- File.joinと間違えるな
    - [“/home/john”, “bookmarks”].join -> /home/johnbookmarks
    - [“/home/john”, “bookmarks”].join("\_") -> /home/\
- odd? 奇数か？
- even? 偶数か？

- ブロックには|a,0|  |b,1|  |c,2| ....
- breakメソッドの引数が指定されていれば、その値がブロック付きメソッド呼出しの返す値になります。インデックスは0から数え始め、最初に奇数になるインデックスは1です。each_with_indexメソッドはインデックスが1の値である"b"を返して繰り返しを終えます。そして、返された"b"はローカル変数のfooに代入されます。

```
foo = ('a'..'z').each_with_index {|i, n| break(i) if n.odd? }
  p foo.succ
```

- 0 % 3 ... あまり０
- 3 % 3 ...　あまり０
- 6 % 5 ... あまり１

- array のソート
    - 1次元
        - array.sort 昇順
        - array.sort.reverse
    - 2次元
    - self <=> other」メソッドの場合はselfとotherを比較して、selfが大きい時に正、等しい時に0、小さい時に負の整数を返します→ダカラ何ッテカンジ意味わからん
    - 

```
score = [["kobayashi", 86],["murata", 54],["azuma", 72]]
puts "a-shoujun"
p score.sort { |a, b| a[0] <=> b[0] }
p score.sort { |a, b| -a[0] <=> -b[0] } #　数値をマイナスをつけているが意味がわからん

puts "a-koujun"
p score.sort { |a, b| a[0] <=> b[0] }.reverse
p score.sort { |a, b| b[0] <=> a[0] }
p score.sort { |a, b| -b[0] <=> -a[0] } # musi

puts "b-shoujun"
p score.sort { |a, b| a[1] <=> b[1] }
p score.sort { |a, b| -b[1] <=> -a[1] } # musi

puts "b-koujun"
p score.sort { |a, b| a[1] <=> b[1] }.reverse
p score.sort { |a, b| b[1] <=> a[1] }
p score.sort { |a, b| -a[1] <=> -b[1] } # オボエテオコウ

a-shoujun
[["azuma", 72], ["kobayashi", 86], ["murata", 54]]
[["azuma", 72], ["kobayashi", 86], ["murata", 54]]
a-koujun
[["murata", 54], ["kobayashi", 86], ["azuma", 72]]
[["murata", 54], ["kobayashi", 86], ["azuma", 72]]
[["murata", 54], ["kobayashi", 86], ["azuma", 72]]
b-shoujun
[["murata", 54], ["azuma", 72], ["kobayashi", 86]]
[["murata", 54], ["azuma", 72], ["kobayashi", 86]]
b-koujun
[["kobayashi", 86], ["azuma", 72], ["murata", 54]]
[["kobayashi", 86], ["azuma", 72], ["murata", 54]]
[["kobayashi", 86], ["azuma", 72], ["murata", 54]]

```

スラッシュハ増えないようだ。　/// にはならないひっかけ

```
https="https://"
domain="example.jp"
dir="index.html"
puts File.join(https, domain, dir)

https://example.jp/index.html

# https:/ -> ソノママ
# https: -> https:/
```

```
true & a = "We"  # 左辺に関係なく、右辺実行
puts a # We
false | b = "are"　# 左辺に関係なく、右辺実行
puts b # are
2 == 1 && c = "Ruby" # 左辺がfalseナノデ、オワル
puts "c=nil" if c.nil?　#nil
5 > 3 || d = "Engineer" #左辺がtrueナノデオワル
puts "d=nil" if d.nil?  # nil

p = a + b + c + d # we + are + nil でエラーになります
```

```
h = {:name => 'sato', :club => 'tennis'}.fetch(:name, 'error')
print h # sato

h = {:name => 'sato', :club => 'tennis'}.fetch(:nam, 'error')
print h # error
```