Railsチュートリアル(第4版)メモ 第4章

Railsチュートリアル(第4版)の個人メモ
気になった部分、忘れそうな部分を記述。

- Ruby 2.6.1
- Rails 5.1.6

4章ではRailsで使うRubyの基礎について学習。

# 4章 Rails風味のRuby
Viewでの処理をシンプル、かつDRYにするために、
Railsでは「ヘルパー」として自作の関数を指定できる。(カスタムヘルパー)

4章の中ではRailsに関係してRubyの以下要素にふれる。
モジュール、メソッド定義、任意のメソッド引数、コメント、ローカル変数の割り当て、論理値 (boolean)、制御フロー、文字列の結合、戻り値

## 4.1
### 4.1.1 カスタムヘルパー
#### カスタムヘルパー
関数のようなもの。下記で定義。
`app/helpers/application_helper.rb`

## 4.2 文字列とメソッド
以下、Railsコンソールを主に使用して学習。
Railsコンソールはirb(Interactive Ruby)の拡張であるので、irbの設定を先にしておく。

### 4.2.2 文字列
#### 文字列リテラル

```ruby
>> puts "foo"
foo
=> nil
```

putsするとfooが出力され、 **戻り値としてnil** が返る。

putsは行末に `¥n` 改行を含むので、
printで改行を含まず表示する。

#### ダブルクォート、シングルクォート
`'` では式展開 `#{foobar}` しない

### 4.2.3 オブジェクトとメッセージ受け渡し
Rubyでは文字列もnilも、全部オブジェクト。

オブジェクトはメッセージに応答する。

```ruby
>> "foobar".length
=> 6
```

`"foobar"` というオブジェクトは `length` メッセージに応答。
このメッセージは `メソッド` という。

#### nil
Rubyではオブジェクトそのものの論理値がfalseになるのは、falseかnilのみ。

オブジェクトを論理値に変換するときは`!!`(バンバン)する。二重否定。

```ruby
>> !!0 # true
```

0もnilではないのでtrue。
このundefinedとかnullとかNaNとか色々無いのはわかりやすいかもしれない。

nilというオブジェクトは `empty?` メソッドは持たないが、

```ruby
>> nil.empty?
# NoMethodError: undefined method `empty?' for nil:NilClass
```
`to_s` で文字列に変換すればいい。
(ただし、nil?でも判定できる)

```ruby
>> nil.to_s # ""
>> nil.to_s.empty? # true
>> nil.nil? # true
```

#### 後続if
英語のようにifを後ろに持っていき、処理をワンライナーにできる

```ruby
>> puts "x is not empty" if !x.empty?
```
`!` はやはり否定。 `if !` は `unless` でも可

### 4.2.4 メソッドの定義
#### メソッド
引数を省略するときカッコも省略可能

```ruby
def foobar(hoge = '')
end

p foobar #カッコも省略
```

#### 暗黙の戻り値
```ruby
def string_message(str = '')
  return "It's an empty string!" if str.empty?
  "The string is nonempty."
end

p string_message('noempty') # returnが無いけど3行目が返る。
```

### 4.2.5
#### モジュール

```ruby:/app/helpers/application_helper.rb
module ApplicationHelper
  def full_title(page_title = '')                  
    〜省略〜
  end
end
```

`module` は `def` で定義したメソッドをまとめるもので、`include` (mixed in) で呼び出す。
素のRubyではincludeで呼び出すが、Railsではincludeされるように組んであるのでノータッチ。

## 4.3 他のデータ構造
文字列、論理値(bool)以外
### 4.3.1 配列と範囲演算子
#### split
文字列を配列に。引数でデリミタの指定もできる

```ruby
>> "foo bar     baz".split # ["foo", "bar", "baz"]
>> "fooxbarxbaz".split('x') # ["foo", "bar", "baz"]
```

#### 配列
- 配列の書き方、指定

ゼロオリジン。

```ruby
>> a = [42, 8, 17]
>> a[0] # 42
```
指定の仕方

```ruby
>> a.first
>> a.second
>> a.last == a[-1] # true
```

- 追加(push)

`push(値)`、`<< 値` (複数可 `<< 値 << 値 ... `)
%wを使っても文字列の配列に変換できる

```ruby
>> %w[foo bar baz quux] # ["foo", "bar", "baz", "quux"]
```

- 連結(join)

`join(デリミタ)` デリミタなしで単純に連結

#### 範囲
```ruby
>> a = (0..9).to_a #  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 配列の取り出しなどにも
>> a[0..2] # [0, 1, 2]

# 3番目から最後、を明示的に
>> a[2..-1] == a[2..(a.length-1)] # true

# 後ろから7番目
>> a[-7]
```

### 4.3.2 ブロック
Rubyの慣例では
一行: 波括弧を使用 { }
複数行: do..end記法を使用

ブロックは、クロージャになっているとのこと。スコープに気をつける。

```ruby
# ブロック
p (1..5).each {|i| puts 2 * i}

# 複数行のブロック
p (1..5).each do |number|
  puts 2 * number
  puts '--'
end
```

ブロック内で宣言した引数に対してメソッドを当てる場合、アンパサンド( `&` ) で省略する記法が使える。(symbol-to-proc)

```ruby
>> %w[A B C].map { |char| char.downcase }
>> %w[A B C].map(&:downcase)
```

もともとRails独自の記法だったものが、Rubyのコア機能として採用されたんだとか。おもしろい。

#### 演習 ランダムに文字生成
使える文字を配列に並べて、シャッフルして、必要文字数分取り出し、となっていたが、
一応重複も許すように作成し直してみた

```ruby
# 演習3 ランダムで8文字生成
def random_subdomain(char_num = 0)
  base_strings = [('0'..'9'), ('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
  gen_word = []
  char_num.times {
    gen_word.push(base_strings.sample)
  }
  gen_word.join
end

puts random_subdomain(8)
```

### 4.3.3 ハッシュとシンボル
#### ハッシュ
PHPでいう連想配列は、ハッシュという
キーが数値になるものは、配列

ハッシュの並び順について、Ruby1.9までは保証していなかったが、今は定義やpushした順で変わらない。

注意として、空のハッシュの定義は `hoge = { ... }` 波括弧

#### シンボル
`:hogepiyo` これがシンボル
`user["name"]` 文字列型のように
`user[:name]` ハッシュのキーとして使える型。
ハッシュの定義には `=>` が使われるが、
シンボルに限ってはコロンを後ろに持ってくればok

```ruby
h1 = { :name => "Michael Hartl", :email => "michael@example.com" }
h2 = { name: "Michael Hartl", email: "michael@example.com" }
h1 == h2 # true
```

`each` を使った展開(PHPと比較)

```php:PHP
foreach($flash as $key => $value){
  echo "Key ${key} has value ${value}";
}
```

```ruby:Ruby
flash.each do |key, value|
  puts "Key #{key.inspect} has value #{value.inspect}"
end
```

#### inspect
`puts "hoge".inspect` で `"hoge"` が表示。
よく使うので省略があり、 `p "hoge"` でも同様の結果
PHPでいう `var_dump()` のような感じか

### 4.3.3 CSS、再び
css呼び出しの部分

```ruby:app/views/layouts/application.html.erb
stylesheet_link_tag 'application', media: 'all',
                    'data-turbolinks-track': 'reload'
```

上記は大分省略されているので明示的に書くと以下の様になる。

```ruby
stylesheet_link_tag('application', { media: 'all', 'data-turbolinks-track': 'reload' })
```

- 引数は丸括弧なしでも可。
- 引数の最後にハッシュが来る場合、波括弧を省略可
- Rubyはある程度自由に改行と空白を入れても、文脈で判断してくれる。  
  このため、改行で可読性を上げることも可

## 4.4 Rubyにおけるクラス
### 4.4.1 コンストラクタ
#### 値は全てオブジェクト
Rubyで扱う値はすべてオブジェクト(何らかのクラスに属する)

```ruby
"hogepiyo" == String.new("hogepiyo") # true
```

ダブルクォートで文字列を定義した際には、Stringクラスのインスタンスが生成されている。
なので、そのStringクラスに対応するメソッドが使えていた、ということ。

配列クラス( `Array.new(["hoge", "piyo"])` )や、ハッシュクラス( `Hash.new` )なども当然ある。

ハッシュクラスは `Hash.new("default")` でキーが存在しない場合の初期値を定義できる。
指定なし `Hash.new` ではnil

### 4.4.2 クラス継承
#### superclassメソッド
`HogepiyoClass.superclass` で
継承元のクラスを調べられる。

Stringなら、
String < Object < BasicObject
でBasicObjectから順々に継承されている。
値すべてがオブジェクト、という意味がわかった。

```ruby
class Word < String
  def palindrome?
    self == self.reverse
    # 実は右のselfも省略できるので、
    # self == reverse
    # でもよい。
  end
end

s = Word.new("level")
s.palindrome? # true
s.length # 5
# 適当にppとかで上記2点確認できる
```

### 4.4.5 ユーザークラス
#### インスタンス変数
`@` から始まる変数。
メソッドの内側で定義したローカル変数のスコープはメソッド内で閉じるが、
インスタンス変数はクラス内の別メソッドでも使える変数。