Rubyの記述ルール（個人メモ）

## はじめに
これまでの個人アプリ開発ではJavaScript、TypeScript、Pythonなどを使ってきました。今回初めてRubyを使うため学習を始めました。
Ruby開発者としての一歩として、Ruby独自の記述ルールやクラスの定義の仕方を理解しようと思い、個人メモを作成することにしました。もし誤り等がありましたら、ご指摘いただけると幸いです。

## null値
Rubyではnull値の場合、「nil」（ニル）と表示されます。

## ハッシュ
JavaScriptでいうところのオブジェクトと同じで、キーとバリューのペアで格納し、キーを指定してバリューを取得するデータ構造です。
また、キーは文字列で指定する方法とシンボルで指定する方法があります。

### 構文
```ruby
ハッシュ名 = {"key" => value, ... }
# または
ハッシュ名 = {:key => value,  ... }
```

【**キーの指定方法**】
- **文字列** "key名"（ダブルクオーテーション）
- **シンボル** :key名（コロン）

### 具体例
```Ruby
# 配列
arr = ["ダイヤ","オパール","サファイヤ"]
p arr[0] # ダイヤ

# ハッシュ(キーを文字列で指定)
arr = {"key1" => "ダイヤ", "key2" => "オパール", "key3" => "サファイヤ"}
p arr["key1"] # ダイヤ

# ハッシュ(キーをシンボルで指定)
arr = {:key1 => "ダイヤ", :key2 => "オパール", :key3 => "サファイヤ"}
p arr[:key1] # ダイヤ

# ハッシュ(キーをシンボル(省略形)で指定)
arr = {key1: "ダイヤ", key2: "オパール", key3: "サファイヤ"}
p arr[:key1] # ダイヤ
```

## 配列のループ処理
### 構文
```Ruby
配列.each do |変数名|
    # ループ処理
end
```

### 具体例
```Ruby
arr = ["ダイヤ","オパール","サファイヤ"]
arr.each do |jewel|
    p jewel
end

# ＝＝出力＝＝
# ダイヤ
# オパール
# サファイヤ
```

## ハッシュのループ処理
### 構文
```Ruby
ハッシュ.each do |key, val|
    # ループ処理
end
```

### 具体例
```Ruby
arr = {:key1 => "ダイヤ", :key2 => "オパール", :key3 => "サファイヤ"}
arr.each do |key, jewel|
    p "#{key}は#{jewel}です"
end

# ＝＝出力＝＝
# key1はダイヤです
# key2はオパールです
# key3はサファイヤです
```

## メソッド（関数）
下記のように、引数を持たないメソッドは()が不要
### 具体例
```Ruby 
# ask()とは書かない
def ask
    p "質問はコメント欄へ"
end
```

### 可変長引数（１つの引数で複数の値を配列で受け取る）
```Ruby 
def num(*i)
    p i  # [1,2,3]
end

num(1,2,3)
```

### オプション引数（1つの引数で複数の値をハッシュで受け取る）
```Ruby 
def num(**i)
    p i  # {num1:Bob, num2:Emily}
end

num(num1:Bob, num2:Emily)
```

### 暗黙的な戻り値
Rubyは最後に処理した値を暗黙的に戻り値とする（returnの記述を省略できる）
```Ruby 
def calc(i)
    i + 2
end

p calc(1)  # 3が出力される
```
## 条件分岐
Rubyでは、条件と処理の内容を一行で書くことができます。
例えば、18歳以上の場合は「大人料金」と出力する関数（メソッド）は以下の通りです。

### 具体例
```Ruby
def price(age)
    "大人料金" if age >= 18  # 条件がtrueの時に処理が実行される
end
```

## 例外処理
以下の二つを組み合わせて、想定外の入力がされた時の処理を記述する
- unless文（falseの時に実行される）：if文と逆
- fail()またはraise()：例外（exception）の発生
### 具体例
```Ruby
def calc_tax(i)
    fail("数値を指定してください") unless i.instance_of?(Integer)
    i * 1.1
end

p calc_tax("あ") # エラー発生 → 処理終了
p calc_tax(3) # 実行されない
```

### 例外処理が発生した場合も処理を継続する方法
```Ruby
def calc_tax(i)
    fail("数値を指定してください") unless i.instance_of?(Integer)
    i * 1.1
end

# beginの中で例外が発生するとbegin内の処理を中断してrescueへ移り引数eに例外内容が渡される
begin
    p calc_tax("あ") # 例外発生 → rescueへ
    p calc_tax(3) # 実行されない
rescue => e
    p e.message # エラーメッセージを表示
    p e.backtrace # エラーが発生した箇所を表示
ensure
    p "例外が発生するかどうかに関わらず必ず実行される処理"
end

p calc_tax(2) # この行は実行する
```

## クラス
### クラスの定義
```Ruby
class Cat
    # コンストラクタ
    def initialize(name, weight)
        @name = name　　　 # 属性（メンバ変数）
        @weight = weight  # 属性（メンバ変数）
    end

    def eat(food)
        @weight += 1
        p "体重：#{@weight}kg"
    end
    
    def cry
        p "#{@name}があなたを呼んでいます"
    end
end
```
### インスタンス生成
```Ruby
# インスタンスの作成
cat1 = Cat.new("ミー",5)
cat2 = Cat.new("たま",3)

cat1.eat("fish") # 体重：6kg
cat2.eat("fish") # 体重：4kg
cat1.eat("fish") # 体重：7kg
```

### attr_accessor (あまり使わない)
クラスの内外から属性の読み書きができる
```Ruby
# クラスの定義
class Cat
    attr_accessor :name, :weight

    def cry
        p "にゃあ"
    end
end

# インスタンスの生成
cat = Cat.new
cat.name = "ミー"
p cat.name  # ミー
```

### staticメソッド
属性を必要としないメソッド（インスタンスを作らなくても使えるメソッド）
```Ruby
class Cat
    # コンストラクタ
    def initialize(name, weight)
        @name = name　　　 # 属性（メンバ変数）
        @weight = weight  # 属性（メンバ変数）
    end

    def eat(food)
        @weight += 1
        p "体重：#{@weight}kg"
    end
    
    # staticメソッド
    def self.cry(food)
        p "#{food}が食べたいにゃあ"
    end
end

p Cat.cry("魚")  #魚が食べたいにゃあ
```

## 参考サイト
https://www.youtube.com/watch?v=8NI57SrDiVw

最後までお読みいただきまして、ありがとうございます。