Ruby on Rails.学習3

#### 投稿目的
- 個人的な学習のために投稿しています。
- 暖かい目で閲覧していただけると幸いです。

## 文字列とメソッドなど

### Railsコンソール
- Rails consoleはirb(IRB: Interactive RuBy)とはRailsアプリケーションを対話的に操作するためのコマンドラインツールです、拡張して作られているため、Rubyの機能をすべて使うことができます。
- デフォルトでは、コンソールはdevelopment(開発)環境という、Railsによって定義された3種類の環境のうちの1つで起動します(他の2つはtest(テスト)環境とproduction(本番)環境です)。

### コメント
- コメントにするにはRubyでは#(「ハッシュマーク」、「オクトソープ」)と呼んだりします、行の終わりまでをコメントにすることができます。
- コンソールにコメントを記述することは普通はありません(コメントはスルーされます)。

```shell:ターミナル
$ rails console
irb(main)> 17 + 42 #整数の足し算
=> 59
```

### 文字列
- 文字列 (string) は、Webアプリケーションにおいておそらく最も重要なデータ構造です。

```shell:ターミナル
irb(main)> '' # 空の文字列
=> ""
irb(main)> 'foo' # 空ではない文字列
=> "foo"
irb(main)> 'foo' + 'bar' # 文字列結合
=> "foobar"
```

- 上記は文字列リテラルといいます、クォートで囲むことで文字列として扱うことができ + を利用することで結合することもできます。

#### 式展開
- 文字列を組み立てる他の方法に式展開というものが存在します、式展開とは #{} という特殊な構文を利用することで変数を展開することができます。

```shell:ターミナル
irb(main)> first_name = 'Michael' # 変数の代入
=> "Michael"
irb(main)> "#{first_name}Hartl" # 文字列の式展開
=> "MichaelHartl"
```

### 出力
- 文字を出力する場合はputs(put stringの略)を利用します、putsは自動的に末尾に\n(改行)を適用した状態になります。
- putsは副作用で文字を出力します、戻り値はnil(Rubyの特別な値で何もないという意味)になります。

```shell:ターミナル
irb(main)> puts 'foo' # 文字列を出力する
foo
=> nil # 気にしなくて問題ありません
```

#### print
- printもputs同様出力ためのものですが改行がありません。
- \n で改行することでputsと同じ振る舞いにすることができます。

```shell:ターミナル
irb(main)> print 'foo'
foo=> nil # 改行がされていない

irb(main)> print "foo\n" # \nで改行
foo
=> nil 
```

### シングルクォートとダブルクォートの違い
- シングルクォートは特殊文字などをそのまま出力することができる。
- 下記のように改行されずにそのまま表示されます式展開も同様です。

```shell:ターミナル
irb(main):023:0> print 'test\n' 
test\n=> nil # 改行がされていない
```

- ダブルクォートの場合はその逆で特殊文字を利用することができます。

```shell:ターミナル
irb(main)> print "foo\n" 
foo
=> nil 
```

## オブジェクトとメッセージ受け渡し
- オブジェクトはいついかなる場合でもメッセージに応答するものです。
- オブジェクトに渡されるメッセージは、一般にはメソッドと呼ばれます。
- メソッドの実体は、そのオブジェクト内で定義されたメソッドです

### 文字列の場合
- 文字列のようなオブジェクトの場合はlengthというメッセージに応答できますが返り値は文字列ではなく文字数を返します。

```shell:ターミナル
irb(main)> "foobar".length # 文字列に "length" というメッセージを送る
=> 6 # 文字数
```

- Rubyの文字列はempty?メソッドにも応答することができます。
- empty?メソッドは空かどうかを判定して、返り値を論理値(true、false)で返します。


```shell:ターミナル
irb(main)> 'fooder'.empty?
=> false
irb(main)> ''.empty?
=> true
```

### 論理値
- 論理値(true、false)とは処理の流れを変更するときなどに有用です。
- if文は論理値を利用して処理の分岐を定義することができます。

```ruby
s = 'foobar'

# 条件: s変数の中身が空なのか判定
if s.empty?
# 空の場合(true)の処理
  puts 'データが空です！'
else
# falseの場合の処理
  puts 'データが存在します！'
end

# 結果: データが存在します！
```

- 条件を複数にする場合はelsifを利用します。
- nil?メソッドは器も中身も何もないかを判定する。

```ruby
s = '';

# 条件1: 何もないかを判定
if s.nil?
# 何もない場合(true)の処理
  puts 'データがnilです！'
# 条件2: 中身が空の判定
elsif s.empty?
# 空の場合(true)の処理
  puts 'データがemptyです！'
else
# falseの場合の処理
  puts 'データが存在します！'
end

# 結果: データがemptyです！
```

- &&(and)や||(or)などの条件演算子を組み合わせることもできます。
- &&はかつ、||どちらかという意味です。
- 比較演算子なども利用できます。

```ruby
a = ''
b = 'Ruby'

if a.empty? && b.empty?
# 両方の条件が一致した場合(true)の処理
  puts 'どちらも空です！'
elsif a.empty? || b.empty?
# 片方の条件が一致している場合(true)の処理
  puts '片方だけ空です！'
else
# falseの場合の処理
  puts 'どちらもデータが存在します！'
end

# 結果: 片方だけ空です！
```

- Rubyではif文の記述の方法に後続ifというのが存在します。
- 条件が真(true)の場合のみ実行するコードを簡潔に記述することができます。
- unless(NOTの場合true)でも利用することができます。
 
```ruby
s = '';
puts 'データが空です！' if s.empty?

# 結果: データが空です！
 
s = 'Ruby';

puts 'データが存在します！' unless s.empty?

# 結果: データが存在します！
```

### オブジェクト
- 上記のように文字列はもちろんオブジェクトでありnilもオブジェクトです。
- オブジェクトを別のオブジェクトに型変換できるメソッドなども存在します
- to_sは文字列オブジェクトにto_iは整数に型を変更します。

```ruby
a = nil # a変数にnilを代入

a.to_s  # nilオブジェクトを文字列オブジェクトに変換

# 結果: ""
```


## Rails動機

- 下記のコードを見ていきます。

```erb:app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all',
                               'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application',
                               'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>
```

- Railsの組み込み関数 [stylesheet_link_tag] を利用しapplication.cssをすべてのメディアタイプを使えるようにしています。

```erb
stylesheet_link_tag(スタイルシートへのパス [, HTMLオプション])
```

### カスタムヘルパー
- RailsのView(ビュー)では膨大な数の組み込み関数が利用されていますが、新しく作成することもできます。
- Railsで新しく作成したメソッドをカスタムヘルパーと呼びます。

#### provide、yield
- layoutディレクトリのファイル内で下記の用に記述することで:title(シンボル)で関連付けされているprovideメソッドを呼び出すことができます。
- yield = 生み出す

```erb
<!-- application.html.erb内のコード -->
<%= yield(:title) %> | Ruby on Rails Tutorial Sample App

<!-- 例 -->
<%= yield(:title) %> (何々の)| タイトル名などと記述して呼び出せるようになる。
```

- provide = 供給 
- 各View(ビュー)のページにprovide関数を使ってViewからLayoutにデータを引き渡すことができます。
- :title(シンボル)で関連付けを行なっています。
- provideメソッドを定義しない場合は各ページごとに固定されているタイトルが表示されます。

```erb:View/erbファイル内
<% provide(:title, 'Home') %>
```

#### カスタムヘルパー定義
- もし、provideメソッドを定義しない場合はtitleタグないで定義されている | まで表示されてしまうのでfull_titleというカスタムヘルパーを作成します。

```erb:application_helper.rb
                <!-- 初期値は空 -->
 def full_title(page_title = '')
     <!-- 'Ruby on Rails Tutorial Sample App'を変数に代入 -->
    base_title = 'Ruby on Rails Tutorial Sample App'
    <!-- if文でpege_title変数が空なのかを判定 -->
    if page_title.empty?
        <!-- 空の場合(true)はbase_title変数のデータを表示 -->
      base_title
    else
        <!-- 空ではない場合(false)はpage_title変数と'|'とbase_title変数のデータを結合して表示 -->
      page_title + " | " + base_title
    end
  end
end
```
- 上記の用にカスタムヘルパーを定義することで下記のコードをシンプルかつ正しく表示することができます。

```erb
<!-- 修正前 -->
<title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>

<!-- 修正後 -->
<title><%= full_title(yield(:title)) %></title>
```

## module
- モジュールは、関連したメソッドをまとめる方法の１つで、includeメソッドを使ってモジュールを読み込むことができます。
- Rubyのコードを書くのであれば、モジュールを作成するたびに明示的にincludeメソッドで読み込んで利用します。
- Railsでは自動的にヘルパーモジュールを読み込んでくれるので、include行をわざわざ書く必要がありません。
- つまり下記で定義したfull_titleメソッドは自動的にすべてのビューで利用できるようになっているということです。

```ruby
module ApplicationHelper 

  def full_title(page_title = '')                 
    base_title = "Ruby on Rails Tutorial Sample App"  
    if page_title.empty?                         
      base_title                                 
    else 
      page_title + " | " + base_title             
    end
  end
  
end
```

## 配列
- 配列とは番号のついたデータのリストです。
- [] で配列にすることができ、最初のデータの番号は0から始まります
- splitメソッドを使うと、文字列を配列で得ることができます。

```ruby
irb(main)> 'red blue green'.split # 空白で区切る
=> ["red", "blue", "green"]

irb(main)> 'redablueagreen'.split('a') # 指定した文字で区切る
=> ["red", "blue", "green"]
```

### 配列の要素の取得
- 配列名に [] 番号をしているすことで取得することが可能です。

```ruby
irb(main)> a = [1, 10 ,100]

irb(main)> a[0] 
=> # 結果: 1
irb(main)> a[1] 
=> # 結果: 10
irb(main)> a[2] 
=># 結果: 100
```

- firstメソッドやlastメソッドでも取得できます。

```ruby
irb(main)> a = [1, 10 ,100]

irb(main)> a.first 
=> # 結果: 1
irb(main)> a.last 
=> # 結果: 100
```

- 配列も多数のメソッドを利用することができます。

```ruby
irb(main)> a = [1, 10 ,100]

irb(main)> a.length # 要素数を整数で返す
=> # 結果: 3
irb(main)> a.empty? # 配列が空かを確認
=> # false

irb(main)> a = [1, 10, 100, 5]
irb(main)> a.sort # 配列内の並び替え
=> # [1, 5, 10 ,100] 
```

- 上記3つのメソッドを実行しても配列中身は変わりません。
- 内容を変更する場合は破壊的メソッドを利用します名前の末尾に ！ を付けることで内容が変更されます。

```ruby
irb(main)> a = [1, 10, 100, 5]
irb(main)> a.sort! # 配列内の並び替え
=> # [1, 5, 10 ,100] 
```

- joinメソッド配列のデータを結合することができます。
- joinメソッドの引数に区切り文字を指定することができます。

```ruby
irb(main)> a = [1, 10, 100, 5]
irb(main)> a.join
=> #  1101005 

irb(main)> a.join(',')
=> # 1, 10, 100, 5 
```

### 範囲(range)
- 範囲指定をするこよが可能です。
- 範囲指定を配列で利用することもできます(to_aで配列に変換することもできます)。

```ruby
0..9 # 1~9を指定しています。

irb(main)> a = (0..9).to_a # 配列に変換
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main)> a[0..2] # 番号0~2のデータを取得
# 結果: [0, 1, 2]
```

- 番号は -1 で最後の配列を指定することもできます。

```ruby
irb(main)> a[2..-1]  # -1を使って選択
# 結果: [2, 3, 4, 5, 6, 7, 8, 9]
```

## ブロック
- {...}やdo~endなどをブロックといいます。
- 下記の用にブロック内に処理を記述します。
- || で囲まれているのは変数です。
- eachメソッドは1~5の数字を順番にnumber変数に代入を行い処理をする。

```ruby 
# do~endの場合
(1..5).each do |number| # 1代入 ⇨ 2代入 ⇨...
    puts 2 * number # 2 * 1 ⇨ 2 * 2 ⇨...
end

# 結果: 2 4 6 8 10

# {...} の場合
(1..5).each { |number| puts 2 * number }

# 結果: 2 4 6 8 10
```

- Ruby共通の慣習では短い行などの場合は {...} を利用し、長い行や複数行の場合はdo~endを利用します。

### ブロック使用例
- 変数を利用しない場合も存在します。

```ruby
# timesメソッドは指定された回数処理を繰り返す
3.times { puts 'おはよう'}

# 結果: おはよう　おはよう　おはよう

# mapメソッドは順番に処理を行いブロック内で返した値で配列を作成
(1..5).map { |number| number * 5 }

# 結果: [5, 10, 15, 20, 25]

array = ['a', 'b', 'c']

array.map { |alphabet| alphabet.upcase }

# 結果: ["A", "B", "C"]
```

- 下記の用に組み合わせることも可能です。

```ruby
('a'..'z').to_a.shuffle[0..7].join

# 上記の詳細が下記になります
('a'..'z').to_a # 英小文字を列挙した配列を作る
('a'..'z').to_a.shuffle # 配列のデータをシャッフル
('a'..'z').to_a.shuffle[0..7] # 配列の冒頭8つの要素を取り出す
('a'..'z').to_a.shuffle[0..7].join # 取り出した要素を結合して１つの文字列にする
```