【Ruby】ドットインストールRuby入門編の内容まとめ【プログラミング学習75日目】

# はじめに
初心者が学びの内容を言語化することで、学習の中で得た知識やスキルを深化させることを目的としている記事です。

# 現在の学習状況
完全未経験者がプログラミングの勉強を始めて75日が経過しました。
現在までの学習状況は以下の通りです。

・Progate(有料版)→HTML/CSS, JavaScript, jQuery, Ruby, Ruby on Rails
・ドットインストール(無料版)→HTML/CSS, JavaScript, jQuery, Ruby
・JavaScript教材（確かな力が身につくJavaScript「超」入門 ）→ 読了
・ポートフォリオ→飲食店の検索・情報共有用のSNSを制作中
・AWS登録、セキュリティ関係の初期設定
・Rubyの開発環境構築（Windows）

この1週間でRubyの開発環境構築およびドットインストールRuby入門編の各章のまとめを行ったため、備忘録として記録していきます。

# Rubyの開発環境構築（Windows）
詳細は下記リンクにメモあり。

[【Ruby／Ruby on Rails】Ruby開発環境構築の流れ for Windows](https://fukutech.qrunch.io/logs/tWUMqVJbLd7tbrWn)

# ドットインストール・Ruby入門の内容
各章について要点をまとめたため記載していきます。

## #01 Rubyを使ってみよう 
〇Ruby、便利コマンド 
・irb ： ちょっと何かを試したい時使える
・ri  ： 知りたい命令、オブジェクトのドキュメントを見ることができる
・exit： 処理終了
・↑   ： 入力履歴

## #02 はじめてのRubyプログラム
〇Rubyの実行
・コマンドにて「ruby ファイル名」とする

〇print, puts, p の違い
`print "hello world" → 改行なし`
`puts "hello world" → 改行が付く`
`p "hello world" → デバッグ用`

##  #03 変数､定数を使ってみよう
・変数：小文字とアンダーバー（_）を使用する
・定数：プログラム中で値を変えて欲しくないもの → 慣習的に全部大文字

##  #04 オブジェクトを理解しよう
・Objects：便利な命令を色々持っている色んなデータ型

①String Class
・Instance： "hello world"
・Method　： .length、.reverse

②Float Class
・Instance： 1.1
・Method： .round、.floorなど

##  #05 数値オブジェクトを使おう
〇オブジェクトがどのクラスに属していてどんなメソッドが使えるか
`p 4.8.class`
`p 4.8.methods`

〇小数点を含めた計算
・10.0 / 3など片方を小数点まで含めればよい

〇分数の計算：例、2/5 + 2/5
①Rational(2, 5) + Rational(2, 5)
②2/5r + 2/5r （省略形）

〇小数点の取り扱い
・四捨五入：.round
・切り捨て：.floor
・切り上げ：.ceil

## #06 文字列オブジェクトを使おう
〇シングルクォーテーション、ダブルクォーテーションの違い
・ダブルクォーテーションは特殊文字、式展開ができる

〇特殊文字の例
・\n：改行
・\t：タブ
`(例) puts "hell\no worl\td"`

〇文字の連結
`puts "hello world" + "world" => 連結されて hello world world となる`
`puts "hello " * 10 => 「"文字列" * 数字X」でその文字をX回繰り返しの意味`

## #07 ?や!がついたメソッドを使おう
〇! について
・upcase ：文字列を大文字にする
・upcase!：文字列を大文字にする＆元の文字列も大文字に書き換える（破壊的なメソッド）

〇? について
・真偽値（true/false）を返す

## #08 配列オブジェクトを使おう
```ruby:配列について
colors = ["red", "blue", "yellow"]

p colors[0]      # [0]：添字
p colors[-1]     # [-1]：末尾、[-2]：末尾の1つ前
p colors[0..2]   # 0～2まで
p colors[0...2]  # 2の直前まで
p colors[5]      # 範囲外：nil

# 要素の書き換え・追記
colors[0] = "pink"
colors[1..2] = ["white", "black"]  # 要素の一挙書き換え
colors.push("gold")  # 要素の追加
colors << "silver"  # .pushの簡略版
p colors

p colors.size  # 要素の数
p colors.sort  # 並び替え
```

## #09 ハッシュオブジェクトを使おう
```ruby:ハッシュオブジェクトについて
# ハッシュ、3種類の書き方
scores = {"taguchi" => 200, "fkoji" => 400}
scores = {:taguchi => 200, :fkoji => 400}  # シンボルオブジェクト、動作が高速
scores = {taguchi: 200, fkoji: 400}

# 値の取り出し方、書き換え方
p scores[:taguchi]
scores[:fkoji] = 600
p scores

# 便利なメソッド
p scores.size  # 要素の数
p scores.keys  # キーの一覧
p scores.values  # 値の一覧
p scores.has_key?(:taguchi)  # そのキーがあるかどうか
```
## #10 オブジェクトを変換してみよう
```ruby:オブジェクトの変換
# 文字列<->数値の変換
x = 50  # 数値
y = "3"  # 文字列

p x + y.to_i  # 整数に変換、to integer
p x + y.to_f  # 小数点に変換、to float
p x.to_s + y  # 文字列に変換、to string

# 配列<->ハッシュの変換
scores = {taguchi: 200, fkoji: 400}

p scores.to_a  # 配列で表現、to array
p scores.to_a.to_h  # ハッシュに戻す、to hash
```

## #11 %記法を使ってみよう
・%記法："や'が文字列中に入ってくるときは%記法の方が便利

```ruby:%記法
puts "hello"
puts 'hello'
puts %Q(hello)  # %Qとするとダブルクォーテーションに対応
puts %(hello)  # Q省略してもOK
puts %q(hello)  # %qとするとシングルクォーテーションに対応

# 配列で文字列を管理したい場合
p ["red", "blue"]
p ['red', 'blue']

p %W(red, blue)  # %Wとするとダブルクォーテーションに対応
p %w(red, blue)  # %wとするとシングルクォーテーションに対応
```
## #12 書式付きで値を埋め込もう
```ruby:書式付きで値を埋め込む方法
# "文字列" %　値 について（書式付きで値を埋め込む方法）
# -> %ｓ：文字列
# -> %ｄ：整数
# -> %ｆ：小数点

p "name: %s" % "taguchi"  
p "name: %10s" % "taguchi"  # 10桁分の幅を確保
p "name: %-10s" % "taguchi"  # 10桁分の幅を確保しつつ左寄せ

# idは整数、rateは少数で表示したい場合
p "id: %d, rate: %f" % [355, 3.284]

# idは整数、ただし全体の文字数が5文字で5桁に満たない場合は0を付けて表記したい場合
# rateは少数、ただし全体の文字数が10文字、そのうち小数点以下が2文字で表記したい場合
p "id: %05d, rate: %10.2f" % [355, 3.284]

# printf:書式付きで文字列を表示するための命令
printf("name: %10s\n", "taguchi")
printf("id: %05d, rate: %10.2f\n", 355, 3.284)

# sprintf：文字列を返す、sprintf(～) = puts printf(～)
p sprintf("name: %10s\n", "taguchi")
p sprintf("id: %05d, rate: %10.2f\n", 355, 3.284)
```

## #13 ifで条件分岐をしてみよう

```ruby:if文、比較演算子、論理演算子 
score = gets.to_i  # getsで数値を受け取れる、ただし文字列なのでto_iで数値に変換する
if score > 80 then  # thenは省略可能
  puts "great!"
elsif score > 60 then  # thenは省略可能
  puts "good!"
else
  puts "so so..."
end

# ちなみに、if文こういう書き方もある
puts "great!" if score > 80
```
##  #14 caseで条件分岐をしてみよう
・caseによる条件分岐
・case ... when ... else ... end 
・gets：ユーザーからの入力を取得、chomp：改行コードを取り除く
・gets.chompが実行されると、コンソールが入力待機状態になる。「変数 = gets.chomp」とすることで、エンターキーを押されるまでに入力された値を変数に代入することができる。

**＜case文の基本構文＞
変数を設定**

**case 変数
when 条件１ then
  処理１
when 条件２ then
  処理２
・・・
when 条件Ⅹ then
  処理Ⅹ
else
  処理１～処理Ⅹのどれにも当てはまらない時の処理
end**

```ruby:caseによる条件分岐
signal = gets.chomp

case signal
when "red" then  # thenは省略可能
  puts "stop!"
when "green", "blue"
  puts "go!"
when "yellow"
  puts "caution!"
else
  puts "wrong signal"
end
```

## #15 while､timesを使ってみよう

```ruby:繰り返し処理について①
# (1) while文
i = 0
while i < 10 do
  puts "#{i}: hello"
  i += 1
end

# (2) timesメソッド：回数が決まっている場合有効
10.times do |i|  # |i|は省略可能
  puts "#{i}: hello"
end

10.times { |i| puts "#{i}: hello" }  # という書き方もある
```
## #16 for､eachを使ってみよう
**＜for文の基本構文＞
for 変数/配列/ハッシュ in 変数 do
  ～
end**

**＜eachメソッドの基本構文＞
変数/配列/ハッシュ.each do |変数|
  ～
end**

```ruby:繰り返し処理について②
# (3) for文
for i in 15..20 do
  p i
end
# 出力結果 => 15, 16, 17, 18, 19, 20

for color in ["red", "blue"] do
  p color
end
# 出力結果 => "red", "blue"

for name, score in {taguchi:200, fkoji: 400} do
  puts "#{name}: #{score}"
end
# 出力結果 => taguchi:200, fkoji:400

# (4) eachメソッド
(15..20).each do |i|
  p i
end
# 出力結果 => 15, 16, 17, 18, 19, 20

["red", "blue"].each do |color|
  p color
end
# 出力結果 => "red", "blue"

{taguchi:200, fkoji: 400}.each do |name, score|
  puts "#{name}: #{score}"
end
# 出力結果 => taguchi:200, fkoji:400
```
## #17 loop､break､nextを使おう
```ruby:loopメソッド
# loopについて
i = 0
loop do  # コマンドctrl+Cでループ終了
  p i
  i += 1
end

# breakについて
i = 0
10.times do |i|
  if i == 7 then
    break  # break：指定部分で終了
  end
  p i
end
# 出力結果 => 0, 1, 2, 3, 4, 5, 6

# nextについて
i = 0
10.times do |i|
  if i == 7 then
    next  # next：指定部分を飛ばす
  end
  p i
end
# 出力結果 => 0, 1, 2, 3, 4, 5, 6, 8, 9
```

## #18 メソッドを作ってみよう
〇メソッド
・メソッドは最後に評価された値を返す
・返したい値はreturnで返すことが有効
・メソッド内で定義された変数には外からアクセスできない

**<基本構文>
def 関数名
  処理
end**

```ruby:メソッドについて
# 引数なしのパターン
def sayHi  
  puts "hi!"
end
sayHi
# 出力結果 => hi!

# 引数ありのパターン
def sayHi(name)
  puts "hi! #{name}"
end
sayHi("taguchi")  # 意味が曖昧にならない場合は()は省略可
# 出力結果 => hi! taguchi

# 引数にデフォルト値を設定するパターン
def sayHi(name = "tom")
  return "hi! #{name}"
end
puts sayHi  # 引数渡さなかったらデフォルト値のtomが渡される
# 出力結果 => hi! tom
```

## #19 クラスを作ってみよう
**<クラス作成の基本構文>
class クラス名(必ず大文字から始める)
  ・・・
end**

・クラスのオブジェクト＝インスタンス
・インスタンスの作り方 => 変数 = クラス名.new
・インスタンスは変数を使って値を保持できる => 「インスタンス変数」
・インスタンス作成時に引数を渡して「インスタンス変数」として値を保持させる

・initializeメソッド：newが作成されたときに呼ばれる特殊なメソッド
・インスタンス変数：変数名に＠を付ける
・インスタンス変数はインスタンス内であればどこからでもアクセス可能

・クラスで定義したメソッドをインスタンスに対して呼び出すには
「インスタンス変数.メソッド」とする

```ruby:
class User

  # initializeメソッド
  def initialize(name)
    @name = name
  end

  def sayHi
    puts "hi! i am #{@name}"
  end

end

tom = User.new("tom")  # インスタンス変数tom
tom.sayHi  # クラスで定義したメソッドをインスタンスに対して呼び出す
# 出力結果 => hi! i am tom
```
## #20 アクセサを使ってみよう
・インスタンス変数
=> インスタンス内ではどこからでもアクセス可能
=> 外部からはアクセスできないが、アクセスしたくなる時が多々ある
=> アクセスするにはアクセス用の新たなメソッドの定義が必要だが、簡単な文法を用意してくれている
=> attr_accessor：インスタンス変数にアクセスできる
=> 値を設定するメソッドをsetter、値を取得するメソッドをgettetと言う
（用語：getterだけ定義したい場合、accessor_readerとすればよい）

・self：そのメソッドを受け取っているインスタンス自身を指す
・インスタンスメソッドの中では、特殊な変数「self」を用いて「self.変数名」とすることで、インスタンス変数を扱うことができる
（用語：メソッドを受け取っているオブジェクトのことを「レシーバー」と言う）

```ruby:attr_accessor、selfについて
class User

  # インスタンス外部からもnameにアクセスするためのおまじない
  attr_accessor :name
  # attr_reader :name

  def initialize(name)
    @name = name
  end

  def sayHi
    # self.name = @name
    # puts "hi! i am #{@name}"
    puts "hi! i am #{self.name}"  # selfは意味が曖昧にならない限り省略可
  end

end

tom = User.new("tom")
tom.sayHi
# 出力結果 => hi! i am tom

tom.name = "tom Jr."  # インスタンスの外部から書き換え
p tom.name  # 表示
# 出力結果 => "tom Jr."
```

##  #21 クラスメソッド､クラス変数を使おう
```ruby:クラスメソッド、クラス変数・定数
class User

  # 変数countでインスタンスを作った数を保持
  # クラス内ではどこでもアクセスできる変数
  @@count = 0  # クラス変数には@@を付けるルール

  VERSION = 1.1  # 定数

  def initialize(name)
    @@count += 1
    @name = name
  end

  def sayHi
    puts "hi! i am #{@name}"
  end

  def self.info
    puts "#{VERSION}: User Class, #{@@count} instances."
  end
end

tom = User.new("tom")
bob = User.new("bob")
steve = User.new("steve")
User.info
# 出力結果 => 1.1: User Class, 3 instances.
p User::VERSION  # クラス外から定数を呼び出す時は「::」を付けるのに注意
# 出力結果 => 1.1
```
## #22 クラスを継承してみよう
```ruby:クラスの継承
class User

  def initialize(name)
    @name = name
  end
  def sayHi
    puts "hi! i am #{@name}"
  end

end

# User：親クラス（Super Class）、AdminUser：子クラス（Sub Class）
class AdminUser < User  # クラスの継承

  def sayHello
    puts "Hello from #{@name}"
  end

  # メソッドのオーバーライド
  # 親クラスにあるメソッドを子クラス内で再度定義すると上書きされる
  def sayHi
    puts "hi! i am admin!"
  end

end

tom = AdminUser.new("tom")

# Userクラスを継承しているのでsayHiも使える
tom.sayHi
# 出力結果 => hi! i am admin!
tom.sayHello
# 出力結果 => Hello from tom
```

##  #23 メソッドのアクセス権を理解しよう
〇メソッドのアクセス権について

・public：通常のメソッドはデフォルトでpublic
・private：initializeとクラスの外に書いたメソッドは自動的にprivate、レシーバーを指定できない
・protected：特殊なシーンでしか使用されない、今回は割愛

・privateキーワードの後に定義したメソッドはレシーバーを指定できない
・クラスの外から呼び出すことはできない
・クラスの中から呼び出すことは可能、呼び出すときは「self」は付けない

・親クラスで定義したら子クラスにも継承される、また、オーバーライドも可能

```ruby:メソッドのアクセス権
class User

  def sayHi
    puts "hi!"
    sayPrivate  # 意味的にはself.sayPrivateだが、レシーバー指定できないのでselfは付けない
  end

  private  # privateキーワード、指定するとレシーバーを指定できない

    def sayPrivate  # privateキーワードの後に書いたメソッドはレシーバーを指定できない
      puts "private"
    end

end

class AdminUser < User  # クラスの継承

  def sayHello
    puts "Hello!"
  sayPrivate
  end

end
# User.new.sayPrivate ・・・レシーバーを指定できないのでNG!

User.new.sayHi
=begin
出力結果 => hi!
           private
=end

AdminUser.new.sayHello  # 子クラスからも呼び出せる
=begin
出力結果 => Hello!
           private
=end
```
## #24 モジュールで名前空間を作ろう

・module：主な用途は2つ → ①名前空間
・クラスのようにメソッドや定数をまとめられる
・インスタンスを作ったり継承したりできないという違いあり
・関連するメソッドや定数をモジュールでまとめてグループ化すると便利

例えば、
def movie_...
end
のように、「movie」は共通してメソッドを定義していきたい場合、他のメソッド名と衝突しないか心配
=> 自分だけの名前空間を作ってあげると便利

**<モジュール作成の基本構文>
module クラス名(必ず大文字から始める)
・・・
end**


```ruby:module、名前空間

module Movie  # module名の1文字目は必ず大文字

  VERSION = 1.1
	
  def self.encode
    puts "encoding..."
  end

  def self.export
    puts "exporting..."
  end
	
end

Movie.encode
Movie.export
p Movie::VERSION
```
##  #25 ミックスインを使ってみよう

・module：主な用途は2つ → ②ミックスイン
・継承関係のない複数のクラスに共通のDebugメソッドを書きたい時、モジュールを作って各クラスに提供することで記述が簡便になる

```ruby:module、ミックスイン
# （例）PlayerクラスとMonsterクラスにinfoメソッドを提供
module Debug

  def info
    puts "#{self.class} debug info..."　　# self.classで呼び出したクラス名を取得
  end
	
end

class Player
  include Debug  # includeというキーワードを使用することでミックスイン可能
end

class Monster
  include Debug  # includeというキーワードを使用することでミックスイン可能
end

Player.new.info
# 出力結果 => Player debug info...

Monster.new.info
# 出力結果 => Monster debug info...
```

##  #26 例外を扱ってみよう

〇例外の扱い方について
・何らかの処理をしていて予期せぬ結果が出た時に適切に処理していく方法
・begin ... rescue ... ensure ... endを使う
　① 例外が発生しそうな処理をbegin～endで囲う
　② 例外が発生した場合の処理をrescueの後に記述していく
　③ 例外の有無に関わらず、最後に必ず実行したい内容はensure中に記述する

```ruby:例外の取り扱いについて
x = gets.to_i

begin
  p 100 / x
rescue => ex
  p ex.message
  p ex.class
  puts "stoped!"
ensure
  puts "--- END ---"
end
```

〇例外クラスの作成
・Rubyの標準的な例外クラスであるStandardErrorを継承したクラスを作成する
・begin中にraiseというキーワードを使用
・「rescue 例外クラス」を用意し、そこに自作したい処理を記述

```ruby:例外クラスの自作方法
class MyError < StandardError; end  # (豆知識)中身がいらない場合は1行で書ける

x = gets.to_i

begin
  if x == 3
    raise MyError  # raiseというキーワードを使用
  end
  p 100 / x
rescue MyError  # 例外クラスを用意、ここに自作したい処理内容を記述
  puts "not 3!"
rescue ex
  p ex.message
  p ex.class
ensure
  puts "--- END ---"
end
```

# まとめ、所感
- Rubyの開発環境構築およびドットインストールRuby入門編の学習を実施した。
- Ruby入門編の各章の内容をまとめ、備忘録として記録した。
- 以前Progateで学んだ基礎の復習ができただけでなく、#23～#26の学習内容はProgateにはなかった内容だったため、新たな知識を習得することができた。