Ruby Silver 2.1.0 のための個人的なノート

# 変数
## ローカル変数
宣言必須。忘れるとNoNameError

```.rb
# 宣言さえされていれば、代入されなくても良い(初期値=nil)
abc = 0 if nil || false
aBc = 0 if nil || true
puts "abc = #{abc} and aBc = #{aBc}" 
# => abc =  and aBc = 0

# def式の外で宣言されたローカル変数をdef式内で参照するとNameError
_x=1
def local_scope_outside_in
 puts _x # => NameError
end
local_scope_outside_in

# def式内で宣言されたローカル変数をdef式外で参照するとNameError
def local_scope_inside_out
 あ = 0
end
local_scope_inside_out
puts あ # => NameError

# ブロック内で宣言されたローカル変数は、次の繰り返しでは未宣言状態
(1..2).each do |x| 
  p defined?(v) # => 常にnil
  v = x # => vの宣言
  p v # => 1とか2とか
end

# 宣言されていない変数への自己代入は例外発生(nilクラスに+=メソッド定義されてないよ)
y += 1 # => NoMethodError
```

## インスタンス変数
- 初期値はdef initialize end 内に書く
- 初期値はnil
- 宣言不要
- @ではじまる
- インスタンス内で共有される

```.ruby
class VarIns
  @un_inited_val
  def initialize
    @inited_val = 0
  end
  def show
    puts "@inited_val=#{@inited_val}"
    puts "@un_inited_val=#{@un_inited_val}"
  end
end
ins = VarIns.new
ins.show

# @inited_val=0
# @un_inited_val=
```



## クラス変数

ローカル変数と違い、初期化が必須！

```.ruby
class ClassVal
  @@class = 0 if nil
  def show
    p @@class
  end
end
cv = ClassVal.new
cv.show # => NameError
```


クラス、サブクラス、モジュール間で共有される

```.ruby
module Show
  @@class = nil # 初期化必須
  def show
    puts "#{self.class.name} class : #{@@class}"
  end
end

class Parent
  include Show
  @@class = :parent
  def update(var)
    @@class = var
  end
end

class Child < Parent
  @@class = :child 
end

class Child2 < Parent
  @@class = :child2 #最後の代入が優先される
end

p = Parent.new
c = Child.new

p.show #Parent class : child2
c.show #Child class  : child2
c.update(:Ruby!)    # 別インスタンスに波及
p.show #Parent class : Ruby!
c.show #Child  class : Ruby!
```

## グローバル変数
アプリケーション全体で共有

```.ruby
# 再代入可能
$global = :global
puts "グローバル変数：#{$global}" # => グローバル変数：global
$global = :local
puts "グローバル変数：#{$global}" # => グローバル変数：local

# 組み込み変数への再代入は不可
$! = "Global" # NameError: $! is a read-only variabl
```

## 定数 [A-Z]ではじまる大文字
定数は何かのクラスに属する変数

```.ruby
class FirstClass
  Constant = 1
end

class SecondClass
  Constant = 2
end

Constant = 0

p FirstClass::Constant  # => 1 
p SecondClass::Constant # => 2 
p ::Constant            # => 0 トップレベル(Object)へのアクセス
p Object::Constant      # => 0 
```

その他

```.ruby
# 
Constant = 0 if nil # => 宣言だけでは参照時にエラー発生
Constant = 1 # 初期化必須
Constant = 2 # 再代入可能 with 警告 warning: already initialized constant
```


## 擬似変数
7つある（ドラゴンボール）

```.ruby
# 再代入不可
nil = false = true = self = __FILE__ = __LINE__ = __ENCODING__ = ""

# ７つの擬似変数
p nil.class if !nil # => NilClass
p false.class unless false # => FalseClass
p true.class if true # => TrueClass
p self.class # => Object
p __FILE__ # =>"note.rb"(実行中のファイル名)
p __LINE__ # => 46(実行中の行番号)
p __ENCODING__ # => #<Encoding:UTF-8>
```

## 予約語



```.rb
# 馴染み深い 28words
class     #定義：クラス
def       #定義：メソッド
end       #定義：閉じる
module    #定義：モジュール名はアルファベットの大文字（定数へのモジュールの代入）
and       #&&と同じ
or        #||と同じ
begin     #例外処理
rescue    #例外処理：例外が発生した場合に実行
else      #例外処理：例外が一切発生しなかった場合に実行、制御：
ensure    #例外処理：例外の発生有無に関わらず実行
break     #脱出：最も内側の繰り返し（現在の繰り返し）
next      #脱出：最も内側の繰り返しの残り部分をスキップして次回の繰り返しにジャンプ
if        #制御：条件分岐
then      #制御：条件分岐（省略可能）
elsif     #制御：条件分岐
unless    #制御：条件分岐(ifの逆)
case      #制御：多岐分岐case文
when      #制御：case文で基準値と比較する(==をオーバーライドした===)
for       #制御：繰り返し
in        #制御：式を評価した結果のオブジェクトの各要素に対して
do        #制御：for文の後にくる（省略可能）
while     #制御：繰り返し
until     #制御：繰り返し（whileの逆)
nil       #擬似変数
false     #擬似変数
true      #擬似変数
self      #擬似変数
super     #メソッド呼び出し：オーバーライドしているメソッドを呼び出す

# 勉強しておこう 4words
defined?  #定義：式が定義されていなければ、偽を返す
redo      #脱出：最も内側の繰り返しの今回の繰り返しを初めからやり直す
retry     #例外処理：rescue 節で begin 式をはじめからもう一度実行。
          #処理が成功するまで処理を繰り返すようなループを作る。
yield     #メソッド呼び出し：ブロック呼び出し

# 暗記しておこう 6words (知ってるけどミスるor知らない) 
return    #戻り値（省略可。多値の返却はArray）
BEGIN     #初期化ルーチン：トップレベルでのみ書ける
END       #後始末ルーチン
alias     #定義：メソッドあるいはグローバル変数に別名をつける
undef     #定義：メソッドの定義を取り消し
not       #制御：条件式の否定
```



# 演算子
ほとんどの演算子は再定義されたメソッドで、読みやすくするためのシンタックスシュガー。
同じ演算子でもメソッド呼び出しを受けるオブジェクトによって意味が異なる（演算子多様性）。

## 再定義 **不** 可能 11個

```.ruby
# 間違えそう!! 意味が同じで優先順位が異なる相方を持つ論理演算子
&& > and
|| > or
! > not

# 範囲演算子 
..    # (1..3).each{|x|p x} # => 1 2 3
...   # (1...3).each{|x|p x} # => 1 2

# 定数のスコープ演算子（クラス内の定数や、モジュール内のクラス名参照とか）
:: # ::Constant, FirstClass::Constantなど
   # `ActiveRecord::Base`は`ActiveRecord`モジュールの`Base`クラス（定数）を参照する

# その他
?: # 条件演算子 1 > 0 ? :yes : :no => yes
= # 代入

```



# 正規表現
- スラッシュで囲んで生成する (regexp = /ruby/ )
- %記法 ( %r|ruby| , %r¥ruby¥)
- /ruby/i 大文字小文字区別 **しない**
- /ruby/o １回だけ式展開する（ループ中で使うときに有利）

```
^ : 行頭
$ : 行末
. : 任意の一文字（改行除く）
* : 直前の表現の0回以上の繰り返し。
¥w: 英数字 [0-9A-Za-z_]と同じ
¥W: 英数字以外
¥s: 空白文字 [¥t¥n¥r¥f]
¥S: 空白文字以外
¥d: 数字
¥D: 数字以外
[]: 文字クラス指定(文字クラス中の^が否定）
{m,n}: 指定範囲の繰り返し(m回以上、最大n回以下）
```

# クラス

```.ruby
# クラスは大文字で始まる
class 日本語クラス # => class/module name must be CONSTANT
end
c = 日本語.new
```


## Arrayクラス
%w!STRING!

```.ruby
ary = %w!a b c! #=> ["a", "b", "c"]
p ary[1,2] # => ["b", "c"]
```

要素削除は、合致するもの全て消える

```.ruby
ary = ["a", "b", "c", "a", "b", "c"]
ary.delete("b") # => "b"
ary # => ["a", "c", "a", "c"]
```

ソート

```.ruby
["Hello", "World", "by", "Ruby"]
p ary.sort{|x,y| x.size - y.size} # => ["by", "Ruby", "World", "Hello"]
```

データ構造

```.ruby
# キュー
ary.push("smth") #最後に追加
ary.shift # 先頭消す(破壊的)

# スタック
ary.push("smth") #最後に追加
ary.pop # 最後に追加したものを排出
```
集合演算

```.ruby
ary1 = %w|ラーメン パスタ お好み焼き|
ary2 = %w|パスタ 寿司 麻婆豆腐|
ary1 & ary2 # => ["パスタ"]
ary1 | ary2 # => ["ラーメン", "パスタ", "お好み焼き", "寿司", "麻婆豆腐"]
ary1 -ary2  # => ["ラーメン", "お好み焼き"]
ary2 - ary1 # => ["寿司", "麻婆豆腐"]
```

その他

```.ruby
ary1 + ary2 #=> ["ラーメン", "パスタ", "お好み焼き", "パスタ", "寿司", "麻婆豆腐"]
ary # => ["soul", "sister"]
ary.collect{|x| x.reverse! } #["luos", "retsis"] (mapと同じ)
compact # nil要素を取り除く
concat # 破壊的に連結する
ary1.concat(ary2) # => ["ラーメン", "パスタ", "お好み焼き", "パスタ", "寿司", "麻婆豆腐"]
ary1.detect{|x| x == "お好み焼き"} # => "お好み焼き" (最初に真になったものを返す) findと同じ
ary1.find_all{|x| x == "パスタ"} # => ["パスタ", "パスタ"]
ary.fill("ok",1..3) #=> [nil, "ok", "ok", "ok"]
p ary # => [nil, "ok", "ok", "ok", ["ok", "ok", "ok"]]
ary.flatten # => [nil, "ok", "ok", "ok", "ok", "ok", "ok"]
ary_slice = ary.slice!(1..3) #=> ["ok", "ok", "ok"]
ary #=> [nil, ["ok", "ok", "ok"]]
ary_slice #=> ["ok", "ok", "ok"]
ary_slice.uniq! #=> ["ok"]
ary_slice #=> ["ok"]
```

## Hashクラス
キーオブジェクトの比較は eql? メソッドが使用される（同一オブジェクトを指しているか？→シンボルを使うのが良さそう）

```.ruby
str1 = "string" # => "string"
str2 = "string" # => "string"
str1 == str2 # => true
str1.eql?(str2) # => true
str1.equal?(str2) # => false
```

```.ruby
hash = {:A => 1, :B => 2} #=> {:A=>1, :B=>2}
hash.empty? #=> false
hash.fetch(:A) #=> 1
hash.include?(:A) #=> true
hash.include?(:C) #=> false
hash.invert #=> {1=>:A, 2=>:B} 値からキーへのハッシュを返す
hash.keys #=> [:A, :B]
hash.has_key?(:A) #=> true member? と同じ
hash.member?(:A) #=> true
hash.member?(:C) #=> false
hash1 = {:a => 1, :b => 2} #=> {:a=>1, :b=>2}
hash2 = {:c => 3, :d => 4} #=> {:c=>3, :d=>4}
hash1.merge(hash2) #=> {:a=>1, :b=>2, :c=>3, :d=>4}　updateと同じ
hash1 #=> {:a=>1, :b=>2}
hash2.merge(hash1) #=> {:c=>3, :d=>4, :a=>1, :b=>2}
hash2.merge(hash2) #=> {:c=>3, :d=>4}
hash2.merge(hash1).sort #=> [[:a, 1], [:b, 2], [:c, 3], [:d, 4]]
hash1.store(:x, 99) #=> 99　[]=　と同じ
hash1 #=> {:a=>1, :b=>2, :x=>99}
hash1.to_a #=> [[:a, 1], [:b, 2], [:x, 99]]
hash1.update(hash2) #=> {:a=>1, :b=>2, :x=>99, :c=>3, :d=>4}
hash1.update(hash2).values #=> [1, 2, 99, 3, 4]
hash1[:y]=(100) #=> 100
hash1 #=> {:a=>1, :b=>2, :x=>99, :c=>3, :d=>4, :y=>100}
```

## 継承
継承の仕方とメソッドの上書き

```.ruby
class Pa
  def f_name
    puts "Ruby"
  end
end

class Child < Pa
  def f_name
    puts "my family name is"
    super
  end
end

child = Child.new
child.f_name

# => my family name is
# => Ruby

```

クラスの再定義は ```class << Time ```

## Mix-in
クラスにモジュールを取り込む機能

- indlude クラスにモジュールを取り込む
- extend オブジェクトにモジュールを取り込む

```.ruby
module Houtyou
  def cut_veg
    puts '野菜を切る'
  end
  def cut_meat
    puts '肉を切る'
  end
end

class MisoSoup
  include Houtyou # <= ここで取り込んだ!!
  def niru
    puts '煮る'
  end
end

miso = MisoSoup.new
miso.cut_veg
miso.niru

# 野菜を切る
# 煮る
```


```.ruby
module KuroMa
  def fire
    puts 'ファイア'
  end
  def firla
    puts 'ファイラ'
  end
  def firga
    puts 'ファイガ'
  end
end

class Char
  def tatakau
    puts 'たたかう'
  end
end

battu = Char.new
rena = Char.new
battu.extend KuroMa

battu.tatakau
rena.tatakau
battu.fire
rena.fire

# たたかう
# たたかう
# ファイア
# sample.rb:28:in `<main>': undefined method `fire' for #<Char:0x007f9e8993a5d8> (NoMethodError)
```

## Stringクラス

indexは位置検索。第二引数で検索位置を指定。
```.ruby
str => "あいうえおあいうえお"
str.index("あ") => 0
str.index("あ",2) => 5
```

deleteメソッドの引数を複数指定すると、引数の共通文字列が削除される

```.ruby
"abcd".delete("abc","bcd") # => "ad"
```


split 文字列分割

- 配列を返す
- 大文字小文字区別なし
- 破壊的メソッドではない

```.ruby
"Ruby on Rails".split(' ') => ["Ruby", "on", "Rails"]
"Ruby on Rails".split('R') => ["", "uby on ", "ails"]
```

% 書式付き文字列
str % arg
数字とか、空白、日付、ハッシュなど

```.ruby
puts "%05d" % 12 # => 00012

puts "%-5s:%08x" % ["ID",self.object_id ] # => ID   :3fd5b106f240

"foo = %{foo}" % { :foo => 'bar' }        #=> "foo = bar"
```


## Timeクラス

```.ruby
- Time.new
    - Time.new
    - Time.new(2002, 10, 31, 2, 2, 2, "+09:00") 
- Time.at(Time.new()+(60*60*24*365).to_i)
    - #=> 2016-10-11 21:45:06 +0900
- Time.local
    - Time.local(2015,10,15,20,15,1)
    - # => 2015-10-15 20:15:01 +0900
- Time.gm # GMT時間で日時作成
    - Time.gm(2000,"jan",1,20,15,1) 
    - # => 2000-01-01 20:15:01 UTC
- + #time + numeric → time
    - Time.now() + (60*60*24*365)
    - # => 2016-10-11 22:31:03 +0900
- - 
    - # time - other_time → float
        -  Time.now() - Time.new(2015,10,12,22,33)
        -  # => 42.759754
    - # time - numeric → time
        - Time.now() - 60
        - # => 2015-10-12 22:33:23 +0900
- strftime # strftime( string ) → string
    - Time.now().strftime("it's %Y/%m/%d %H:%M:%S %W || %y %B %b %I %p || %j days past, %W weeks past || %Z || %%")
    - # => it's 2015/10/12 22:46:02 41 || 15 October Oct 10 PM || 285 days past, 41 weeks past || JST || %
- hour # => fixnum
- min # => fixnum
- sec # => fixnum
- year # => fixnum
- month | mon # => fixnum
- day | mday # Time.now.day  => 12
- yday # => fixnum  1/1を1とした通算日
- isdst | dst? # 夏時間？
- zone # タイムゾーン
```

## Fileクラス

```.ruby
- basename(file_name [, suffix] ) # → base_name
   - File.basename("/home/ruby.rb")          
   - #=> "ruby.rb"
   - File.basename("/home/ruby.rb", ".rb")   
   - #=> "ruby"
- dirname(file_name) # → dir_name
    - File.dirname("/home/gumby/work/ruby.rb")   
    - #=> "/home/gumby/work"
- extname(path) # → string (拡張子を返す)
    - File.extname("a/b/d/test.rb")   
    - #=> ".rb"
- split(file_name) # → array ["パス","ファイル名.拡張子"].size = 2
    -  File.split("/home/dev/ruby/ruby.rb") 
    -  #=> ["/home/dev/ruby", "ruby.rb"]
-  join(string, ...) # → path(文字列を接続してパスを作る)
    -  File.join("home","dev","ruby","ruby.rb")
    -  # => "home/dev/ruby/ruby.rb"
-  stat(file_name) # → stat(ファイル情報取得)
    -  File.stat("sample.rb").mtime
    -  #=> 2015-10-12 02:54:26 +0900
-  mtime(file_name) # → time(ファイル更新日時)
    -  File.mtime("sample.rb")
    -  # => 2015-10-12 02:54:26 +0900
-  rename(old_name, new_name) # → 0 ファイル名変更orファイル移動
    -  File.rename("sample.rb","re_sample.rb")
    -  # => 0 (ファイルがない場合は例外)
-  File.open
    -  読み出し r
    -  書き込み w
    -  追記 a
    -  読み書き r+ , w+
    -  読み書き追記 a+
-  gets | readline # 一行読む
-  read # 
-  readlines # 全ての行を一度に読み込み、配列へ格納して返却
```


## Dirクラス

```.ruby
- Dir.glob # Dir[]と同じ
    - glob( pattern, [flags] ) → matches # マッチしたファイル名を配列で返す("."で始まる文字の検索はFILE::FNM_DOTMATCH)
        - Dir.glob("*[s]*.{rb,?ql}",File::FNM_DOTMATCH)
        - # => ["sample.rb", "noun_list.sql"]
    - glob( pattern, [flags] ) { |filename| block } → nil # 配列に対してブロック処理
        - Dir.glob("./*"){|x| puts x}
        - # => ./converter.rb
        - # => ./sample.rb
- Dir.open # ディレクトリストリームを開く
    - Dir.open('.').each{|f| p f }
    - Dir.open("/Users/naoki/dev/ruby"){|d| d.each{|f| p f }}
- Dir.read
    - d = Dir.open("/Users/naoki/dev/ruby") 
    - d.read # => "."
    - d.read # => ".."
    - d.read # => "converter.rb"
    - d.read # => "noun_list.sql"
    - d.read # => nil
- Dir.each #インスタンスメソッド
    - Dir.open("./").each{|f| p f}
- Dir.foreach #クラス・メソッド
    - Dir.foreach('.'){|f| p f}
- Dir.mkdir
- Dir.rmdir
- Dir.chdir("../") # 移動
- Dir.pwd # linuxのpwd
```