Rubyの基本文法

# 概要

Railsの5.0系が正式リリースされて早3ヶ月が経過しました。
そろそろ触らないとまずいと思い、Rubyの復習からさくっとやりました。

(最近は、Pythonの事ばかり考えていたので、頭の整理もしたかった。)

内容に関しては、主要機能のみをさくっとまとめた感じです。


# ターミナル操作

- irb
	- Intaractive Ruby
	- ターミナルでインタラクティブにコマンドを確認できる。
- ri
	- ```ri Array```などで命令やオブジェクトのドキュメントを確認できる。


# 出力系の命令

- print
	- コンソール出力
- puts
	- 改行付きコンソール出力
- p
	- デバッグ用コンソール出力
- 行末のセミコロンは原則なし
- コメント
	- #
	- =begin~=end

# 変数と定数

- 変数
	- 英語小文字 or _(最初の文字)
	- ```msg = 'Hello'```
- 定数
	- 英語大文字(最初の文字)
	- 再代入しても、警告は出るが、値は変わってしまう。

# Rubyのオブジェクトの概念

## オブジェクトの理解

- 全ての値がオブジェクトである。
	- 'hello world'や1.1など
- オブジェクトとは何か
	- 便利な命令をたくさん持ったデータ型
		- ```'hello world'.length```
	- オブジェクトが用意している命令をメソッドと呼ぶ。
- どのメソッドが使えるかは、その値がどのオブジェクトに属しているかで変わる。
	- オブジェクトの種類の事をクラスと呼ぶ。
		- String Class
		- Float Class
	- Rubyではクラスを上手く使う事でいいプログラムが書ける。

- 1.1や'hello world'の様な実際の値をインスタンスと呼ぶ。

- オブジェクトは便利な命令をたくさん持ったデータ型
- インスタンスは、クラスから生成された実際の値。
	- 型を必ず持つ
	- 型 = クラス

# クラスの情報取得メソッド

- クラスの確認
	- ```<instance>.class```
- インスタンスが持つメソッドの確認
	- ```<instance>.methods```
- Fixnumクラス
- Floatクラス
	- ```<instance>.round```
	- ```<instance>.floor```
	- ```<instance>.ceil```

# 文字列オブジェクト

- ""
	- 特殊文字が使える
	- 式展開が可能
- ''
	- 特殊文字が使えない
	- 式展開が不可能
- #{}
	- 文字列中でRuby式が評価される。
- +
	- 文字列を連結できる。
- *
	- 文字列を繰り返す。

# 破壊的メソッドと真偽値メソッド

- !が付くメソッド
	- 破壊的メソッド
		- !なしは単純に値を返すだけ
		- !があるものは、値を返し、元の値も変更する。
		- ただし、感嘆符付きのメソッドが必ずしも破壊的とは限らない。
	- ```upcase!```or```upcase```
- ?が付くメソッド
	- 真偽値を返すメソッド
	- ```<instance>.empty?
	- ```<instance>.include?(<string>)



# 配列オブジェクト

```ruby
colors = [
  'red',
  'blue',
  'yellow'
]

p colors[0]     # "red"
p colors[-1]    # "yellow"
p colors[0..2]  # ["red", "blue", "yellow"]
p colors[0...2] # ["red", "blue"]
p colors[5]     # nil

colors[0] = 'pink'
colors[1..2] = ['white', 'black']
colors.push('gold')
colors << 'silver'

p colors # ["pink", "white", "black", "gold", "silver"]
p colors.size # 5
p colors.sort # ["black", "gold", "pink", "silver", "white"]

```

- 添え字の-値
	- -1で1番後ろの要素
	- -2で後ろから2番目の要素
- **添え字の範囲指定**
	- **..で添え字から添え字まで**
	- **...で添え字から添え字の1つ前の添え字まで**
- 要素がない添え字を指定
	- nilを返す
- 要素の書き換え
	- 添え字を指定して代入
- 要素の範囲指定入れ替え
	- 添え字を範囲で指定して、配列を代入
- 要素を末尾に追加
	- ```<instance>.push(<値>)```
	- ```<instance> << <値>```
- 配列の要素数を返す
	- ```<instance>.size```
- 配列の順序を並び替える
	- ```<instance>.sort```


# ハッシュオブジェクト

- 辞書型
- key & value

```ruby
# アローで表現する
scores = {
  "fujimoto" => 200,
  "horio" => 400
}

# シンボル & アローで表現する
scores = {
  :fujimoto => 200,
  :horio => 400
}

# シンボル & ショートハンドで表現する
scores = {
  fujimoto: 200,
  horio: 400
}

p scores[:fujimoto] # 200
scores[:horio] = 100

p scores # {:fujimoto=>200, :horio=>100}

p scores.size # 2
p scores.keys # [:fujimoto, :horio]
p scores.values # [200, 100]
p scores.has_key?(:fujimoto) # true
```

# シンボルオブジェクト

- 文字列の様なもの(識別子として利用する)
- **高速な識別子という認識**
	- ハッシュクラスを作成する際に利用する事が多い

	
# オブジェクトの変換

- ```<instance>.to_i```
	- 数値に変換(integer)
- ```<instance>.to_f```
	- 小数値に変換(float)
- ```<instance>.to_s```
	- 文字列に変換(string)
- ```<instance>.to_a```
	- 配列に変換(array)
	- オブジェクトを配列に変換できる
		- ```[[:fujimoto, 200], [:horio, 300]]```
- ```<instance>.to_h```
	- ハッシュに変換(hash)


# 便利な%記法

- % or %Q
	- 文字列を表現
	- ダブルクォーテーション
	- ```p %(hello) # "hello"```
- %q
	- 文字列を表現
	- シングルクォーテーション
	- ```p %q(hello) # 'hello'```
- %W
	- 配列を表現
		- スペース区切り
	- 式展開あり
	- ```p %W(red blue) # ["red", "blue"]```
- %w
	- 配列を表現
		- スペース区切り
	- 式展開なし
- %r
	- 正規表現を表現
- %s
	- シンボルを表現

- クォーテーションを書かなくてもよくなる。
- 文字列中でのクォーテションが見やすくなる。

# 書式付きで値を埋め込む

- %s
	- 文字列
- %d
	- 数値
- %f 小数値

```ruby
p "name: %s" % 'fujimoto' # "name: fujimoto"
p "id: %05d & rate: %5.2f" % [3, 83.2] # "id: 00003 & rate: 83.20"
```

- printf
	- 書式付き文字列をコンソールに表示する
	- ```printf("name: %s", "fujimoto")
- sprintf
	- 書式付き文字列を返す
	- ```p sprintf("name: %s", "fujimoto")


# 条件分岐

```ruby
puts "テストの点数を入力して下さい。"
score = gets.to_i

if score > 80 then
  puts "great!"
elsif score > 60 then
  puts "better"
else
  puts "soso!"
end
```

- gets
	- ターミナルでインタラクティブに入力を求める。
- 条件文のthenは省略可能
- 最後はendで終わる
- 論理演算子
	- &&(AND)
	- ||(OR)
	- !(NOT)

- 1行で書く

```ruby
p "great" if score >= 20
```

- 三項演算子で書く

```ruby
puts score > 50 ? 'OK' : 'NG'
```


# caseの条件分岐

```ruby
signal = gets.chomp

case signal
  when 'red'
    p 'stop'
  when 'green', "blue"
    p 'go'
  when 'yellow'
    p 'caution'
  else
    p 'wrong'
end
```

- case-when-else-endで記述する。
- ```<instance>.chomp```
	- 末尾の改行を削除する


# 制御構造での繰り返し

## while

```ruby
i = 0

while i < 10 do
  p "#{i}: hello"
  i += 1
end
```


## for

- 配列・ハッシュ・範囲オブジェクト分だけループを回す際に利用する。

```ruby
colors = [
  'red',
  'blue'
]

scores = {
  fujimoto: 200,
  horio: 300
}

for color in colors do
  p color
end

for name, score in scores do
  p "#{name}: #{score}"
end
```

- do-endの部分は{}で表現も可能
- doは省略可能。

# イテレータでの繰り返し

## each
    
- for文は内部的にeachが使われている為、書き換え可能。

```ruby
colors = [
  'red',
  'blue'
]

scores = {
  fujimoto: 200,
  horio: 300
}

colors.each do |color|
  p color
end

scores.each do |name, score|
  p "#{name}: #{score}"
end
```

- whileと同じ様に1行で表現する場合は、do-endを波かっこで表現も可能。
- doの省略は不可。

## times

- 回数が決まっている際に利用する。
- 数字クラスのメソッド

```ruby
10.times do |i|
  puts "#{i}: hello"
end

10.times { |i|
  puts "#{i}: hellohello}"
}
```

- doの後ろにブロックパラメーターを準備できる。
	- ```|i|```
- doは省略可能。

# 無限ループ

- ```loop do-end```

# 繰り返しで使える命令

- ループ終了
	- break
- ループスキップ
	- skip

# メソッド

- 本来はクラスに定義するもの
- グローバルに直接定義する事も可能
	- privateとなる。

```ruby
def sayHello
	p "hello"
end

sayHello # hello
```

- def-endで囲う
- ()で引数を渡す事も可能
	- =で初期化も可能
	- 実行側の()は省略可能。
- returnを使わなくても、最後の値を返す様になる。

# クラス

- クラスは大文字から始まる
- インスタンス化
	- ```tom = User.new```
- イニシャライズ
	- ```def initialize()-end```
- インスタンス変数
	- ```@variable```
	- クラス内部のどこからでも参照可能
	- メソッド内でのみ定義可能

# アクセサ

- インスタンス変数には直接アクセスできない
	- すべてprivate
- getter/setterの為のショートハンド
	- アクセサ
		- ```attr_accessor <Symbol>```
			- setterとgetterを作ってくれる
	- getterのみ定義
		- ```attr_reader <Symbol>```

- self
	- レシーバを指す
	- クラスメソッド内で利用可能
		- レシーバである事に注意。
			- attr_accessorやattr_readerを付与していれば呼び出せる
	- selfは曖昧な表現にならない限り省略可能である。

- レシーバ
	- メソッドを受け取っている(インスタンス)の事。

```ruby

class User

  attr_reader :name

  def initialize(name="noName")
    @name = name
  end

  def sayHi
    # @<var>でインスタンス変数にアクセス
    #   return "Hi, #{@name}"
    # selfでレシーバにアクセス
    # return "Hi, #{self.name}"
    # selfは曖昧にならない限り省略可能
    return "Hi, #{name}"
  end
end
```


# クラス変数・クラスメソッド・クラス定数

- クラス変数は@@で定義する
- クラスメソッドはメソッド名にselfをつける
	- ```Class.<methodName>で呼び出し可能
	- 関数名の先頭にselfをつけると、クラスメソッドの作成となる。
- クラス定数は全て大文字で宣言する
	- ```Class::<CONST>```で呼び出し可能

```ruby

class User

  attr_reader :name

  # クラス変数を定義する。
  # クラス変数は直接呼び出せない
  @@count = 0
  # 定数を宣言する。
  VERSION = 1.1

  def initialize(name="noName")
    @name = name
    # インスタンス化される度にクラス変数を1増加する。
    @@count += 1
  end

  def sayHi
    return "Hi, #{name}"
  end

  # クラスメソッドを定義する。
  def self.info
    p "hi, i am UserClass, #{@@count} Version: #{VERSION}"
  end
end

# クラスメソッドの呼び出し
User.info
# クラス定数の呼び出し
p User::VERSION
```

# クラスの継承

```ruby
class AdminUser < User
  def sayHello
    puts "Hello from #{name}"
  end
end

tom = AdminUser.new("TOM")

p tom.sayHi
tom.sayHello
```

- <で継承でできる
- オーバーライド可能


# メソッドのアクセス権

- 原則はpublic
- initializeとクラスの外に書いたメソッドはprivateになる。
- privateはクラスの中で定義して、クラスのメソッド内部で利用する。
	- privateメソッドはself指定なしで呼び出す。
		- privateメソッドはselfが使えない為
	- Rubyのprivateメソッドはオーバーライドが可能である。

```ruby

class User

  attr_reader :name

  def initialize(name="noName")
    @name = name
  end

  private def sayPrivate
    puts "private"
  end

  def sayHi
    sayPrivate
    p "Hi, #{@name}"
  end

end

class AdminUser < User
  def sayHello
    sayPrivate
    puts "Hello from #{name}"
  end
end

tom = User.new("TOM")
tom.sayHi
```


# モジュール

- 継承不可
- インスタンス不可
- 用途2つ
	- 名前空間を作成する。
	- MIX-INを提供する。
- モジュールの1文字目は大文字
- モジュール変数 = 定数
	- 普通の定数と同じ様に呼び出す。
- モジュール関数を作成できる
	- ```<ModuleName>.<method>```
	- ```def self.<method> - end```

```ruby

# module
# クラス・メソッドOK
# インスタンス化できない・継承できない
# 用途 -> 名前空間

module Movie

  VERSION = 1.1

  def self.encode
    puts "encoding"
  end

  def self.export
    puts "export"
  end
end

Movie.export
p Movie::VERSION
```


# Mix-In

- モジュールの2つ目の役割
- 用途の違うクラスに共通の機能を付与する
- インスタンスメソッドとして定義する。
	- 他のクラスのインスタンスに埋め込む事ができる。
- include命令を利用して、MIX-INを行う。

```ruby

# デバッグ機能を各クラスに追加したい

module Debug
  def info
    puts "#{self.class} debug info..."
  end
end

class Player
  include Debug
end

class Monster
  include Debug
end

player = Player.new

player.info

monaster = Monster.new

monaster.info
```


# 例外

- begin-rescue-endでtry-catch
- ensureで成功でもエラーでも行う処理を記述できる
- raiseで独自のエラークラスを引数に取り、エラーを発生させる事ができる。
	- 独自エラークラスは、StandardErrorクラスを継承する事

```ruby

class MyError < StandardError
end

x = gets.to_i

begin
  if x == 3
    raise MyError
  end
  p 100 / x
rescue MyError
  puts "this is myError"
rescue => ex
  p ex.message
  p ex.class
  p "stopeed"
ensure
  p "--end--"
end
```

# まとめ

やっぱりRubyの文法は好きです。
(GitHub社が好きな理由がよく分かる。)

次回はRails5.0で簡単アプリでも作りたいと思います。