【個人学習振り返り】Ruby勉強#1

#この記事の目的
自分の振り返り用としての投稿です。
Sierから卒業しWebエンジニアになるため、Rubyを１から習得中です。

#■勉強に利用させていただいた動画
大変勉強になりました。投稿者様に感謝です。
本ページはこちらを参考に手でやった記録になります。

https://www.youtube.com/watch?v=8NI57SrDiVw&t=1074s

#■テスト環境web
paiza io 
(https://paiza.io/ja)

#標準出力に出すコマンドはRubyではp
```
p "hello world!"
p "1"+"1"
p 1+1
```
#■変数
変数名＝値
ここはほかの言語と同じ

####数値の代入
```
a = 1
b = 2

p a
p b

p a + b
```
→以下が返ってくる。
1
2
3

####文字列の代入
```
a1="ruby"
a2="on"
a3="rails"

p a1+a2+a3
```
　→rubyonrailsが返ってくる

####文字と数字の結合

\#{変数名}を使う

```
p "今日は#{a1}の勉強#{a}回目です"
```

　→"今日はrubyの勉強1回目です"

#■比較

####true
```
p 1==1
```

####false
```
p 1==2
```

その他の言語と同じで、以下が使える。
\>
<
\>=
<=
!=

##条件式
if 条件式

elsif

else

end

例）

```
score=80

if score >= 80
   p "1"
elsif score >= 70
   p "2"
else
   p"3"
end
```

###条件組み合わせ
####and
```
　1 <= i && 1 < 10
```
####or
```
　1 <= i || 1 < 10
```

#■配列
####空の配列 

```
[]
```

####文字列の配列
配列は[]ブラケット記号

["ruby","on","rails"]

```
arr = ["ruby","on","rails"]

p arr[0]
p arr[1]
p arr[2]
```
####nilとは
rubyでは存在しない値は、「null」ではなく「nil」となる

#■ハッシュ
配列な好きなキー名をつけること。
ハッシュで使う名前のことをkeyという。
ハッシュでは[]ではなくて、｛｝を用いる。

キー >= 値

```
arr={"udon" => "ruby","soba" => "on" , "yakisoba" => "rails"}

p arr["udon"]
p arr["soba"]
p arr["yakisoba"]
```
→以下が返ってくる。
"ruby"
"on"
"rails"

####シンボル
文字列を省略した書き方
ハッシュのキー以外ではあまり使わないかも？
ここは自分の環境ではうまくいかず、全部nilになってしまった。

```
arr={:udon => "ruby",:soba => "on" , :yakisoba => "rails"}

p arr["udon"]
p arr["soba"]
p arr["yakisoba"]
```

さらに　=>も省略して
キー：値
とすることも可能

```
arr={udon:"ruby",soba:"on" , yakisoba:"rails"}

p arr["key1"]
p arr["keyex"]
p arr["key3"]
```

#■ループ処理
構文は
配列名.each do |変数名|
\#ループ処理
end

変数名に一要素ずつ取り出されて処理される。

```
arr=["ruby","on" , "rails"]
arr.each do |lang|
p lang
end
```

→以下が返ってくる。
"ruby"
"on"
"rails"

####ハッシュのループ処理
構文は
配列名.each do |変数名(キー名用),変数名(値用)|
\#ループ処理
end

```
arr={"udon" => "ruby","soba" => "on" , "yakisoba" => "rails"}

arr.each do |key,val|
p "#{key}と#{val}の組み合わせです"
end
```

→以下の結果が返ってくる
"udonとrubyの組み合わせです"
"sobaとonの組み合わせです"
"yakisobaとrailsの組み合わせです"

####ループ処理のスキップ

nextコマンドを使うことで実現する。
これに該当する処理はスキップされる。
以下の例だとudonがスキップされる。


```
arr={"udon" => "ruby","soba" => "on" , "yakisoba" => "rails"}

arr.each do |key,val|
next if key=="udon"
p "#{key}と#{val}の組み合わせです"
end
```
⇒以下の結果が返ってくる
"sobaとonの組み合わせです"
"yakisobaとrailsの組み合わせです"

#■メソッド

【定義】
def メソッド名(引数)
処理部分
end

【呼び出し】
メソッド名(引数)

```
def method1(arg1)
p "#{arg1}です"
end

method1("RUBY")
```

⇒以下が結果として戻ってくる
"RUBYです"

####引数が二つの場合
```
def method2(arg1,arg2)
p "#{arg1}と#{arg2}です"
end

method2("RUBY","on")
```
⇒以下が結果として戻ってくる
"RUBYとonです"

####引数のデフォルト値
```
def method3(arg1="引数１",arg2="引数２")
p "#{arg1}と#{arg2}です"
end

method3()
method3(nil,"on")
method3("RUBY","on")
```

####キーワード引数
引数に名前を付ける機能。

```
def method4(score: 100)
p "#{score}です"
end

method4()
method4(score: 90)
```
→結果は以下の通り。
"100です"
"90です"

####可変長引数
一つの引数で複数の値を配列で受け取る
method側で()内に＊を追加して機能させる。

```
def method5(*i)
p "#{i}です"
end

method5(1,2,3)
```
→以下の結果となる。
"[1, 2, 3]です"


####オプション引数
一つの引数で複数の値をハッシュで受け取る。


```
def method6(**i)
p i
end

method6(item1:100,item2:200)
```

→以下の結果となる。
{:item1=>100, :item2=>200}
あってるかな？

####return処理
returnが実行されるとその段階でメソッドが強制終了になる。
呼び出し元に戻り値を返す。

ただreturnを書かない場合は、最後に処理した値が暗黙的に戻り値になる。

```
def method7(age)

    if age >= 20
      return "大人料金"
    else 
      return
    end
end

age_score=method7(19)
p age_score
```
→以下の結果となる。
20を引数とした場合、大人料金がプリントされる。
19とした場合は、nilが返る。

暗黙的な戻り値版(returnを用いない)

```
def method8(age)

    if age >= 20
      "大人料金"
    else 
      "子供料金"
    end
end

p method8(19)
```

#unless文
ifの逆。falseの場合のみ実行される。


```
def method9(age)

    unless age >= 20
      "子供料金"
    end
end

p method9(19)
```

#■例外処理
想定外のエラーのこと。
fail()またはraise()で発生させる。

```
def method10(age)
    fail("数値を指定してください") unless age.instance_of?(Integer)
    age*1.1
end

p method10(19)
p method10("a")
```

以下の結果となる。
Main.rb:2:in `method10': 数値を指定してください (RuntimeError)
	from Main.rb:8:in `<main>'

最初の(19)も処理されていない？

####例外をキャッチする
「begin」「fail」「raise」「rescue」 「ensure」を使用する。

begin：例外処理の開始
fail:例外の発生させるために記載。
raise:failと意味は同じ。failで出たものをさらに外に出すとき、区別する用意しようする
rescue：例外発生時の処理を記載。
ensure:例外の発生有無によらず、実行する処理を記載。

```
def method11(age)
    fail("数値を指定してください") unless age.instance_of?(Integer)
    age*1.1
end

begin
　p method11(19)
　p method11("a")
rescue => e
　p e.message
　p e.backtrace
end

p method11(2)
```

以下の結果となる。
３つのmethod11の呼び出しがそれぞれできている。

20.900000000000002
"数値を指定してください"
["Main.rb:2:in `method11'", "Main.rb:8:in `<main>'"]
2.2

以下はraise組み込み版。
一番下のmethod12も実行されなくなる。
例外が出たら即終了させたいときに使うのかな？

```
def method12(age)
    fail("数値を指定してください") unless age.instance_of?(Integer)
    age*1.1
end

begin
    p method12(19)
    p method12("a")
rescue => e
    p e.message
    p e.backtrace
    raise e
end

p method12(2)
```

以下はensureを組み込み版。
raiseを入れると処理が終わってしまうので、これとは併用できない。

```
def method13(age)
    fail("数値を指定してください") unless age.instance_of?(Integer)
    age*1.1
end

begin
    p method13(20)
    p method13("a")
rescue => e
    p e.message
    p e.backtrace
ensure
    p "これだけは実行された。"
end

p method13(30)
```

####rescueにパターンを持たせる
特定のエラー名を指定してキャッチすることができる。

```
def method14(i)
    fail("数値を指定してください") unless i.instance_of?(Integer)
    1/i
end

begin
p method14(0)

rescue ZeroDivisionError => e
    p "ゼロによる除算はだめ"
rescue => e
    p e.message
end
```

####メソッド内に例外処理を持たせる。
```
def method15(i)
    1/i
rescue => e
    p e.message
end
p method15(0)
```
→以下の結果になった。
"divided by 0"
"divided by 0"

#クラス
変数やメソッドをまとめておくことができる。
変数の前に@をつけることでクラスの中のどこからでも参照できるようになる。

####クラス関連の用語
@付き変数のことを、属性orメンバ変数と呼ぶそう。
インスタンス化は、猫を一匹つくることとと覚える。
コンストラクタ：クラスを初期化するメソッドのことで、Rubyの場合は、これがinitialize()で行われている
　　　　　　　　似た単語をJavaで聞いたかも。

多分同じオブジェクト指向言語・・かなり混乱中。

１）クラスで猫がどんなものかを定義
２）class名.new(クラスが要求する初期値)をすることで、クラスCatのinitializeメソッドが呼び出される。
３）これにより、一匹の猫を産み出せる。
　　cat1とcat2は別々の猫でそれぞれの歴史があり、相互に影響はしない。
　　(メソッドで呼び出せるものはcat1とcat2で同じだが、メンバ変数の内容がそれぞれ独立しているイメージ。
　　猫が2匹いるイメージと考えるとわかりやすいか)

```
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

#インスタンスの作成
cat1=Cat.new("一郎",5)
cat2=Cat.new("次郎",8)
    
cat1.eat("魚")
cat2.eat("魚")
cat1.eat("魚")

cat2.cry()
```
→以下の結果となった。
"体重:6KG"
"体重:9KG"
"体重:7KG"
"私は次郎だにゃん！"

####クラス内外からの属性の読み書きを許す
attr_accessorを使うと、クラスの中でinitializeを書く必要がなくなる。
ただプログラム設計上、initializeで定義したほうが安心なよう。

```
class Cat
    attr_accessor :name,:weight

    def cry
    p "私は#{@name}だにゃん！"
    end
end

#インスタンスの作成
cat1=Cat.new
cat1.name="一郎"
cat1.weight=5

p cat1.name
p cat1.weight
cat1.cry()
```

####クラスの定数

```
class Cat
    ANIMAL="猫"
    MY_LEGS=4

    def leg_count
    "#{ANIMAL}は#{MY_LEGS}本足です。"
    end
end

#インスタンスの作成
cat1=Cat.new
p cat1.leg_count
#クラス定数の参照方法
p Cat::MY_LEGS
```

####staticメソッド
属性(メンバ変数)を必要としない、つまりどのインスタンスから読んでも同じになるような処理
そういった属性は、self.メソッド名でクラス内に定義する。
この情報はインスタンス化していなくても呼び出せる。

```
class Cat
    def initialize(name,weight)
    @name = name
    @weight = weight
    end

    def self.jump(height)
    p "#{height}m、ジャンプします"
    end

    def cry
    p "私は#{@name}だにゃん！"
    end
end

#呼び出し
Cat.jump(5)
```
→以下の結果となった。
"5m、ジャンプします"

一定の範囲staticメソッドとして扱いたい場合は、
class << self
メソッド定義
end

でこの間のものを一括で定義できる。
selfとわざわざ書く必要なし。

```
class Cat
    class << self
        def method1
        end

        class << self
        def method2
        end
    end

    def cry
    p "私は#{@name}だにゃん！"
    end
end

#呼び出し
Cat.jump(5)
```

#継承について
共通する部分を抜き出してクラスを作成し、それを小さなクラスに割り当てることを継承という。
イメージとしては、動物→犬・猫といった具合
犬と猫は動物の全要素を使用できる。

この場合、動物は親クラス
犬猫は子クラス

```
#継承元
class Animal
    def initialize(name,weight)
        @name = name
        @weight = weight
    end

    def eat(food)
        @weight+=1
        p "体重:#{@weight}kg"
    end
end

#継承先
class Cat < Animal
    def cry
    p "私は#{@name}だにゃん！"
    end
end

class Dog < Animal
    def cry
    p "私は#{@name}だわん"
    end
end

dog1=Dog.new("犬",5)
cat1=Cat.new("猫",2)

dog1.eat("tori")
cat1.eat("fugu")
```

#継承のオーバーライド
親クラスから継承したメソッドを子クラスで同名メソッドで定義をすると
子クラス側が優先され、親クラスは無視される。
以下の更新を行うと、eatメソッドが猫のみ2kgペースで増える。
子クラスで上書きしても、親クラスへの影響はなし。

```
#継承元
class Animal
    def initialize(name,weight)
        @name = name
        @weight = weight
    end

    def eat(food)
        @weight+=1
        p "体重:#{@weight}kg"
    end
end

#継承先
class Cat < Animal

    def eat(food)
        @weight+=2
        p "体重:#{@weight}kg"
    end

    def cry
    p "私は#{@name}だにゃん！"
    end
end

class Dog < Animal
    def cry
    p "私は#{@name}だわん"
    end
end

#呼び出し
dog1=Dog.new("犬",5)
cat1=Cat.new("猫",2)

dog1.eat("tori")
cat1.eat("fugu")
```
→以下の結果となる。
"体重:6kg"
"体重:4kg"

#■モジュール
クラスの一部分を切り出したもの。あまり理解できていない。
人と動物という継承関係にないものでも、同じメソッドを持たせたいときに使うらしい。

クラスと同じような感じで、module　として定義し、
使う側ではinclude文で読み込む。

```
#継承元
module Eat
    attr_accessor :weight

    def eat
        @weight+=1
        p "体重:#{@weight}kg"
    end
end

#継承先
class ANIMAL
    include Eat
end

class HUMAN
    include Eat
end

#呼び出し
human=HUMAN.new
human.weight=20
human.eat

```

#■総括
一時間の動画をこなすのに半日以上かかってしまいました。
次はRuby on railsでより実践的にやりたいです。