今更ながら Ruby on Rails Tutorial をやってみた (その4)

## この記事について…

普段はRuby on Railsと無縁なプログラマなんですが、今更ながら**面白そう**という単純な理由から[**Ruby on Rails Tutorial**](https://railstutorial.jp/)をやってみようと思い立ちました。今回は[前回の記事](https://qiita.com/hideki0145/items/05c0571530db7e10fe1d)の続きで第4章をやっていきます。
尚、Rails 5.1に対応した第4版を用いて、かつVagrantを使用した環境で進めていきます。

## 第4章 Rails風味のRuby

この章では、Rails開発で必要なRubyの知識を学習していきます。自分は数年前C++のプロジェクトに所属していたこともあるので、オブジェクト指向スクリプト言語であるRubyを使用できるのがとても嬉しいです。
はじめに、irbの設定をコマンドプロンプト上で読みやすく書きやすいように更新します。

```ruby:~/.irbrc
IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.conf[:AUTO_INDENT_MODE] = false
```

さて、チュートリアル内に出てくるRuby記法の備忘録です。
C++経験者として「Rubyにはこんな記法があるのかー」と感じたものについて抜粋してお届けします。

```ruby:式展開という概念
# コメントは#から始まる VSCodeの場合は「ctrl+/」で選択行をコメントアウト可能
>> first_name = "Taro" # 変数代入
>> last_name = "Qiita"
>> "#{first_name} #{last_name}" # 式展開
=> "Taro Qiita"
>> first_name + " " + last_name # このように記述しても結果は一緒だが、上記の方がすっきり
```

```ruby:画面出力
>> puts "hoge" # 画面出力でよく使うのはputs
hoge # 出力に改行文字を含む
=> nil # nilは「何もない」ことを表す特別な値
>> print "hoge"
hoge=> nil # printは改行文字を含まない printで改行したい場合は\n付加

>> 'hoge' # Rubyは'で囲んで文字リテラルを表現しても"とほとんど同じ
=> "hoge"
>> '#{first_name}' # 違いは式展開を行わないこと
=> "\#{first_name}" # 実際の現場では、'と"のどちらを主に使用しているのでしょうか？
```

```ruby:Rubyはあらゆるものがオブジェクト
>> "hoge".length
=> 4
>> "hoge".empty? # Rubyはメソッド名に?とかが付いていることがあって直感で分かり易い
=> false

>> puts "not empty" if !s.empty? # s.empty?の否定
>> puts "not empty" unless s.empty? # 上記と同値 後続するif/unless文で式を実行するかどうか制御することができる
not empty
=> nil

>> 1.to_s # 1を文字列変換
=> "1"

# nilは前述したとおり特別で、オブジェクトそのものの論理値がfalseになるのはfalse自身とnilのみ
>> !!nil # !!を使用すると、すべてのオブジェクトを論理値に変換可能
=> false
>> !!0 # Rubyでは数字のゼロですら論理値はtrue
=> true
```

```ruby:メソッド
>> def method(arg = "") # デフォルト引数を定義している
?>   if arg.empty?
?>     "empty" # 暗黙の戻り値 returnで明示的に戻り値を指定することも可能
?>   else
?>     "nonempty" # 暗黙の戻り値
?>   end
?> end
=> :method
>> puts method("hoge")
nonempty
=> nil
```

```ruby:配列操作と範囲オブジェクトについて
# 配列に分割
>> "hoge fuga piyo".split # 文字列を3つの要素を持つ配列に分割する
=> ["hoge", "fuga", "piyo"]
>> "hogexfugaxpiyo".split("x") # 区切文字を指定することも可能
=> ["hoge", "fuga", "piyo"]

# 配列へのアクセス
>> a = [42, 8, 17]
>> a[0] # []で配列にアクセス
=> 42
>> a[-1] # 負数の添え字も受け付ける(すごい！)
=> 17
>> a.first # []以外にもアクセス方法は存在する
=> 42
>> a.second
=> 8
>> a.last # a[-1]と同値
=> 17

# 配列も色々なメソッドに応答する
>> a.empty?
=> false
>> a.include?(42)
=> true
>> a.sort
=> [8, 17, 42]
>> a.reverse
=> [17, 8, 42]
>> a.shuffle
=> [17, 42, 8] # ここまでのメソッドではa自身の内容は変わらない
>> a.sort! # 破壊的メソッドを使用するとa自身の内容が変わる !が付くことが多い
=> [8, 17, 42]
>> a
=> [8, 17, 42]

# 配列の追加
>> a.push(6)
=> [42, 8, 17, 6]
>> a << 7 # pushと<<は同等
=> [42, 8, 17, 6, 7]
>> a << "foo" << "bar" # 配列に連続して追加可能
=> [42, 8, 17, 6, 7, "foo", "bar"] # 異なる型が混在可能

# 連結する
>> a.join
=> "4281767foobar"
>> a.join(', ') # ", "を使用して連結する
=> "42, 8, 17, 6, 7, foo, bar"

# 範囲オブジェクトの概念
>> 0..9
=> 0..9
>> (0..9).to_a # 範囲オブジェクトを配列に変換
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>> a = %w[foo bar baz quux] # %wを使って文字列の配列に変換
=> ["foo", "bar", "baz", "quux"]
>> a[0..2]
=> ["foo", "bar", "baz"]
>> a = (0..9).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>> a[2..(a.length-1)] # 明示的に配列の長さを使って選択
=> [2, 3, 4, 5, 6, 7, 8, 9]
>> a[2..-1] # 添字に-1を使って選択(a[2..(a.length-1)]と同値)
=> [2, 3, 4, 5, 6, 7, 8, 9]
>> ('a'..'e').to_a # 文字列に対しても範囲オブジェクトは利用可能
=> ["a", "b", "c", "d", "e"] # 以上、配列については長くなってしまいました
```

```ruby:ブロック
>> (1..5).each { |i| puts 2 * i } # 1行で記述する場合
>> (1..5).each do |i| # 複数行で記述する場合(あくまで慣習で{}でも動作する)
?>   puts 2 * i
?> end
```

```ruby:ハッシュとシンボル
>> user = {} # {}は空のハッシュ
>> user["first_name"] = "Taro" # キーが"first_name"で値が"Taro"
>> user = { "first_name" => "Taro" } # 上と同値
>> user["first_name"] # アクセス方法は配列と似ている
=> "Taro"
>> user = { :name => "Taro" } # シンボル(:name等)をキーとして使用することが多い
>> user = { name: "Taro" } # 上と同値、Ruby 1.9からの新しい記法
>> user[:name]
=> "Taro"
>> user[:password]
=> nil # 未定義のハッシュ値はnil
```

```ruby:Rubyにおけるクラス
>> class String # Ruby組み込みの基本クラスを拡張することができる！
?>   def shuffle
?>     split("").shuffle.join
?>   end
?> end
```

ほとんどチュートリアル内の例題書き写しのようになってしまった点はお許しいただければと思います。主にRailsで使用するRubyの知識を急ぎ足で学習しました。配列操作・範囲オブジェクトの辺りが今まで馴染みのないところでした。
クラスの継承辺りは特に問題なく理解できましたが、基本クラスを直接拡張できるというのは面白いですね。

それでは、次回 第5章から再開したいと思います。